Move from ACI to a generic ServiceId.
This commit is contained in:
parent
9f1deda220
commit
7ca2420287
110 changed files with 841 additions and 824 deletions
|
@ -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 {
|
defaultConfig {
|
||||||
versionCode canonicalVersionCode * postFixSize
|
versionCode canonicalVersionCode * postFixSize
|
||||||
versionName canonicalVersionName
|
versionName canonicalVersionName
|
||||||
|
@ -190,36 +232,6 @@ android {
|
||||||
testInstrumentationRunnerArguments clearPackageData: 'true'
|
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 {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
if (keystores['debug'] != null) {
|
if (keystores['debug'] != null) {
|
||||||
|
@ -371,19 +383,6 @@ android {
|
||||||
variant.setIgnore(true)
|
variant.setIgnore(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
|
||||||
checkReleaseBuilds false
|
|
||||||
abortOnError true
|
|
||||||
baseline file("lint-baseline.xml")
|
|
||||||
disable "LintError"
|
|
||||||
}
|
|
||||||
|
|
||||||
testOptions {
|
|
||||||
unitTests {
|
|
||||||
includeAndroidResources = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
@ -4,7 +4,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertFalse
|
import org.junit.Assert.assertFalse
|
||||||
import org.junit.Assert.assertNotEquals
|
import org.junit.Assert.assertNotEquals
|
||||||
import org.junit.Assert.assertNull
|
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
@ -30,8 +29,8 @@ class RecipientDatabaseTest {
|
||||||
|
|
||||||
private lateinit var recipientDatabase: RecipientDatabase
|
private lateinit var recipientDatabase: RecipientDatabase
|
||||||
|
|
||||||
private val localAci = ACI.from(UUID.randomUUID());
|
private val localAci = ACI.from(UUID.randomUUID())
|
||||||
private val localPni = PNI.from(UUID.randomUUID());
|
private val localPni = PNI.from(UUID.randomUUID())
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
|
@ -52,7 +51,7 @@ class RecipientDatabaseTest {
|
||||||
val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, null, true)
|
val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, null, true)
|
||||||
|
|
||||||
val recipient = Recipient.resolved(recipientId)
|
val recipient = Recipient.resolved(recipientId)
|
||||||
assertEquals(ACI_A, recipient.requireAci())
|
assertEquals(ACI_A, recipient.requireServiceId())
|
||||||
assertFalse(recipient.hasE164())
|
assertFalse(recipient.hasE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +61,7 @@ class RecipientDatabaseTest {
|
||||||
val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, null, false)
|
val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, null, false)
|
||||||
|
|
||||||
val recipient = Recipient.resolved(recipientId)
|
val recipient = Recipient.resolved(recipientId)
|
||||||
assertEquals(ACI_A, recipient.requireAci())
|
assertEquals(ACI_A, recipient.requireServiceId())
|
||||||
assertFalse(recipient.hasE164())
|
assertFalse(recipient.hasE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +72,7 @@ class RecipientDatabaseTest {
|
||||||
|
|
||||||
val recipient = Recipient.resolved(recipientId)
|
val recipient = Recipient.resolved(recipientId)
|
||||||
assertEquals(E164_A, recipient.requireE164())
|
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. */
|
/** 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)
|
val recipient = Recipient.resolved(recipientId)
|
||||||
assertEquals(E164_A, recipient.requireE164())
|
assertEquals(E164_A, recipient.requireE164())
|
||||||
assertFalse(recipient.hasAci())
|
assertFalse(recipient.hasServiceId())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** With high trust, you can associate an ACI-e164 pair. */
|
/** 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 recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
|
||||||
|
|
||||||
val recipient = Recipient.resolved(recipientId)
|
val recipient = Recipient.resolved(recipientId)
|
||||||
assertEquals(ACI_A, recipient.requireAci())
|
assertEquals(ACI_A, recipient.requireServiceId())
|
||||||
assertEquals(E164_A, recipient.requireE164())
|
assertEquals(E164_A, recipient.requireE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +101,7 @@ class RecipientDatabaseTest {
|
||||||
val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false)
|
val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false)
|
||||||
|
|
||||||
val recipient = Recipient.resolved(recipientId)
|
val recipient = Recipient.resolved(recipientId)
|
||||||
assertEquals(ACI_A, recipient.requireAci())
|
assertEquals(ACI_A, recipient.requireServiceId())
|
||||||
assertFalse(recipient.hasE164())
|
assertFalse(recipient.hasE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,26 +112,26 @@ class RecipientDatabaseTest {
|
||||||
/** With high trust, you can associate an e164 with an existing ACI. */
|
/** With high trust, you can associate an e164 with an existing ACI. */
|
||||||
@Test
|
@Test
|
||||||
fun getAndPossiblyMerge_aciMapsToExistingUserButE164DoesNot_aciAndE164_highTrust() {
|
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)
|
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true)
|
||||||
assertEquals(existingId, retrievedId)
|
assertEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, retrievedRecipient.requireE164())
|
assertEquals(E164_A, retrievedRecipient.requireE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** With low trust, you cannot associate an ACI-e164 pair, and therefore cannot store the e164. */
|
/** With low trust, you cannot associate an ACI-e164 pair, and therefore cannot store the e164. */
|
||||||
@Test
|
@Test
|
||||||
fun getAndPossiblyMerge_aciMapsToExistingUserButE164DoesNot_aciAndE164_lowTrust() {
|
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)
|
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false)
|
||||||
assertEquals(existingId, retrievedId)
|
assertEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertFalse(retrievedRecipient.hasE164())
|
assertFalse(retrievedRecipient.hasE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +144,7 @@ class RecipientDatabaseTest {
|
||||||
assertEquals(existingId, retrievedId)
|
assertEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_B, retrievedRecipient.requireE164())
|
assertEquals(E164_B, retrievedRecipient.requireE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +157,7 @@ class RecipientDatabaseTest {
|
||||||
assertEquals(existingId, retrievedId)
|
assertEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, retrievedRecipient.requireE164())
|
assertEquals(E164_A, retrievedRecipient.requireE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +174,7 @@ class RecipientDatabaseTest {
|
||||||
assertEquals(existingId, retrievedId)
|
assertEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, retrievedRecipient.requireE164())
|
assertEquals(E164_A, retrievedRecipient.requireE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,12 +187,12 @@ class RecipientDatabaseTest {
|
||||||
assertNotEquals(existingId, retrievedId)
|
assertNotEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertFalse(retrievedRecipient.hasE164())
|
assertFalse(retrievedRecipient.hasE164())
|
||||||
|
|
||||||
val existingRecipient = Recipient.resolved(existingId)
|
val existingRecipient = Recipient.resolved(existingId)
|
||||||
assertEquals(E164_A, existingRecipient.requireE164())
|
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. */
|
/** 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)
|
assertNotEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_B, retrievedRecipient.requireAci())
|
assertEquals(ACI_B, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, retrievedRecipient.requireE164())
|
assertEquals(E164_A, retrievedRecipient.requireE164())
|
||||||
assertEquals(PNI_A, retrievedRecipient.pni.get())
|
|
||||||
|
|
||||||
val existingRecipient = Recipient.resolved(existingId)
|
val existingRecipient = Recipient.resolved(existingId)
|
||||||
assertEquals(ACI_A, existingRecipient.requireAci())
|
assertEquals(ACI_A, existingRecipient.requireServiceId())
|
||||||
assertFalse(existingRecipient.hasE164())
|
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. */
|
/** 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)
|
assertNotEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_B, retrievedRecipient.requireAci())
|
assertEquals(ACI_B, retrievedRecipient.requireServiceId())
|
||||||
assertFalse(retrievedRecipient.hasE164())
|
assertFalse(retrievedRecipient.hasE164())
|
||||||
|
|
||||||
val existingRecipient = Recipient.resolved(existingId)
|
val existingRecipient = Recipient.resolved(existingId)
|
||||||
assertEquals(ACI_A, existingRecipient.requireAci())
|
assertEquals(ACI_A, existingRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, existingRecipient.requireE164())
|
assertEquals(E164_A, existingRecipient.requireE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,11 +246,11 @@ class RecipientDatabaseTest {
|
||||||
assertNotEquals(existingId, retrievedId)
|
assertNotEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_B, retrievedRecipient.requireAci())
|
assertEquals(ACI_B, retrievedRecipient.requireServiceId())
|
||||||
assertFalse(retrievedRecipient.hasE164())
|
assertFalse(retrievedRecipient.hasE164())
|
||||||
|
|
||||||
val existingRecipient = Recipient.resolved(existingId)
|
val existingRecipient = Recipient.resolved(existingId)
|
||||||
assertEquals(ACI_A, existingRecipient.requireAci())
|
assertEquals(ACI_A, existingRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, existingRecipient.requireE164())
|
assertEquals(E164_A, existingRecipient.requireE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +267,7 @@ class RecipientDatabaseTest {
|
||||||
assertEquals(existingId, retrievedId)
|
assertEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, retrievedRecipient.requireE164())
|
assertEquals(E164_A, retrievedRecipient.requireE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +284,7 @@ class RecipientDatabaseTest {
|
||||||
assertEquals(existingAciId, retrievedId)
|
assertEquals(existingAciId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, retrievedRecipient.requireE164())
|
assertEquals(E164_A, retrievedRecipient.requireE164())
|
||||||
|
|
||||||
val existingE164Recipient = Recipient.resolved(existingE164Id)
|
val existingE164Recipient = Recipient.resolved(existingE164Id)
|
||||||
|
@ -310,7 +307,7 @@ class RecipientDatabaseTest {
|
||||||
assertEquals(existingAciId, retrievedId)
|
assertEquals(existingAciId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, retrievedRecipient.requireE164())
|
assertEquals(E164_A, retrievedRecipient.requireE164())
|
||||||
|
|
||||||
val existingE164Recipient = Recipient.resolved(existingE164Id)
|
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. */
|
/** Low trust means you can’t merge. If you’re retrieving a user from the table with this data, prefer the ACI one. */
|
||||||
@Test
|
@Test
|
||||||
fun getAndPossiblyMerge_bothAciAndE164MapToExistingUser_aciAndE164_lowTrust() {
|
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 existingE164Id: RecipientId = recipientDatabase.getOrInsertFromE164(E164_A)
|
||||||
|
|
||||||
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false)
|
val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false)
|
||||||
assertEquals(existingAciId, retrievedId)
|
assertEquals(existingAciId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertFalse(retrievedRecipient.hasE164())
|
assertFalse(retrievedRecipient.hasE164())
|
||||||
|
|
||||||
val existingE164Recipient = Recipient.resolved(existingE164Id)
|
val existingE164Recipient = Recipient.resolved(existingE164Id)
|
||||||
assertEquals(E164_A, existingE164Recipient.requireE164())
|
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. */
|
/** 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)
|
assertEquals(existingId1, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, retrievedRecipient.requireE164())
|
assertEquals(E164_A, retrievedRecipient.requireE164())
|
||||||
|
|
||||||
val existingRecipient2 = Recipient.resolved(existingId2)
|
val existingRecipient2 = Recipient.resolved(existingId2)
|
||||||
assertEquals(ACI_B, existingRecipient2.requireAci())
|
assertEquals(ACI_B, existingRecipient2.requireServiceId())
|
||||||
assertFalse(existingRecipient2.hasE164())
|
assertFalse(existingRecipient2.hasE164())
|
||||||
|
|
||||||
assert(changeNumberListener.numberChangeWasEnqueued)
|
assert(changeNumberListener.numberChangeWasEnqueued)
|
||||||
|
@ -371,11 +368,11 @@ class RecipientDatabaseTest {
|
||||||
assertEquals(existingId1, retrievedId)
|
assertEquals(existingId1, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_B, retrievedRecipient.requireE164())
|
assertEquals(E164_B, retrievedRecipient.requireE164())
|
||||||
|
|
||||||
val existingRecipient2 = Recipient.resolved(existingId2)
|
val existingRecipient2 = Recipient.resolved(existingId2)
|
||||||
assertEquals(ACI_B, existingRecipient2.requireAci())
|
assertEquals(ACI_B, existingRecipient2.requireServiceId())
|
||||||
assertEquals(E164_A, existingRecipient2.requireE164())
|
assertEquals(E164_A, existingRecipient2.requireE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +389,7 @@ class RecipientDatabaseTest {
|
||||||
assertEquals(existingId1, retrievedId)
|
assertEquals(existingId1, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, retrievedRecipient.requireE164())
|
assertEquals(E164_A, retrievedRecipient.requireE164())
|
||||||
|
|
||||||
assertFalse(recipientDatabase.getByE164(E164_B).isPresent)
|
assertFalse(recipientDatabase.getByE164(E164_B).isPresent)
|
||||||
|
@ -417,11 +414,11 @@ class RecipientDatabaseTest {
|
||||||
assertEquals(existingId2, retrievedId)
|
assertEquals(existingId2, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertFalse(retrievedRecipient.hasE164())
|
assertFalse(retrievedRecipient.hasE164())
|
||||||
|
|
||||||
val recipientWithId1 = Recipient.resolved(existingId1)
|
val recipientWithId1 = Recipient.resolved(existingId1)
|
||||||
assertEquals(ACI_B, recipientWithId1.requireAci())
|
assertEquals(ACI_B, recipientWithId1.requireServiceId())
|
||||||
assertEquals(E164_A, recipientWithId1.requireE164())
|
assertEquals(E164_A, recipientWithId1.requireE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +437,7 @@ class RecipientDatabaseTest {
|
||||||
assertEquals(existingId, retrievedId)
|
assertEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, retrievedRecipient.requireE164())
|
assertEquals(E164_A, retrievedRecipient.requireE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,7 +456,7 @@ class RecipientDatabaseTest {
|
||||||
assertEquals(existingId, retrievedId)
|
assertEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_B, retrievedRecipient.requireE164())
|
assertEquals(E164_B, retrievedRecipient.requireE164())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +472,7 @@ class RecipientDatabaseTest {
|
||||||
assertEquals(existingId, retrievedId)
|
assertEquals(existingId, retrievedId)
|
||||||
|
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_B, retrievedRecipient.requireE164())
|
assertEquals(E164_B, retrievedRecipient.requireE164())
|
||||||
|
|
||||||
changeNumberListener.waitForJobManager()
|
changeNumberListener.waitForJobManager()
|
||||||
|
@ -506,18 +503,18 @@ class RecipientDatabaseTest {
|
||||||
@Test
|
@Test
|
||||||
fun createByUuidSanityCheck() {
|
fun createByUuidSanityCheck() {
|
||||||
// GIVEN one recipient
|
// GIVEN one recipient
|
||||||
val recipientId: RecipientId = recipientDatabase.getOrInsertFromAci(ACI_A)
|
val recipientId: RecipientId = recipientDatabase.getOrInsertFromServiceId(ACI_A)
|
||||||
|
|
||||||
// WHEN I retrieve one by UUID
|
// WHEN I retrieve one by UUID
|
||||||
val possible: Optional<RecipientId> = recipientDatabase.getByAci(ACI_A)
|
val possible: Optional<RecipientId> = recipientDatabase.getByServiceId(ACI_A)
|
||||||
|
|
||||||
// THEN I get it back, and it has the properties I expect
|
// THEN I get it back, and it has the properties I expect
|
||||||
assertTrue(possible.isPresent)
|
assertTrue(possible.isPresent)
|
||||||
assertEquals(recipientId, possible.get())
|
assertEquals(recipientId, possible.get())
|
||||||
|
|
||||||
val recipient = Recipient.resolved(recipientId)
|
val recipient = Recipient.resolved(recipientId)
|
||||||
assertTrue(recipient.aci.isPresent)
|
assertTrue(recipient.serviceId.isPresent)
|
||||||
assertEquals(ACI_A, recipient.aci.get())
|
assertEquals(ACI_A, recipient.serviceId.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException::class)
|
@Test(expected = IllegalArgumentException::class)
|
||||||
|
|
|
@ -53,8 +53,8 @@ class RecipientDatabaseTest_merges {
|
||||||
private lateinit var reactionDatabase: ReactionDatabase
|
private lateinit var reactionDatabase: ReactionDatabase
|
||||||
private lateinit var notificationProfileDatabase: NotificationProfileDatabase
|
private lateinit var notificationProfileDatabase: NotificationProfileDatabase
|
||||||
|
|
||||||
private val localAci = ACI.from(UUID.randomUUID());
|
private val localAci = ACI.from(UUID.randomUUID())
|
||||||
private val localPni = PNI.from(UUID.randomUUID());
|
private val localPni = PNI.from(UUID.randomUUID())
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
|
@ -80,9 +80,9 @@ class RecipientDatabaseTest_merges {
|
||||||
@Test
|
@Test
|
||||||
fun getAndPossiblyMerge_general() {
|
fun getAndPossiblyMerge_general() {
|
||||||
// Setup
|
// Setup
|
||||||
val recipientIdAci: RecipientId = recipientDatabase.getOrInsertFromAci(ACI_A)
|
val recipientIdAci: RecipientId = recipientDatabase.getOrInsertFromServiceId(ACI_A)
|
||||||
val recipientIdE164: RecipientId = recipientDatabase.getOrInsertFromE164(E164_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 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
|
val smsId2: Long = smsDatabase.insertMessageInbox(smsMessage(sender = recipientIdE164, time = 1, body = "1")).get().messageId
|
||||||
|
@ -127,7 +127,7 @@ class RecipientDatabaseTest_merges {
|
||||||
|
|
||||||
// Recipient validation
|
// Recipient validation
|
||||||
val retrievedRecipient = Recipient.resolved(retrievedId)
|
val retrievedRecipient = Recipient.resolved(retrievedId)
|
||||||
assertEquals(ACI_A, retrievedRecipient.requireAci())
|
assertEquals(ACI_A, retrievedRecipient.requireServiceId())
|
||||||
assertEquals(E164_A, retrievedRecipient.requireE164())
|
assertEquals(E164_A, retrievedRecipient.requireE164())
|
||||||
|
|
||||||
val existingE164Recipient = Recipient.resolved(recipientIdE164)
|
val existingE164Recipient = Recipient.resolved(recipientIdE164)
|
||||||
|
|
|
@ -571,11 +571,11 @@ public final class ContactSelectionListFragment extends LoggingFragment
|
||||||
AlertDialog loadingDialog = SimpleProgressDialog.show(requireContext());
|
AlertDialog loadingDialog = SimpleProgressDialog.show(requireContext());
|
||||||
|
|
||||||
SimpleTask.run(getViewLifecycleOwner().getLifecycle(), () -> {
|
SimpleTask.run(getViewLifecycleOwner().getLifecycle(), () -> {
|
||||||
return UsernameUtil.fetchAciForUsername(requireContext(), contact.getNumber());
|
return UsernameUtil.fetchAciForUsername(contact.getNumber());
|
||||||
}, uuid -> {
|
}, uuid -> {
|
||||||
loadingDialog.dismiss();
|
loadingDialog.dismiss();
|
||||||
if (uuid.isPresent()) {
|
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());
|
SelectedContact selected = SelectedContact.forUsername(recipient.getId(), contact.getNumber());
|
||||||
|
|
||||||
if (onContactSelectedListener != null) {
|
if (onContactSelectedListener != null) {
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class NewConversationActivity extends ContactSelectionActivity
|
||||||
SimpleTask.run(getLifecycle(), () -> {
|
SimpleTask.run(getLifecycle(), () -> {
|
||||||
Recipient resolved = Recipient.external(this, number);
|
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.");
|
Log.i(TAG, "[onContactSelected] Not registered or no UUID. Doing a directory refresh.");
|
||||||
try {
|
try {
|
||||||
DirectoryHelper.refreshDirectoryFor(this, resolved, false);
|
DirectoryHelper.refreshDirectoryFor(this, resolved, false);
|
||||||
|
|
|
@ -26,8 +26,7 @@ import org.thoughtcrime.securesms.util.Hex
|
||||||
import org.thoughtcrime.securesms.util.SpanUtil
|
import org.thoughtcrime.securesms.util.SpanUtil
|
||||||
import org.thoughtcrime.securesms.util.Util
|
import org.thoughtcrime.securesms.util.Util
|
||||||
import org.thoughtcrime.securesms.util.livedata.Store
|
import org.thoughtcrime.securesms.util.livedata.Store
|
||||||
import org.whispersystems.signalservice.api.push.ACI
|
import org.whispersystems.signalservice.api.push.ServiceId
|
||||||
import org.whispersystems.signalservice.api.push.PNI
|
|
||||||
import java.util.Objects
|
import java.util.Objects
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,18 +60,11 @@ class InternalConversationSettingsFragment : DSLSettingsFragment(
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!recipient.isGroup) {
|
if (!recipient.isGroup) {
|
||||||
val aci = recipient.aci.transform(ACI::toString).or("null")
|
val serviceId = recipient.serviceId.transform(ServiceId::toString).or("null")
|
||||||
longClickPref(
|
longClickPref(
|
||||||
title = DSLSettingsText.from("ACI"),
|
title = DSLSettingsText.from("ServiceId"),
|
||||||
summary = DSLSettingsText.from(aci),
|
summary = DSLSettingsText.from(serviceId),
|
||||||
onLongClick = { copyToClipboard(aci) }
|
onLongClick = { copyToClipboard(serviceId) }
|
||||||
)
|
|
||||||
|
|
||||||
val pni = recipient.pni.transform(PNI::toString).or("null")
|
|
||||||
longClickPref(
|
|
||||||
title = DSLSettingsText.from("PNI"),
|
|
||||||
summary = DSLSettingsText.from(pni),
|
|
||||||
onLongClick = { copyToClipboard(pni) }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,17 +145,8 @@ class InternalConversationSettingsFragment : DSLSettingsFragment(
|
||||||
.setTitle("Are you sure?")
|
.setTitle("Are you sure?")
|
||||||
.setNegativeButton(android.R.string.cancel) { d, _ -> d.dismiss() }
|
.setNegativeButton(android.R.string.cancel) { d, _ -> d.dismiss() }
|
||||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
if (recipient.hasAci()) {
|
if (recipient.hasServiceId()) {
|
||||||
SignalDatabase.sessions.deleteAllFor(accountId = Recipient.self().requireAci(), addressName = recipient.requireAci().toString())
|
SignalDatabase.sessions.deleteAllFor(serviceId = SignalStore.account().requireAci(), addressName = recipient.requireServiceId().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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
|
|
|
@ -127,10 +127,10 @@ data class CallParticipantsState(
|
||||||
fun getIncomingRingingGroupDescription(context: Context): String? {
|
fun getIncomingRingingGroupDescription(context: Context): String? {
|
||||||
if (callState == WebRtcViewModel.State.CALL_INCOMING &&
|
if (callState == WebRtcViewModel.State.CALL_INCOMING &&
|
||||||
groupCallState == WebRtcViewModel.GroupCallState.RINGING &&
|
groupCallState == WebRtcViewModel.GroupCallState.RINGING &&
|
||||||
ringerRecipient.hasAci()
|
ringerRecipient.hasServiceId()
|
||||||
) {
|
) {
|
||||||
val ringerName = ringerRecipient.getShortDisplayName(context)
|
val ringerName = ringerRecipient.getShortDisplayName(context)
|
||||||
val membersWithoutYouOrRinger: List<GroupMemberEntry.FullMember> = groupMembers.filterNot { it.member.isSelf || ringerRecipient.requireAci() == it.member.aci.orNull() }
|
val membersWithoutYouOrRinger: List<GroupMemberEntry.FullMember> = groupMembers.filterNot { it.member.isSelf || ringerRecipient.requireServiceId() == it.member.serviceId.orNull() }
|
||||||
|
|
||||||
return when (membersWithoutYouOrRinger.size) {
|
return when (membersWithoutYouOrRinger.size) {
|
||||||
0 -> context.getString(R.string.WebRtcCallView__s_is_calling_you, ringerName)
|
0 -> context.getString(R.string.WebRtcCallView__s_is_calling_you, ringerName)
|
||||||
|
|
|
@ -112,9 +112,9 @@ public class DirectoryHelper {
|
||||||
RecipientDatabase recipientDatabase = SignalDatabase.recipients();
|
RecipientDatabase recipientDatabase = SignalDatabase.recipients();
|
||||||
|
|
||||||
for (Recipient recipient : recipients) {
|
for (Recipient recipient : recipients) {
|
||||||
if (recipient.hasAci() && !recipient.hasE164()) {
|
if (recipient.hasServiceId() && !recipient.hasE164()) {
|
||||||
if (ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(recipient.requireAci())) {
|
if (ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(recipient.requireServiceId())) {
|
||||||
recipientDatabase.markRegistered(recipient.getId(), recipient.requireAci());
|
recipientDatabase.markRegistered(recipient.getId(), recipient.requireServiceId());
|
||||||
} else {
|
} else {
|
||||||
recipientDatabase.markUnregistered(recipient.getId());
|
recipientDatabase.markUnregistered(recipient.getId());
|
||||||
}
|
}
|
||||||
|
@ -136,11 +136,11 @@ public class DirectoryHelper {
|
||||||
RegisteredState originalRegisteredState = recipient.resolve().getRegistered();
|
RegisteredState originalRegisteredState = recipient.resolve().getRegistered();
|
||||||
RegisteredState newRegisteredState;
|
RegisteredState newRegisteredState;
|
||||||
|
|
||||||
if (recipient.hasAci() && !recipient.hasE164()) {
|
if (recipient.hasServiceId() && !recipient.hasE164()) {
|
||||||
boolean isRegistered = ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(recipient.requireAci());
|
boolean isRegistered = ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(recipient.requireServiceId());
|
||||||
stopwatch.split("aci-network");
|
stopwatch.split("aci-network");
|
||||||
if (isRegistered) {
|
if (isRegistered) {
|
||||||
boolean idChanged = recipientDatabase.markRegistered(recipient.getId(), recipient.requireAci());
|
boolean idChanged = recipientDatabase.markRegistered(recipient.getId(), recipient.requireServiceId());
|
||||||
if (idChanged) {
|
if (idChanged) {
|
||||||
Log.w(TAG, "ID changed during refresh by UUID.");
|
Log.w(TAG, "ID changed during refresh by UUID.");
|
||||||
}
|
}
|
||||||
|
@ -173,14 +173,14 @@ public class DirectoryHelper {
|
||||||
if (aci != null) {
|
if (aci != null) {
|
||||||
boolean idChanged = recipientDatabase.markRegistered(recipient.getId(), aci);
|
boolean idChanged = recipientDatabase.markRegistered(recipient.getId(), aci);
|
||||||
if (idChanged) {
|
if (idChanged) {
|
||||||
recipient = Recipient.resolved(recipientDatabase.getByAci(aci).get());
|
recipient = Recipient.resolved(recipientDatabase.getByServiceId(aci).get());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Registered number set had a null ACI!");
|
Log.w(TAG, "Registered number set had a null ACI!");
|
||||||
}
|
}
|
||||||
} else if (recipient.hasAci() && recipient.isRegistered() && hasCommunicatedWith(recipient)) {
|
} else if (recipient.hasServiceId() && recipient.isRegistered() && hasCommunicatedWith(recipient)) {
|
||||||
if (ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(recipient.requireAci())) {
|
if (ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(recipient.requireServiceId())) {
|
||||||
recipientDatabase.markRegistered(recipient.getId(), recipient.requireAci());
|
recipientDatabase.markRegistered(recipient.getId(), recipient.requireServiceId());
|
||||||
} else {
|
} else {
|
||||||
recipientDatabase.markUnregistered(recipient.getId());
|
recipientDatabase.markUnregistered(recipient.getId());
|
||||||
}
|
}
|
||||||
|
@ -485,7 +485,13 @@ public class DirectoryHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasSession(@NonNull RecipientId id) {
|
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) ||
|
return ApplicationDependencies.getProtocolStore().aci().containsSession(protocolAddress) ||
|
||||||
ApplicationDependencies.getProtocolStore().pni().containsSession(protocolAddress);
|
ApplicationDependencies.getProtocolStore().pni().containsSession(protocolAddress);
|
||||||
|
@ -511,7 +517,7 @@ public class DirectoryHelper {
|
||||||
List<Recipient> possiblyUnlisted = Stream.of(inactiveIds)
|
List<Recipient> possiblyUnlisted = Stream.of(inactiveIds)
|
||||||
.map(Recipient::resolved)
|
.map(Recipient::resolved)
|
||||||
.filter(Recipient::isRegistered)
|
.filter(Recipient::isRegistered)
|
||||||
.filter(Recipient::hasAci)
|
.filter(Recipient::hasServiceId)
|
||||||
.filter(DirectoryHelper::hasCommunicatedWith)
|
.filter(DirectoryHelper::hasCommunicatedWith)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
@ -546,12 +552,9 @@ public class DirectoryHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasCommunicatedWith(@NonNull Recipient recipient) {
|
private static boolean hasCommunicatedWith(@NonNull Recipient recipient) {
|
||||||
ACI localAci = Recipient.self().requireAci();
|
ACI localAci = SignalStore.account().requireAci();
|
||||||
|
|
||||||
return SignalDatabase.threads().hasThread(recipient.getId()) ||
|
return SignalDatabase.threads().hasThread(recipient.getId()) || (recipient.hasServiceId() && SignalDatabase.sessions().hasSessionFor(localAci, recipient.requireServiceId().toString()));
|
||||||
(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()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class DirectoryResult {
|
static class DirectoryResult {
|
||||||
|
|
|
@ -1554,14 +1554,14 @@ public class ConversationParentFragment extends Fragment
|
||||||
smsEnabled = false;
|
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);
|
sendButton.disableTransport(Type.TEXTSECURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recipient.get().isPushGroup() && recipient.get().isForceSmsSelection() && smsEnabled) {
|
if (!recipient.get().isPushGroup() && recipient.get().isForceSmsSelection() && smsEnabled) {
|
||||||
sendButton.setDefaultTransport(Type.SMS);
|
sendButton.setDefaultTransport(Type.SMS);
|
||||||
} else {
|
} 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);
|
sendButton.setDefaultTransport(Type.TEXTSECURE);
|
||||||
} else {
|
} else {
|
||||||
sendButton.setDefaultTransport(Type.SMS);
|
sendButton.setDefaultTransport(Type.SMS);
|
||||||
|
@ -3013,7 +3013,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
return new SettableFuture<>(null);
|
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;
|
final long thread = this.threadId;
|
||||||
|
|
||||||
if (sendPush) {
|
if (sendPush) {
|
||||||
|
@ -3076,7 +3076,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
final long thread = this.threadId;
|
final long thread = this.threadId;
|
||||||
final Context context = requireContext().getApplicationContext();
|
final Context context = requireContext().getApplicationContext();
|
||||||
final String messageBody = getMessage();
|
final String messageBody = getMessage();
|
||||||
final boolean sendPush = (isSecureText && !forceSms) || recipient.get().isAciOnly();
|
final boolean sendPush = (isSecureText && !forceSms) || recipient.get().isServiceIdOnly();
|
||||||
|
|
||||||
OutgoingTextMessage message;
|
OutgoingTextMessage message;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import android.text.SpannableString;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewTreeObserver;
|
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
@ -52,6 +51,7 @@ import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
|
||||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
|
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ACI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -351,12 +351,12 @@ public final class ConversationUpdateItem extends FrameLayout
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (conversationMessage.getMessageRecord().isGroupCall()) {
|
} else if (conversationMessage.getMessageRecord().isGroupCall()) {
|
||||||
UpdateDescription updateDescription = MessageRecord.getGroupCallUpdateDescription(getContext(), conversationMessage.getMessageRecord().getBody(), true);
|
UpdateDescription updateDescription = MessageRecord.getGroupCallUpdateDescription(getContext(), conversationMessage.getMessageRecord().getBody(), true);
|
||||||
Collection<ACI> acis = updateDescription.getMentioned();
|
Collection<ServiceId> acis = updateDescription.getMentioned();
|
||||||
|
|
||||||
int text = 0;
|
int text = 0;
|
||||||
if (Util.hasItems(acis)) {
|
if (Util.hasItems(acis)) {
|
||||||
if (acis.contains(Recipient.self().requireAci())) {
|
if (acis.contains(Recipient.self().requireServiceId())) {
|
||||||
text = R.string.ConversationUpdateItem_return_to_call;
|
text = R.string.ConversationUpdateItem_return_to_call;
|
||||||
} else if (GroupCallUpdateDetailsUtil.parse(conversationMessage.getMessageRecord().getBody()).getIsCallFull()) {
|
} else if (GroupCallUpdateDetailsUtil.parse(conversationMessage.getMessageRecord().getBody()).getIsCallFull()) {
|
||||||
text = R.string.ConversationUpdateItem_call_is_full;
|
text = R.string.ConversationUpdateItem_call_is_full;
|
||||||
|
|
|
@ -126,7 +126,7 @@ final class SafetyNumberChangeRepository {
|
||||||
|
|
||||||
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||||
for (ChangedRecipient changedRecipient : changedRecipients) {
|
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());
|
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);
|
SignalIdentityKeyStore.SaveResult result = ApplicationDependencies.getProtocolStore().aci().identities().saveIdentity(mismatchAddress, changedRecipient.getIdentityRecord().getIdentityKey(), true);
|
||||||
|
|
|
@ -22,7 +22,7 @@ public final class SenderKeyUtil {
|
||||||
*/
|
*/
|
||||||
public static void rotateOurKey(@NonNull Context context, @NonNull DistributionId distributionId) {
|
public static void rotateOurKey(@NonNull Context context, @NonNull DistributionId distributionId) {
|
||||||
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
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);
|
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.
|
* 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) {
|
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);
|
return SignalDatabase.senderKeys().getCreatedTime(address, distributionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||||
import org.whispersystems.libsignal.state.IdentityKeyStore;
|
import org.whispersystems.libsignal.state.IdentityKeyStore;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -110,8 +111,8 @@ public class SignalBaseIdentityKeyStore {
|
||||||
boolean nonBlockingApproval)
|
boolean nonBlockingApproval)
|
||||||
{
|
{
|
||||||
Recipient recipient = Recipient.resolved(recipientId);
|
Recipient recipient = Recipient.resolved(recipientId);
|
||||||
if (recipient.hasServiceIdentifier()) {
|
if (recipient.hasServiceId()) {
|
||||||
cache.save(recipient.requireServiceId(), recipientId, identityKey, verifiedStatus, firstUse, timestamp, nonBlockingApproval);
|
cache.save(recipient.requireServiceId().toString(), recipientId, identityKey, verifiedStatus, firstUse, timestamp, nonBlockingApproval);
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "[saveIdentity] No serviceId for " + recipient.getId());
|
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) {
|
public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, IdentityKeyStore.Direction direction) {
|
||||||
Recipient self = Recipient.self();
|
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());
|
address.getName().equals(self.requireE164());
|
||||||
|
|
||||||
if (isSelf) {
|
if (isSelf) {
|
||||||
|
@ -150,19 +151,20 @@ public class SignalBaseIdentityKeyStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull Optional<IdentityRecord> getIdentityRecord(@NonNull Recipient recipient) {
|
public @NonNull Optional<IdentityRecord> getIdentityRecord(@NonNull Recipient recipient) {
|
||||||
if (recipient.hasServiceIdentifier()) {
|
if (recipient.hasServiceId()) {
|
||||||
IdentityStoreRecord record = cache.get(recipient.requireServiceId());
|
IdentityStoreRecord record = cache.get(recipient.requireServiceId().toString());
|
||||||
return Optional.fromNullable(record).transform(r -> r.toIdentityRecord(recipient.getId()));
|
return Optional.fromNullable(record).transform(r -> r.toIdentityRecord(recipient.getId()));
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "[getIdentityRecord] No serviceId for " + recipient.getId());
|
Log.w(TAG, "[getIdentityRecord] No ServiceId for " + recipient.getId());
|
||||||
return Optional.absent();
|
return Optional.absent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull IdentityRecordList getIdentityRecords(@NonNull List<Recipient> recipients) {
|
public @NonNull IdentityRecordList getIdentityRecords(@NonNull List<Recipient> recipients) {
|
||||||
List<String> addressNames = recipients.stream()
|
List<String> addressNames = recipients.stream()
|
||||||
.filter(Recipient::hasServiceIdentifier)
|
.filter(Recipient::hasServiceId)
|
||||||
.map(Recipient::requireServiceId)
|
.map(Recipient::requireServiceId)
|
||||||
|
.map(ServiceId::toString)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
if (addressNames.isEmpty()) {
|
if (addressNames.isEmpty()) {
|
||||||
|
@ -172,8 +174,8 @@ public class SignalBaseIdentityKeyStore {
|
||||||
List<IdentityRecord> records = new ArrayList<>(recipients.size());
|
List<IdentityRecord> records = new ArrayList<>(recipients.size());
|
||||||
|
|
||||||
for (Recipient recipient : recipients) {
|
for (Recipient recipient : recipients) {
|
||||||
if (recipient.hasServiceIdentifier()) {
|
if (recipient.hasServiceId()) {
|
||||||
IdentityStoreRecord record = cache.get(recipient.requireServiceId());
|
IdentityStoreRecord record = cache.get(recipient.requireServiceId().toString());
|
||||||
|
|
||||||
if (record != null) {
|
if (record != null) {
|
||||||
records.add(record.toIdentityRecord(recipient.getId()));
|
records.add(record.toIdentityRecord(recipient.getId()));
|
||||||
|
@ -189,8 +191,8 @@ public class SignalBaseIdentityKeyStore {
|
||||||
public void setApproval(@NonNull RecipientId recipientId, boolean nonBlockingApproval) {
|
public void setApproval(@NonNull RecipientId recipientId, boolean nonBlockingApproval) {
|
||||||
Recipient recipient = Recipient.resolved(recipientId);
|
Recipient recipient = Recipient.resolved(recipientId);
|
||||||
|
|
||||||
if (recipient.hasServiceIdentifier()) {
|
if (recipient.hasServiceId()) {
|
||||||
cache.setApproval(recipient.requireServiceId(), recipientId, nonBlockingApproval);
|
cache.setApproval(recipient.requireServiceId().toString(), recipientId, nonBlockingApproval);
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "[setApproval] No serviceId for " + recipient.getId());
|
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) {
|
public void setVerified(@NonNull RecipientId recipientId, IdentityKey identityKey, VerifiedStatus verifiedStatus) {
|
||||||
Recipient recipient = Recipient.resolved(recipientId);
|
Recipient recipient = Recipient.resolved(recipientId);
|
||||||
|
|
||||||
if (recipient.hasServiceIdentifier()) {
|
if (recipient.hasServiceId()) {
|
||||||
cache.setVerified(recipient.requireServiceId(), recipientId, identityKey, verifiedStatus);
|
cache.setVerified(recipient.requireServiceId().toString(), recipientId, identityKey, verifiedStatus);
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "[setVerified] No serviceId for " + recipient.getId());
|
Log.w(TAG, "[setVerified] No serviceId for " + recipient.getId());
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import androidx.annotation.NonNull;
|
||||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceDataStore;
|
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 {
|
public final class SignalServiceDataStoreImpl implements SignalServiceDataStore {
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ public final class SignalServiceDataStoreImpl implements SignalServiceDataStore
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SignalServiceAccountDataStoreImpl get(@NonNull AccountIdentifier accountIdentifier) {
|
public SignalServiceAccountDataStoreImpl get(@NonNull ServiceId accountIdentifier) {
|
||||||
if (accountIdentifier.equals(SignalStore.account().getAci())) {
|
if (accountIdentifier.equals(SignalStore.account().getAci())) {
|
||||||
return aciStore;
|
return aciStore;
|
||||||
} else if (accountIdentifier.equals(SignalStore.account().getPni())) {
|
} else if (accountIdentifier.equals(SignalStore.account().getPni())) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import org.whispersystems.libsignal.state.PreKeyRecord;
|
||||||
import org.whispersystems.libsignal.state.PreKeyStore;
|
import org.whispersystems.libsignal.state.PreKeyStore;
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyStore;
|
import org.whispersystems.libsignal.state.SignedPreKeyStore;
|
||||||
import org.whispersystems.signalservice.api.push.AccountIdentifier;
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ public class TextSecurePreKeyStore implements PreKeyStore, SignedPreKeyStore {
|
||||||
private static final Object LOCK = new Object();
|
private static final Object LOCK = new Object();
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final AccountIdentifier accountId;
|
private final ServiceId accountId;
|
||||||
|
|
||||||
public TextSecurePreKeyStore(@NonNull AccountIdentifier accountId) {
|
public TextSecurePreKeyStore(@NonNull ServiceId accountId) {
|
||||||
this.accountId = accountId;
|
this.accountId = accountId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.thoughtcrime.securesms.crypto.storage;
|
package org.thoughtcrime.securesms.crypto.storage;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
@ -15,7 +13,7 @@ import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||||
import org.whispersystems.libsignal.protocol.CiphertextMessage;
|
import org.whispersystems.libsignal.protocol.CiphertextMessage;
|
||||||
import org.whispersystems.libsignal.state.SessionRecord;
|
import org.whispersystems.libsignal.state.SessionRecord;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceSessionStore;
|
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.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -28,9 +26,9 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
||||||
|
|
||||||
private static final Object LOCK = new Object();
|
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;
|
this.accountId = accountId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,8 +133,8 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
Recipient recipient = Recipient.resolved(recipientId);
|
Recipient recipient = Recipient.resolved(recipientId);
|
||||||
|
|
||||||
if (recipient.hasAci()) {
|
if (recipient.hasServiceId()) {
|
||||||
archiveSession(new SignalProtocolAddress(recipient.requireAci().toString(), deviceId));
|
archiveSession(new SignalProtocolAddress(recipient.requireServiceId().toString(), deviceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recipient.hasE164()) {
|
if (recipient.hasE164()) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.crypto.SenderKeyUtil;
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor;
|
import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor;
|
||||||
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob;
|
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.ACI;
|
||||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||||
import org.thoughtcrime.securesms.groups.GroupAccessControl;
|
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.DecryptedGroupUtil;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.GroupChangeReconstruct;
|
import org.whispersystems.signalservice.api.groupsv2.GroupChangeReconstruct;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
@ -821,7 +823,7 @@ private static final String[] GROUP_PROJECTION = {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean gv2GroupActive(@NonNull DecryptedGroup decryptedGroup) {
|
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() ||
|
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), aci.uuid()).isPresent() ||
|
||||||
DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), 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) {
|
public boolean isPendingMember(@NonNull Recipient recipient) {
|
||||||
if (isV2Group()) {
|
if (isV2Group()) {
|
||||||
Optional<ACI> aci = recipient.getAci();
|
Optional<ServiceId> serviceId = recipient.getServiceId();
|
||||||
if (aci.isPresent()) {
|
if (serviceId.isPresent()) {
|
||||||
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().getDecryptedGroup().getPendingMembersList(), aci.get().uuid())
|
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().getDecryptedGroup().getPendingMembersList(), serviceId.get().uuid())
|
||||||
.isPresent();
|
.isPresent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1275,13 +1277,13 @@ private static final String[] GROUP_PROJECTION = {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAdmin(@NonNull Recipient recipient) {
|
public boolean isAdmin(@NonNull Recipient recipient) {
|
||||||
Optional<ACI> aci = recipient.getAci();
|
Optional<ServiceId> serviceId = recipient.getServiceId();
|
||||||
|
|
||||||
if (!aci.isPresent()) {
|
if (!serviceId.isPresent()) {
|
||||||
return false;
|
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)
|
.transform(t -> t.getRole() == Member.Role.ADMINISTRATOR)
|
||||||
.or(false);
|
.or(false);
|
||||||
}
|
}
|
||||||
|
@ -1291,21 +1293,21 @@ private static final String[] GROUP_PROJECTION = {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MemberLevel memberLevel(@NonNull Recipient recipient) {
|
public MemberLevel memberLevel(@NonNull Recipient recipient) {
|
||||||
Optional<ACI> aci = recipient.getAci();
|
Optional<ServiceId> serviceId = recipient.getServiceId();
|
||||||
|
|
||||||
if (!aci.isPresent()) {
|
if (!serviceId.isPresent()) {
|
||||||
return MemberLevel.NOT_A_MEMBER;
|
return MemberLevel.NOT_A_MEMBER;
|
||||||
}
|
}
|
||||||
|
|
||||||
DecryptedGroup decryptedGroup = getDecryptedGroup();
|
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
|
.transform(member -> member.getRole() == Member.Role.ADMINISTRATOR
|
||||||
? MemberLevel.ADMINISTRATOR
|
? MemberLevel.ADMINISTRATOR
|
||||||
: MemberLevel.FULL_MEMBER)
|
: MemberLevel.FULL_MEMBER)
|
||||||
.or(() -> DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), aci.get().uuid())
|
.or(() -> DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), serviceId.get().uuid())
|
||||||
.transform(m -> MemberLevel.PENDING_MEMBER)
|
.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)
|
.transform(m -> MemberLevel.REQUESTING_MEMBER)
|
||||||
.or(MemberLevel.NOT_A_MEMBER)));
|
.or(MemberLevel.NOT_A_MEMBER)));
|
||||||
}
|
}
|
||||||
|
@ -1317,7 +1319,7 @@ private static final String[] GROUP_PROJECTION = {
|
||||||
public List<RecipientId> getMemberRecipientIds(@NonNull MemberSet memberSet) {
|
public List<RecipientId> getMemberRecipientIds(@NonNull MemberSet memberSet) {
|
||||||
boolean includeSelf = memberSet.includeSelf;
|
boolean includeSelf = memberSet.includeSelf;
|
||||||
DecryptedGroup groupV2 = getDecryptedGroup();
|
DecryptedGroup groupV2 = getDecryptedGroup();
|
||||||
UUID selfUuid = Recipient.self().requireAci().uuid();
|
UUID selfUuid = Recipient.self().requireServiceId().uuid();
|
||||||
List<RecipientId> recipients = new ArrayList<>(groupV2.getMembersCount() + groupV2.getPendingMembersCount());
|
List<RecipientId> recipients = new ArrayList<>(groupV2.getMembersCount() + groupV2.getPendingMembersCount());
|
||||||
int unknownMembers = 0;
|
int unknownMembers = 0;
|
||||||
int unknownPending = 0;
|
int unknownPending = 0;
|
||||||
|
|
|
@ -19,7 +19,6 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ACI;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -106,7 +105,7 @@ public final class MentionUtil {
|
||||||
BodyRangeList.Builder builder = BodyRangeList.newBuilder();
|
BodyRangeList.Builder builder = BodyRangeList.newBuilder();
|
||||||
|
|
||||||
for (Mention mention : mentions) {
|
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()
|
builder.addRanges(BodyRangeList.BodyRange.newBuilder()
|
||||||
.setMentionUuid(uuid)
|
.setMentionUuid(uuid)
|
||||||
.setStart(mention.getStart())
|
.setStart(mention.getStart())
|
||||||
|
@ -122,7 +121,7 @@ public final class MentionUtil {
|
||||||
return Stream.of(BodyRangeList.parseFrom(data).getRangesList())
|
return Stream.of(BodyRangeList.parseFrom(data).getRangesList())
|
||||||
.filter(bodyRange -> bodyRange.getAssociatedValueCase() == BodyRangeList.BodyRange.AssociatedValueCase.MENTIONUUID)
|
.filter(bodyRange -> bodyRange.getAssociatedValueCase() == BodyRangeList.BodyRange.AssociatedValueCase.MENTIONUUID)
|
||||||
.map(mention -> {
|
.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());
|
return new Mention(id, mention.getStart(), mention.getLength());
|
||||||
})
|
})
|
||||||
.toList();
|
.toList();
|
||||||
|
|
|
@ -9,7 +9,7 @@ import org.whispersystems.libsignal.InvalidKeyException
|
||||||
import org.whispersystems.libsignal.ecc.Curve
|
import org.whispersystems.libsignal.ecc.Curve
|
||||||
import org.whispersystems.libsignal.ecc.ECKeyPair
|
import org.whispersystems.libsignal.ecc.ECKeyPair
|
||||||
import org.whispersystems.libsignal.state.PreKeyRecord
|
import org.whispersystems.libsignal.state.PreKeyRecord
|
||||||
import org.whispersystems.signalservice.api.push.AccountIdentifier
|
import org.whispersystems.signalservice.api.push.ServiceId
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
class OneTimePreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : Database(context, databaseHelper) {
|
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? {
|
fun get(serviceId: ServiceId, keyId: Int): PreKeyRecord? {
|
||||||
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(accountId, keyId), null, null, null).use { cursor ->
|
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId), null, null, null).use { cursor ->
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
try {
|
try {
|
||||||
val publicKey = Curve.decodePoint(Base64.decode(cursor.requireNonNullString(PUBLIC_KEY)), 0)
|
val publicKey = Curve.decodePoint(Base64.decode(cursor.requireNonNullString(PUBLIC_KEY)), 0)
|
||||||
|
@ -52,9 +52,9 @@ class OneTimePreKeyDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun insert(accountId: AccountIdentifier, keyId: Int, record: PreKeyRecord) {
|
fun insert(serviceId: ServiceId, keyId: Int, record: PreKeyRecord) {
|
||||||
val contentValues = contentValuesOf(
|
val contentValues = contentValuesOf(
|
||||||
ACCOUNT_ID to accountId.toString(),
|
ACCOUNT_ID to serviceId.toString(),
|
||||||
KEY_ID to keyId,
|
KEY_ID to keyId,
|
||||||
PUBLIC_KEY to Base64.encodeBytes(record.keyPair.publicKey.serialize()),
|
PUBLIC_KEY to Base64.encodeBytes(record.keyPair.publicKey.serialize()),
|
||||||
PRIVATE_KEY to Base64.encodeBytes(record.keyPair.privateKey.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)
|
writableDatabase.replace(TABLE_NAME, null, contentValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun delete(accountId: AccountIdentifier, keyId: Int) {
|
fun delete(serviceId: ServiceId, keyId: Int) {
|
||||||
val database = databaseHelper.signalWritableDatabase
|
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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,7 @@ import org.whispersystems.libsignal.util.guava.Optional
|
||||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile
|
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile
|
||||||
import org.whispersystems.signalservice.api.push.ACI
|
import org.whispersystems.signalservice.api.push.ACI
|
||||||
import org.whispersystems.signalservice.api.push.PNI
|
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.push.SignalServiceAddress
|
||||||
import org.whispersystems.signalservice.api.storage.SignalAccountRecord
|
import org.whispersystems.signalservice.api.storage.SignalAccountRecord
|
||||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord
|
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 TABLE_NAME = "recipient"
|
||||||
|
|
||||||
const val ID = "_id"
|
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 PNI_COLUMN = "pni"
|
||||||
private const val USERNAME = "username"
|
private const val USERNAME = "username"
|
||||||
const val PHONE = "phone"
|
const val PHONE = "phone"
|
||||||
|
@ -171,7 +172,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
"""
|
"""
|
||||||
CREATE TABLE $TABLE_NAME (
|
CREATE TABLE $TABLE_NAME (
|
||||||
$ID INTEGER PRIMARY KEY AUTOINCREMENT,
|
$ID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
$ACI_COLUMN TEXT UNIQUE DEFAULT NULL,
|
$SERVICE_ID TEXT UNIQUE DEFAULT NULL,
|
||||||
$USERNAME TEXT UNIQUE DEFAULT NULL,
|
$USERNAME TEXT UNIQUE DEFAULT NULL,
|
||||||
$PHONE TEXT UNIQUE DEFAULT NULL,
|
$PHONE TEXT UNIQUE DEFAULT NULL,
|
||||||
$EMAIL 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<String> = arrayOf(
|
private val RECIPIENT_PROJECTION: Array<String> = arrayOf(
|
||||||
ID,
|
ID,
|
||||||
ACI_COLUMN,
|
SERVICE_ID,
|
||||||
PNI_COLUMN,
|
PNI_COLUMN,
|
||||||
USERNAME,
|
USERNAME,
|
||||||
PHONE,
|
PHONE,
|
||||||
|
@ -367,7 +368,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
}
|
}
|
||||||
|
|
||||||
fun containsPhoneOrUuid(id: String): Boolean {
|
fun containsPhoneOrUuid(id: String): Boolean {
|
||||||
val query = "$ACI_COLUMN = ? OR $PHONE = ?"
|
val query = "$SERVICE_ID = ? OR $PHONE = ?"
|
||||||
val args = arrayOf(id, id)
|
val args = arrayOf(id, id)
|
||||||
readableDatabase.query(TABLE_NAME, arrayOf(ID), query, args, null, null, null).use { cursor -> return cursor != null && cursor.moveToFirst() }
|
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())
|
return getByColumn(GROUP_ID, groupId.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getByAci(uuid: ACI): Optional<RecipientId> {
|
fun getByServiceId(serviceId: ServiceId): Optional<RecipientId> {
|
||||||
return getByColumn(ACI_COLUMN, uuid.toString())
|
return getByColumn(SERVICE_ID, serviceId.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getByUsername(username: String): Optional<RecipientId> {
|
fun getByUsername(username: String): Optional<RecipientId> {
|
||||||
return getByColumn(USERNAME, username)
|
return getByColumn(USERNAME, username)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAndPossiblyMerge(aci: ACI?, e164: String?, highTrust: Boolean): RecipientId {
|
fun getAndPossiblyMerge(serviceId: ServiceId?, e164: String?, highTrust: Boolean): RecipientId {
|
||||||
return getAndPossiblyMerge(aci, e164, highTrust, false)
|
return getAndPossiblyMerge(serviceId, e164, highTrust, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAndPossiblyMerge(aci: ACI?, e164: String?, highTrust: Boolean, changeSelf: Boolean): RecipientId {
|
fun getAndPossiblyMerge(serviceId: ServiceId?, e164: String?, highTrust: Boolean, changeSelf: Boolean): RecipientId {
|
||||||
require(!(aci == null && e164 == null)) { "Must provide an ACI or E164!" }
|
require(!(serviceId == null && e164 == null)) { "Must provide an ACI or E164!" }
|
||||||
|
|
||||||
val db = writableDatabase
|
val db = writableDatabase
|
||||||
|
|
||||||
|
@ -408,7 +409,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
|
|
||||||
db.beginTransaction()
|
db.beginTransaction()
|
||||||
try {
|
try {
|
||||||
val fetch: RecipientFetch = fetchRecipient(aci, e164, highTrust, changeSelf)
|
val fetch: RecipientFetch = fetchRecipient(serviceId, e164, highTrust, changeSelf)
|
||||||
|
|
||||||
if (fetch.logBundle != null) {
|
if (fetch.logBundle != null) {
|
||||||
Log.w(TAG, fetch.toString())
|
Log.w(TAG, fetch.toString())
|
||||||
|
@ -432,29 +433,29 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
fetch.id
|
fetch.id
|
||||||
}
|
}
|
||||||
is RecipientFetch.MatchAndUpdateAci -> {
|
is RecipientFetch.MatchAndUpdateAci -> {
|
||||||
markRegistered(fetch.id, fetch.aci)
|
markRegistered(fetch.id, fetch.serviceId)
|
||||||
recipientsNeedingRefresh = listOf(fetch.id)
|
recipientsNeedingRefresh = listOf(fetch.id)
|
||||||
fetch.id
|
fetch.id
|
||||||
}
|
}
|
||||||
is RecipientFetch.MatchAndInsertAci -> {
|
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)
|
RecipientId.from(id)
|
||||||
}
|
}
|
||||||
is RecipientFetch.MatchAndMerge -> {
|
is RecipientFetch.MatchAndMerge -> {
|
||||||
remapped = Pair(fetch.e164Id, fetch.aciId)
|
remapped = Pair(fetch.e164Id, fetch.sidId)
|
||||||
val mergedId: RecipientId = merge(fetch.aciId, fetch.e164Id)
|
val mergedId: RecipientId = merge(fetch.sidId, fetch.e164Id)
|
||||||
recipientsNeedingRefresh = listOf(mergedId)
|
recipientsNeedingRefresh = listOf(mergedId)
|
||||||
recipientChangedNumber = fetch.changedNumber
|
recipientChangedNumber = fetch.changedNumber
|
||||||
mergedId
|
mergedId
|
||||||
}
|
}
|
||||||
is RecipientFetch.Insert -> {
|
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)
|
RecipientId.from(id)
|
||||||
}
|
}
|
||||||
is RecipientFetch.InsertAndReassignE164 -> {
|
is RecipientFetch.InsertAndReassignE164 -> {
|
||||||
removePhoneNumber(fetch.e164Id, db)
|
removePhoneNumber(fetch.e164Id, db)
|
||||||
recipientsNeedingRefresh = listOf(fetch.e164Id)
|
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)
|
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 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(
|
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(),
|
byE164 = byE164.transform { id -> RecipientLogDetails(id = id) }.orNull(),
|
||||||
label = "L0"
|
label = "L0"
|
||||||
)
|
)
|
||||||
|
@ -504,9 +505,9 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
|
|
||||||
if (byAci.isPresent && byE164.isAbsent()) {
|
if (byAci.isPresent && byE164.isAbsent()) {
|
||||||
val aciRecord: RecipientRecord = getRecord(byAci.get())
|
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
|
val changedNumber: RecipientId? = if (aciRecord.e164 != null && aciRecord.e164 != e164) aciRecord.id else null
|
||||||
return RecipientFetch.MatchAndUpdateE164(byAci.get(), e164, changedNumber, logs.label("L1"))
|
return RecipientFetch.MatchAndUpdateE164(byAci.get(), e164, changedNumber, logs.label("L1"))
|
||||||
} else if (e164 == null) {
|
} else if (e164 == null) {
|
||||||
|
@ -520,12 +521,12 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
val e164Record: RecipientRecord = getRecord(byE164.get())
|
val e164Record: RecipientRecord = getRecord(byE164.get())
|
||||||
logs = logs.copy(byE164 = e164Record.toLogDetails())
|
logs = logs.copy(byE164 = e164Record.toLogDetails())
|
||||||
|
|
||||||
if (highTrust && aci != null && e164Record.aci == null) {
|
if (highTrust && serviceId != null && e164Record.serviceId == null) {
|
||||||
return RecipientFetch.MatchAndUpdateAci(byE164.get(), aci, logs.label("L3"))
|
return RecipientFetch.MatchAndUpdateAci(byE164.get(), serviceId, logs.label("L3"))
|
||||||
} else if (highTrust && aci != null && e164Record.aci != SignalStore.account().aci) {
|
} else if (highTrust && serviceId != null && e164Record.serviceId != SignalStore.account().aci) {
|
||||||
return RecipientFetch.InsertAndReassignE164(aci, e164, byE164.get(), logs.label("L4"))
|
return RecipientFetch.InsertAndReassignE164(serviceId, e164, byE164.get(), logs.label("L4"))
|
||||||
} else if (aci != null) {
|
} else if (serviceId != null) {
|
||||||
return RecipientFetch.Insert(aci, null, logs.label("L5"))
|
return RecipientFetch.Insert(serviceId, null, logs.label("L5"))
|
||||||
} else {
|
} else {
|
||||||
return RecipientFetch.Match(byE164.get(), null)
|
return RecipientFetch.Match(byE164.get(), null)
|
||||||
}
|
}
|
||||||
|
@ -533,9 +534,9 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
|
|
||||||
if (byAci.isAbsent() && byE164.isAbsent()) {
|
if (byAci.isAbsent() && byE164.isAbsent()) {
|
||||||
if (highTrust) {
|
if (highTrust) {
|
||||||
return RecipientFetch.Insert(aci, e164, logs.label("L6"))
|
return RecipientFetch.Insert(serviceId, e164, logs.label("L6"))
|
||||||
} else if (aci != null) {
|
} else if (serviceId != null) {
|
||||||
return RecipientFetch.Insert(aci, null, logs.label("L7"))
|
return RecipientFetch.Insert(serviceId, null, logs.label("L7"))
|
||||||
} else {
|
} else {
|
||||||
return RecipientFetch.Insert(null, e164, logs.label("L8"))
|
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 aciRecord: RecipientRecord = getRecord(byAci.get())
|
||||||
val e164Record: RecipientRecord = getRecord(byE164.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) {
|
if (highTrust) {
|
||||||
val changedNumber: RecipientId? = if (aciRecord.e164 != null) aciRecord.id else null
|
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 {
|
} else {
|
||||||
return RecipientFetch.Match(byAci.get(), logs.label("L10"))
|
return RecipientFetch.Match(byAci.get(), logs.label("L10"))
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
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"))
|
return RecipientFetch.MatchAndReassignE164(id = byAci.get(), e164Id = byE164.get(), e164 = e164!!, changedNumber = changedNumber, logs.label("L11"))
|
||||||
} else {
|
} else {
|
||||||
|
@ -565,8 +566,8 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOrInsertFromAci(aci: ACI): RecipientId {
|
fun getOrInsertFromServiceId(serviceId: ServiceId): RecipientId {
|
||||||
return getOrInsertByColumn(ACI_COLUMN, aci.toString()).recipientId
|
return getOrInsertByColumn(SERVICE_ID, serviceId.toString()).recipientId
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOrInsertFromE164(e164: String): RecipientId {
|
fun getOrInsertFromE164(e164: String): RecipientId {
|
||||||
|
@ -785,13 +786,13 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
val recipientId: RecipientId?
|
val recipientId: RecipientId?
|
||||||
if (id < 0) {
|
if (id < 0) {
|
||||||
Log.w(TAG, "[applyStorageSyncContactInsert] Failed to insert. Possibly merging.")
|
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))
|
db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId))
|
||||||
} else {
|
} else {
|
||||||
recipientId = RecipientId.from(id)
|
recipientId = RecipientId.from(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (insert.identityKey.isPresent && insert.address.hasValidAci()) {
|
if (insert.identityKey.isPresent && insert.address.hasValidServiceId()) {
|
||||||
try {
|
try {
|
||||||
val identityKey = IdentityKey(insert.identityKey.get(), 0)
|
val identityKey = IdentityKey(insert.identityKey.get(), 0)
|
||||||
identities.updateIdentityAfterSync(insert.address.identifier, recipientId!!, identityKey, StorageSyncModels.remoteToLocalIdentityStatus(insert.identityState))
|
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()
|
var recipientId = getByColumn(STORAGE_SERVICE_ID, Base64.encodeBytes(update.old.id.raw)).get()
|
||||||
|
|
||||||
Log.w(TAG, "[applyStorageSyncContactUpdate] Found user $recipientId. Possibly merging.")
|
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")
|
Log.w(TAG, "[applyStorageSyncContactUpdate] Merged into $recipientId")
|
||||||
db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId))
|
db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId))
|
||||||
|
@ -834,7 +835,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val oldIdentityRecord = identityStore.getIdentityRecord(recipientId)
|
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)
|
val identityKey = IdentityKey(update.new.identityKey.get(), 0)
|
||||||
identities.updateIdentityAfterSync(update.new.address.identifier, recipientId, identityKey, StorageSyncModels.remoteToLocalIdentityStatus(update.new.identityState))
|
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<String>?): List<RecipientRecord> {
|
private fun getRecordForSync(query: String?, args: Array<String>?): List<RecipientRecord> {
|
||||||
val table =
|
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 ${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}
|
LEFT OUTER JOIN ${ThreadDatabase.TABLE_NAME} ON $TABLE_NAME.$ID = ${ThreadDatabase.TABLE_NAME}.${ThreadDatabase.RECIPIENT_ID}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
@ -1018,7 +1019,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
fun getContactStorageSyncIdsMap(): Map<RecipientId, StorageId> {
|
fun getContactStorageSyncIdsMap(): Map<RecipientId, StorageId> {
|
||||||
val query = """
|
val query = """
|
||||||
$STORAGE_SERVICE_ID NOT NULL AND (
|
$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
|
OR
|
||||||
$GROUP_TYPE IN (?)
|
$GROUP_TYPE IN (?)
|
||||||
)
|
)
|
||||||
|
@ -1505,7 +1506,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
val selfId = Recipient.self().id
|
val selfId = Recipient.self().id
|
||||||
|
|
||||||
for ((key, value) in profileKeys) {
|
for ((key, value) in profileKeys) {
|
||||||
val recipientId = getOrInsertFromAci(key)
|
val recipientId = getOrInsertFromServiceId(key)
|
||||||
if (setProfileKeyIfAbsent(recipientId, value)) {
|
if (setProfileKeyIfAbsent(recipientId, value)) {
|
||||||
Log.i(TAG, "Learned new profile key")
|
Log.i(TAG, "Learned new profile key")
|
||||||
updated.add(recipientId)
|
updated.add(recipientId)
|
||||||
|
@ -1513,7 +1514,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((key, value) in authoritativeProfileKeys) {
|
for ((key, value) in authoritativeProfileKeys) {
|
||||||
val recipientId = getOrInsertFromAci(key)
|
val recipientId = getOrInsertFromServiceId(key)
|
||||||
|
|
||||||
if (selfId == recipientId) {
|
if (selfId == recipientId) {
|
||||||
Log.i(TAG, "Seen authoritative update for self")
|
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.")
|
Log.w(TAG, "[setPhoneNumber] Hit a conflict when trying to update $id. Possibly merging.")
|
||||||
|
|
||||||
val existing: RecipientRecord = getRecord(id)
|
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")
|
Log.w(TAG, "[setPhoneNumber] Resulting id: $newId")
|
||||||
|
|
||||||
db.setTransactionSuccessful()
|
db.setTransactionSuccessful()
|
||||||
|
@ -1812,7 +1813,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
db.beginTransaction()
|
db.beginTransaction()
|
||||||
try {
|
try {
|
||||||
val id = Recipient.self().id
|
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) {
|
if (id == newId) {
|
||||||
Log.i(TAG, "[updateSelfPhone] Phone updated for self")
|
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.
|
* @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
|
val db = writableDatabase
|
||||||
|
|
||||||
db.beginTransaction()
|
db.beginTransaction()
|
||||||
try {
|
try {
|
||||||
markRegisteredOrThrow(id, aci)
|
markRegisteredOrThrow(id, serviceId)
|
||||||
db.setTransactionSuccessful()
|
db.setTransactionSuccessful()
|
||||||
return false
|
return false
|
||||||
} catch (e: SQLiteConstraintException) {
|
} catch (e: SQLiteConstraintException) {
|
||||||
Log.w(TAG, "[markRegistered] Hit a conflict when trying to update $id. Possibly merging.")
|
Log.w(TAG, "[markRegistered] Hit a conflict when trying to update $id. Possibly merging.")
|
||||||
|
|
||||||
val existing = getRecord(id)
|
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")
|
Log.w(TAG, "[markRegistered] Merged into $newId")
|
||||||
|
|
||||||
db.setTransactionSuccessful()
|
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.
|
* 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 {
|
val contentValues = ContentValues(2).apply {
|
||||||
put(REGISTERED, RegisteredState.REGISTERED.id)
|
put(REGISTERED, RegisteredState.REGISTERED.id)
|
||||||
put(ACI_COLUMN, aci.toString().toLowerCase())
|
put(SERVICE_ID, serviceId.toString().toLowerCase())
|
||||||
}
|
}
|
||||||
if (update(id, contentValues)) {
|
if (update(id, contentValues)) {
|
||||||
setStorageIdIfNotSet(id)
|
setStorageIdIfNotSet(id)
|
||||||
|
@ -1920,7 +1921,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bulkUpdatedRegisteredStatus(registered: Map<RecipientId, ACI?>, unregistered: Collection<RecipientId>) {
|
fun bulkUpdatedRegisteredStatus(registered: Map<RecipientId, ServiceId?>, unregistered: Collection<RecipientId>) {
|
||||||
val db = writableDatabase
|
val db = writableDatabase
|
||||||
|
|
||||||
db.beginTransaction()
|
db.beginTransaction()
|
||||||
|
@ -1929,7 +1930,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
val values = ContentValues(2).apply {
|
val values = ContentValues(2).apply {
|
||||||
put(REGISTERED, RegisteredState.REGISTERED.id)
|
put(REGISTERED, RegisteredState.REGISTERED.id)
|
||||||
if (aci != null) {
|
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()
|
db.beginTransaction()
|
||||||
try {
|
try {
|
||||||
for ((e164, aci) in mapping) {
|
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) {
|
if (aciEntry.isPresent) {
|
||||||
val idChanged = setPhoneNumber(aciEntry.get(), e164)
|
val idChanged = setPhoneNumber(aciEntry.get(), e164)
|
||||||
if (idChanged) {
|
if (idChanged) {
|
||||||
aciEntry = getByAci(aci!!)
|
aciEntry = getByServiceId(aci!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2272,7 +2273,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
val blockedUuid = blocked
|
val blockedUuid = blocked
|
||||||
.map { b: SignalServiceAddress -> b.aci.toString().toLowerCase() }
|
.map { b: SignalServiceAddress -> b.serviceId.toString().toLowerCase() }
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
val db = writableDatabase
|
val db = writableDatabase
|
||||||
|
@ -2293,7 +2294,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uuid in blockedUuid) {
|
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<V1> = ArrayList(groupIds.size)
|
val groupIdStrings: MutableList<V1> = ArrayList(groupIds.size)
|
||||||
|
@ -2604,10 +2605,10 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sessions
|
// Sessions
|
||||||
val localAci: ACI = SignalStore.account().aci!!
|
val localAci: ACI = SignalStore.account().requireAci()
|
||||||
val sessionDatabase = sessions
|
val sessionDatabase = sessions
|
||||||
val hasE164Session = sessionDatabase.getAllFor(localAci, e164Record.e164).isNotEmpty()
|
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) {
|
if (hasE164Session && hasAciSession) {
|
||||||
Log.w(TAG, "Had a session for both users. Deleting the E164.", true)
|
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) {
|
} else if (hasE164Session && !hasAciSession) {
|
||||||
Log.w(TAG, "Had a session for E164, but not ACI. Re-assigning to the ACI.", true)
|
Log.w(TAG, "Had a session for E164, but not ACI. Re-assigning to the ACI.", true)
|
||||||
val values = ContentValues().apply {
|
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))
|
db.update(SessionDatabase.TABLE_NAME, values, "${SessionDatabase.ACCOUNT_ID} = ? AND ${SessionDatabase.ADDRESS} = ?", SqlUtil.buildArgs(localAci, e164Record.e164))
|
||||||
} else if (!hasE164Session && hasAciSession) {
|
} else if (!hasE164Session && hasAciSession) {
|
||||||
|
@ -2694,11 +2695,11 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
check(writableDatabase.inTransaction()) { "Must be in a transaction!" }
|
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()
|
val values = ContentValues()
|
||||||
values.put(PHONE, e164)
|
values.put(PHONE, e164)
|
||||||
if (aci != null) {
|
if (serviceId != null) {
|
||||||
values.put(ACI_COLUMN, aci.toString().toLowerCase())
|
values.put(SERVICE_ID, serviceId.toString().toLowerCase())
|
||||||
values.put(REGISTERED, RegisteredState.REGISTERED.id)
|
values.put(REGISTERED, RegisteredState.REGISTERED.id)
|
||||||
values.put(STORAGE_SERVICE_ID, Base64.encodeBytes(StorageSyncHelper.generateKey()))
|
values.put(STORAGE_SERVICE_ID, Base64.encodeBytes(StorageSyncHelper.generateKey()))
|
||||||
values.put(AVATAR_COLOR, AvatarColor.random().serialize())
|
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 profileName = ProfileName.fromParts(contact.givenName.orNull(), contact.familyName.orNull())
|
||||||
val username = contact.username.orNull()
|
val username = contact.username.orNull()
|
||||||
|
|
||||||
if (contact.address.hasValidAci()) {
|
if (contact.address.hasValidServiceId()) {
|
||||||
put(ACI_COLUMN, contact.address.aci.toString())
|
put(SERVICE_ID, contact.address.serviceId.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
put(PHONE, contact.address.number.orNull())
|
put(PHONE, contact.address.number.orNull())
|
||||||
|
@ -2845,7 +2846,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
|
|
||||||
return RecipientRecord(
|
return RecipientRecord(
|
||||||
id = recipientId,
|
id = recipientId,
|
||||||
aci = ACI.parseOrNull(cursor.requireString(ACI_COLUMN)),
|
serviceId = ACI.parseOrNull(cursor.requireString(SERVICE_ID)),
|
||||||
pni = PNI.parseOrNull(cursor.requireString(PNI_COLUMN)),
|
pni = PNI.parseOrNull(cursor.requireString(PNI_COLUMN)),
|
||||||
username = cursor.requireString(USERNAME),
|
username = cursor.requireString(USERNAME),
|
||||||
e164 = cursor.requireString(PHONE),
|
e164 = cursor.requireString(PHONE),
|
||||||
|
@ -3045,7 +3046,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
private fun RecipientRecord.toLogDetails(): RecipientLogDetails {
|
private fun RecipientRecord.toLogDetails(): RecipientLogDetails {
|
||||||
return RecipientLogDetails(
|
return RecipientLogDetails(
|
||||||
id = this.id,
|
id = this.id,
|
||||||
aci = this.aci,
|
serviceId = this.serviceId,
|
||||||
e164 = this.e164
|
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.
|
* 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*.
|
* 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.
|
* 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.
|
* 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.
|
* 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(
|
private data class LogBundle(
|
||||||
val label: String,
|
val label: String,
|
||||||
val aci: ACI? = null,
|
val serviceId: ServiceId? = null,
|
||||||
val e164: String? = null,
|
val e164: String? = null,
|
||||||
val byAci: RecipientLogDetails? = null,
|
val bySid: RecipientLogDetails? = null,
|
||||||
val byE164: RecipientLogDetails? = null
|
val byE164: RecipientLogDetails? = null
|
||||||
) {
|
) {
|
||||||
fun label(label: String): LogBundle {
|
fun label(label: String): LogBundle {
|
||||||
|
@ -3400,7 +3401,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
|
||||||
*/
|
*/
|
||||||
private data class RecipientLogDetails(
|
private data class RecipientLogDetails(
|
||||||
val id: RecipientId,
|
val id: RecipientId,
|
||||||
val aci: ACI? = null,
|
val serviceId: ServiceId? = null,
|
||||||
val e164: String? = null
|
val e164: String? = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,7 @@ public class SenderKeyDatabase extends Database {
|
||||||
public Cursor getAllCreatedBySelf() {
|
public Cursor getAllCreatedBySelf() {
|
||||||
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
|
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
|
||||||
String query = ADDRESS + " = ?";
|
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");
|
return db.query(TABLE_NAME, new String[]{ ID, DISTRIBUTION_ID, CREATED_AT }, query, args, null, null, CREATED_AT + " DESC");
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,8 +145,8 @@ public class SenderKeySharedDatabase extends Database {
|
||||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||||
Recipient recipient = Recipient.resolved(recipientId);
|
Recipient recipient = Recipient.resolved(recipientId);
|
||||||
|
|
||||||
if (recipient.hasAci()) {
|
if (recipient.hasServiceId()) {
|
||||||
db.delete(TABLE_NAME, ADDRESS + " = ?", SqlUtil.buildArgs(recipient.requireAci().toString()));
|
db.delete(TABLE_NAME, ADDRESS + " = ?", SqlUtil.buildArgs(recipient.requireServiceId().toString()));
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Recipient doesn't have a UUID! " + recipientId);
|
Log.w(TAG, "Recipient doesn't have a UUID! " + recipientId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import org.thoughtcrime.securesms.util.CursorUtil
|
||||||
import org.thoughtcrime.securesms.util.SqlUtil
|
import org.thoughtcrime.securesms.util.SqlUtil
|
||||||
import org.whispersystems.libsignal.SignalProtocolAddress
|
import org.whispersystems.libsignal.SignalProtocolAddress
|
||||||
import org.whispersystems.libsignal.state.SessionRecord
|
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 org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.ArrayList
|
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!" }
|
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 ->
|
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 {
|
statement.apply {
|
||||||
bindString(1, accountId.toString())
|
bindString(1, serviceId.toString())
|
||||||
bindString(2, address.name)
|
bindString(2, address.name)
|
||||||
bindLong(3, address.deviceId.toLong())
|
bindLong(3, address.deviceId.toLong())
|
||||||
bindBlob(4, record.serialize())
|
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 projection = arrayOf(RECORD)
|
||||||
val selection = "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?"
|
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 ->
|
readableDatabase.query(TABLE_NAME, projection, selection, args, null, null, null).use { cursor ->
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
|
@ -68,14 +68,14 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun load(accountId: AccountIdentifier, addresses: List<SignalProtocolAddress>): List<SessionRecord?> {
|
fun load(serviceId: ServiceId, addresses: List<SignalProtocolAddress>): List<SessionRecord?> {
|
||||||
val projection = arrayOf(ADDRESS, DEVICE, RECORD)
|
val projection = arrayOf(ADDRESS, DEVICE, RECORD)
|
||||||
val query = "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?"
|
val query = "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?"
|
||||||
val args: MutableList<Array<String>> = ArrayList(addresses.size)
|
val args: MutableList<Array<String>> = ArrayList(addresses.size)
|
||||||
val sessions: HashMap<SignalProtocolAddress, SessionRecord?> = LinkedHashMap(addresses.size)
|
val sessions: HashMap<SignalProtocolAddress, SessionRecord?> = LinkedHashMap(addresses.size)
|
||||||
|
|
||||||
for (address in addresses) {
|
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
|
sessions[address] = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,10 +97,10 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
|
||||||
return sessions.values.toList()
|
return sessions.values.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllFor(accountId: AccountIdentifier, addressName: String): List<SessionRow> {
|
fun getAllFor(serviceId: ServiceId, addressName: String): List<SessionRow> {
|
||||||
val results: MutableList<SessionRow> = mutableListOf()
|
val results: MutableList<SessionRow> = 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()) {
|
while (cursor.moveToNext()) {
|
||||||
try {
|
try {
|
||||||
results.add(
|
results.add(
|
||||||
|
@ -118,12 +118,12 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllFor(accountId: AccountIdentifier, addressNames: List<String?>): List<SessionRow> {
|
fun getAllFor(serviceId: ServiceId, addressNames: List<String?>): List<SessionRow> {
|
||||||
val query: SqlUtil.Query = SqlUtil.buildCollectionQuery(ADDRESS, addressNames)
|
val query: SqlUtil.Query = SqlUtil.buildCollectionQuery(ADDRESS, addressNames)
|
||||||
val results: MutableList<SessionRow> = LinkedList()
|
val results: MutableList<SessionRow> = LinkedList()
|
||||||
|
|
||||||
val queryString = "$ACCOUNT_ID = ? AND (${query.where})"
|
val queryString = "$ACCOUNT_ID = ? AND (${query.where})"
|
||||||
val queryArgs: Array<String> = arrayOf(accountId.toString()) + query.whereArgs
|
val queryArgs: Array<String> = arrayOf(serviceId.toString()) + query.whereArgs
|
||||||
|
|
||||||
readableDatabase.query(TABLE_NAME, null, queryString, queryArgs, null, null, null).use { cursor ->
|
readableDatabase.query(TABLE_NAME, null, queryString, queryArgs, null, null, null).use { cursor ->
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
|
@ -143,10 +143,10 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAll(accountId: AccountIdentifier): List<SessionRow> {
|
fun getAll(serviceId: ServiceId): List<SessionRow> {
|
||||||
val results: MutableList<SessionRow> = mutableListOf()
|
val results: MutableList<SessionRow> = 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()) {
|
while (cursor.moveToNext()) {
|
||||||
try {
|
try {
|
||||||
results.add(
|
results.add(
|
||||||
|
@ -164,10 +164,10 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSubDevices(accountId: AccountIdentifier, addressName: String): List<Int> {
|
fun getSubDevices(serviceId: ServiceId, addressName: String): List<Int> {
|
||||||
val projection = arrayOf(DEVICE)
|
val projection = arrayOf(DEVICE)
|
||||||
val selection = "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $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<Int> = mutableListOf()
|
val results: MutableList<Int> = mutableListOf()
|
||||||
|
|
||||||
|
@ -179,17 +179,17 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
fun delete(accountId: AccountIdentifier, address: SignalProtocolAddress) {
|
fun delete(serviceId: ServiceId, address: SignalProtocolAddress) {
|
||||||
writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?", SqlUtil.buildArgs(accountId, address.name, address.deviceId))
|
writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?", SqlUtil.buildArgs(serviceId, address.name, address.deviceId))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteAllFor(accountId: AccountIdentifier, addressName: String) {
|
fun deleteAllFor(serviceId: ServiceId, addressName: String) {
|
||||||
writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $ADDRESS = ?", SqlUtil.buildArgs(accountId, addressName))
|
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 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 ->
|
readableDatabase.query(TABLE_NAME, arrayOf("1"), query, args, null, null, null, "1").use { cursor ->
|
||||||
return cursor.moveToFirst()
|
return cursor.moveToFirst()
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import org.whispersystems.libsignal.InvalidKeyException
|
||||||
import org.whispersystems.libsignal.ecc.Curve
|
import org.whispersystems.libsignal.ecc.Curve
|
||||||
import org.whispersystems.libsignal.ecc.ECKeyPair
|
import org.whispersystems.libsignal.ecc.ECKeyPair
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord
|
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.io.IOException
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ class SignedPreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : D
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
fun get(accountId: AccountIdentifier, keyId: Int): SignedPreKeyRecord? {
|
fun get(serviceId: ServiceId, keyId: Int): SignedPreKeyRecord? {
|
||||||
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(accountId, keyId), null, null, null).use { cursor ->
|
readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId), null, null, null).use { cursor ->
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
try {
|
try {
|
||||||
val publicKey = Curve.decodePoint(Base64.decode(cursor.requireNonNullString(PUBLIC_KEY)), 0)
|
val publicKey = Curve.decodePoint(Base64.decode(cursor.requireNonNullString(PUBLIC_KEY)), 0)
|
||||||
|
@ -58,10 +58,10 @@ class SignedPreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : D
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAll(accountId: AccountIdentifier): List<SignedPreKeyRecord> {
|
fun getAll(serviceId: ServiceId): List<SignedPreKeyRecord> {
|
||||||
val results: MutableList<SignedPreKeyRecord> = LinkedList()
|
val results: MutableList<SignedPreKeyRecord> = 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()) {
|
while (cursor.moveToNext()) {
|
||||||
try {
|
try {
|
||||||
val keyId = cursor.requireInt(KEY_ID)
|
val keyId = cursor.requireInt(KEY_ID)
|
||||||
|
@ -81,9 +81,9 @@ class SignedPreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : D
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
fun insert(accountId: AccountIdentifier, keyId: Int, record: SignedPreKeyRecord) {
|
fun insert(serviceId: ServiceId, keyId: Int, record: SignedPreKeyRecord) {
|
||||||
val contentValues = contentValuesOf(
|
val contentValues = contentValuesOf(
|
||||||
ACCOUNT_ID to accountId.toString(),
|
ACCOUNT_ID to serviceId.toString(),
|
||||||
KEY_ID to keyId,
|
KEY_ID to keyId,
|
||||||
PUBLIC_KEY to Base64.encodeBytes(record.keyPair.publicKey.serialize()),
|
PUBLIC_KEY to Base64.encodeBytes(record.keyPair.publicKey.serialize()),
|
||||||
PRIVATE_KEY to Base64.encodeBytes(record.keyPair.privateKey.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)
|
writableDatabase.replace(TABLE_NAME, null, contentValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun delete(accountId: AccountIdentifier, keyId: Int) {
|
fun delete(serviceId: ServiceId, keyId: Int) {
|
||||||
writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(accountId, keyId))
|
writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -719,11 +719,11 @@ public class SmsDatabase extends MessageDatabase {
|
||||||
|
|
||||||
if (!peerEraIdSameAsPrevious && !Util.isEmpty(peekGroupCallEraId)) {
|
if (!peerEraIdSameAsPrevious && !Util.isEmpty(peekGroupCallEraId)) {
|
||||||
Recipient self = Recipient.self();
|
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()
|
byte[] updateDetails = GroupCallUpdateDetails.newBuilder()
|
||||||
.setEraId(Util.emptyIfNull(peekGroupCallEraId))
|
.setEraId(Util.emptyIfNull(peekGroupCallEraId))
|
||||||
.setStartedCallUuid(Recipient.resolved(sender).requireAci().toString())
|
.setStartedCallUuid(Recipient.resolved(sender).requireServiceId().toString())
|
||||||
.setStartedCallTimestamp(timestamp)
|
.setStartedCallTimestamp(timestamp)
|
||||||
.addAllInCallUuids(Stream.of(peekJoinedUuids).map(UUID::toString).toList())
|
.addAllInCallUuids(Stream.of(peekJoinedUuids).map(UUID::toString).toList())
|
||||||
.setIsCallFull(isCallFull)
|
.setIsCallFull(isCallFull)
|
||||||
|
@ -800,7 +800,7 @@ public class SmsDatabase extends MessageDatabase {
|
||||||
if (!sameEraId && !Util.isEmpty(messageGroupCallEraId)) {
|
if (!sameEraId && !Util.isEmpty(messageGroupCallEraId)) {
|
||||||
byte[] updateDetails = GroupCallUpdateDetails.newBuilder()
|
byte[] updateDetails = GroupCallUpdateDetails.newBuilder()
|
||||||
.setEraId(Util.emptyIfNull(messageGroupCallEraId))
|
.setEraId(Util.emptyIfNull(messageGroupCallEraId))
|
||||||
.setStartedCallUuid(Recipient.resolved(sender).requireAci().toString())
|
.setStartedCallUuid(Recipient.resolved(sender).requireServiceId().toString())
|
||||||
.setStartedCallTimestamp(timestamp)
|
.setStartedCallTimestamp(timestamp)
|
||||||
.addAllInCallUuids(Collections.emptyList())
|
.addAllInCallUuids(Collections.emptyList())
|
||||||
.setIsCallFull(false)
|
.setIsCallFull(false)
|
||||||
|
@ -849,7 +849,7 @@ public class SmsDatabase extends MessageDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupCallUpdateDetails groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(record.getBody());
|
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);
|
sameEraId = groupCallUpdateDetails.getEraId().equals(peekGroupCallEraId) && !Util.isEmpty(peekGroupCallEraId);
|
||||||
|
|
||||||
|
|
|
@ -1208,7 +1208,7 @@ public class ThreadDatabase extends Database {
|
||||||
Recipient pinnedRecipient;
|
Recipient pinnedRecipient;
|
||||||
|
|
||||||
if (pinned.getContact().isPresent()) {
|
if (pinned.getContact().isPresent()) {
|
||||||
pinnedRecipient = Recipient.externalPush(context, pinned.getContact().get());
|
pinnedRecipient = Recipient.externalPush(pinned.getContact().get());
|
||||||
} else if (pinned.getGroupV1Id().isPresent()) {
|
} else if (pinned.getGroupV1Id().isPresent()) {
|
||||||
try {
|
try {
|
||||||
pinnedRecipient = Recipient.externalGroupExact(context, GroupId.v1(pinned.getGroupV1Id().get()));
|
pinnedRecipient = Recipient.externalGroupExact(context, GroupId.v1(pinned.getGroupV1Id().get()));
|
||||||
|
|
|
@ -6,11 +6,12 @@ import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateDetails;
|
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.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.util.DateUtils;
|
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.ACI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -22,13 +23,13 @@ import java.util.Objects;
|
||||||
*/
|
*/
|
||||||
public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFactory {
|
public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFactory {
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final List<ACI> joinedMembers;
|
private final List<ServiceId> joinedMembers;
|
||||||
private final boolean withTime;
|
private final boolean withTime;
|
||||||
private final GroupCallUpdateDetails groupCallUpdateDetails;
|
private final GroupCallUpdateDetails groupCallUpdateDetails;
|
||||||
private final ACI selfAci;
|
private final ACI selfAci;
|
||||||
|
|
||||||
public GroupCallUpdateMessageFactory(@NonNull Context context,
|
public GroupCallUpdateMessageFactory(@NonNull Context context,
|
||||||
@NonNull List<ACI> joinedMembers,
|
@NonNull List<ServiceId> joinedMembers,
|
||||||
boolean withTime,
|
boolean withTime,
|
||||||
@NonNull GroupCallUpdateDetails groupCallUpdateDetails)
|
@NonNull GroupCallUpdateDetails groupCallUpdateDetails)
|
||||||
{
|
{
|
||||||
|
@ -36,7 +37,7 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFa
|
||||||
this.joinedMembers = new ArrayList<>(joinedMembers);
|
this.joinedMembers = new ArrayList<>(joinedMembers);
|
||||||
this.withTime = withTime;
|
this.withTime = withTime;
|
||||||
this.groupCallUpdateDetails = groupCallUpdateDetails;
|
this.groupCallUpdateDetails = groupCallUpdateDetails;
|
||||||
this.selfAci = Recipient.self().requireAci();
|
this.selfAci = SignalStore.account().requireAci();
|
||||||
|
|
||||||
boolean removed = this.joinedMembers.remove(selfAci);
|
boolean removed = this.joinedMembers.remove(selfAci);
|
||||||
if (removed) {
|
if (removed) {
|
||||||
|
@ -87,12 +88,12 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private @NonNull String describe(@NonNull ACI aci) {
|
private @NonNull String describe(@NonNull ServiceId serviceId) {
|
||||||
if (aci.isUnknown()) {
|
if (serviceId.isUnknown()) {
|
||||||
return context.getString(R.string.MessageRecord_unknown);
|
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()) {
|
if (recipient.isSelf()) {
|
||||||
return context.getString(R.string.MessageRecord_you);
|
return context.getString(R.string.MessageRecord_you);
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.util.StringUtil;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.api.util.UuidUtil;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -746,11 +747,11 @@ final class GroupsV2UpdateMessageProducer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map an ACI to a string that describes the group member.
|
* Map an ACI to a string that describes the group member.
|
||||||
* @param aci
|
* @param serviceId
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
String describe(@NonNull ACI aci);
|
String describe(@NonNull ServiceId serviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface StringFactory1Arg {
|
private interface StringFactory1Arg {
|
||||||
|
@ -771,9 +772,9 @@ final class GroupsV2UpdateMessageProducer {
|
||||||
@NonNull StringFactory1Arg stringFactory,
|
@NonNull StringFactory1Arg stringFactory,
|
||||||
@DrawableRes int iconResource)
|
@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,
|
private UpdateDescription updateDescription(@NonNull ByteString uuid1Bytes,
|
||||||
|
@ -781,9 +782,9 @@ final class GroupsV2UpdateMessageProducer {
|
||||||
@NonNull StringFactory2Args stringFactory,
|
@NonNull StringFactory2Args stringFactory,
|
||||||
@DrawableRes int iconResource)
|
@DrawableRes int iconResource)
|
||||||
{
|
{
|
||||||
ACI aci1 = ACI.fromByteStringOrUnknown(uuid1Bytes);
|
ServiceId sid1 = ServiceId.fromByteStringOrUnknown(uuid1Bytes);
|
||||||
ACI aci2 = ACI.fromByteStringOrUnknown(uuid2Bytes);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -60,7 +60,7 @@ import org.thoughtcrime.securesms.util.StringUtil;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.libsignal.util.guava.Function;
|
import org.whispersystems.libsignal.util.guava.Function;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
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.api.util.UuidUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -253,7 +253,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||||
|
|
||||||
private static boolean selfCreatedGroup(@NonNull DecryptedGroupChange change) {
|
private static boolean selfCreatedGroup(@NonNull DecryptedGroupChange change) {
|
||||||
return change.getRevision() == 0 &&
|
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) {
|
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);
|
ShortStringDescriptionStrategy descriptionStrategy = new ShortStringDescriptionStrategy(context);
|
||||||
byte[] decoded = Base64.decode(body);
|
byte[] decoded = Base64.decode(body);
|
||||||
DecryptedGroupV2Context decryptedGroupV2Context = DecryptedGroupV2Context.parseFrom(decoded);
|
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())) {
|
if (decryptedGroupV2Context.hasChange() && (decryptedGroupV2Context.getGroupState().getRevision() != 0 || decryptedGroupV2Context.hasPreviousGroupState())) {
|
||||||
return UpdateDescription.concatWithNewLines(updateMessageProducer.describeChanges(decryptedGroupV2Context.getPreviousGroupState(), decryptedGroupV2Context.getChange()));
|
return UpdateDescription.concatWithNewLines(updateMessageProducer.describeChanges(decryptedGroupV2Context.getPreviousGroupState(), decryptedGroupV2Context.getChange()));
|
||||||
|
@ -292,7 +292,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||||
}
|
}
|
||||||
|
|
||||||
DecryptedGroup groupState = decryptedGroupV2Context.getGroupState();
|
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()) {
|
if (decryptedGroupV2Context.hasChange()) {
|
||||||
UUID changeEditor = UuidUtil.fromByteStringOrNull(decryptedGroupV2Context.getChange().getEditor());
|
UUID changeEditor = UuidUtil.fromByteStringOrNull(decryptedGroupV2Context.getChange().getEditor());
|
||||||
|
@ -314,7 +314,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||||
@NonNull Function<Recipient, String> stringGenerator,
|
@NonNull Function<Recipient, String> stringGenerator,
|
||||||
@DrawableRes int iconResource)
|
@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()),
|
() -> stringGenerator.apply(recipient.resolve()),
|
||||||
iconResource);
|
iconResource);
|
||||||
}
|
}
|
||||||
|
@ -382,11 +382,11 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||||
public static @NonNull UpdateDescription getGroupCallUpdateDescription(@NonNull Context context, @NonNull String body, boolean withTime) {
|
public static @NonNull UpdateDescription getGroupCallUpdateDescription(@NonNull Context context, @NonNull String body, boolean withTime) {
|
||||||
GroupCallUpdateDetails groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(body);
|
GroupCallUpdateDetails groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(body);
|
||||||
|
|
||||||
List<ACI> joinedMembers = Stream.of(groupCallUpdateDetails.getInCallUuidsList())
|
List<ServiceId> joinedMembers = Stream.of(groupCallUpdateDetails.getInCallUuidsList())
|
||||||
.map(UuidUtil::parseOrNull)
|
.map(UuidUtil::parseOrNull)
|
||||||
.withoutNulls()
|
.withoutNulls()
|
||||||
.map(ACI::from)
|
.map(ServiceId::from)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
UpdateDescription.StringFactory stringFactory = new GroupCallUpdateMessageFactory(context, joinedMembers, withTime, groupCallUpdateDetails);
|
UpdateDescription.StringFactory stringFactory = new GroupCallUpdateMessageFactory(context, joinedMembers, withTime, groupCallUpdateDetails);
|
||||||
|
|
||||||
|
@ -421,11 +421,11 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NonNull String describe(@NonNull ACI aci) {
|
public @NonNull String describe(@NonNull ServiceId serviceId) {
|
||||||
if (aci.isUnknown()) {
|
if (serviceId.isUnknown()) {
|
||||||
return context.getString(R.string.MessageRecord_unknown);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,15 +20,15 @@ import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper
|
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper
|
||||||
import org.whispersystems.libsignal.util.guava.Optional
|
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.PNI
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database model for [RecipientDatabase].
|
* Database model for [RecipientDatabase].
|
||||||
*/
|
*/
|
||||||
data class RecipientRecord(
|
data class RecipientRecord(
|
||||||
val id: RecipientId,
|
val id: RecipientId,
|
||||||
val aci: ACI?,
|
val serviceId: ServiceId?,
|
||||||
val pni: PNI?,
|
val pni: PNI?,
|
||||||
val username: String?,
|
val username: String?,
|
||||||
val e164: String?,
|
val e164: String?,
|
||||||
|
|
|
@ -9,6 +9,7 @@ import androidx.annotation.WorkerThread;
|
||||||
|
|
||||||
import org.signal.core.util.ThreadUtil;
|
import org.signal.core.util.ThreadUtil;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.api.util.UuidUtil;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -28,14 +29,14 @@ public final class UpdateDescription {
|
||||||
String create();
|
String create();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Collection<ACI> mentioned;
|
private final Collection<ServiceId> mentioned;
|
||||||
private final StringFactory stringFactory;
|
private final StringFactory stringFactory;
|
||||||
private final String staticString;
|
private final String staticString;
|
||||||
private final int lightIconResource;
|
private final int lightIconResource;
|
||||||
private final int lightTint;
|
private final int lightTint;
|
||||||
private final int darkTint;
|
private final int darkTint;
|
||||||
|
|
||||||
private UpdateDescription(@NonNull Collection<ACI> mentioned,
|
private UpdateDescription(@NonNull Collection<ServiceId> mentioned,
|
||||||
@Nullable StringFactory stringFactory,
|
@Nullable StringFactory stringFactory,
|
||||||
@Nullable String staticString,
|
@Nullable String staticString,
|
||||||
@DrawableRes int iconResource,
|
@DrawableRes int iconResource,
|
||||||
|
@ -60,11 +61,11 @@ public final class UpdateDescription {
|
||||||
* @param mentioned UUIDs of recipients that are mentioned in the string.
|
* @param mentioned UUIDs of recipients that are mentioned in the string.
|
||||||
* @param stringFactory The background method for generating the string.
|
* @param stringFactory The background method for generating the string.
|
||||||
*/
|
*/
|
||||||
public static UpdateDescription mentioning(@NonNull Collection<ACI> mentioned,
|
public static UpdateDescription mentioning(@NonNull Collection<ServiceId> mentioned,
|
||||||
@NonNull StringFactory stringFactory,
|
@NonNull StringFactory stringFactory,
|
||||||
@DrawableRes int iconResource)
|
@DrawableRes int iconResource)
|
||||||
{
|
{
|
||||||
return new UpdateDescription(ACI.filterKnown(mentioned),
|
return new UpdateDescription(ServiceId.filterKnown(mentioned),
|
||||||
stringFactory,
|
stringFactory,
|
||||||
null,
|
null,
|
||||||
iconResource,
|
iconResource,
|
||||||
|
@ -118,7 +119,7 @@ public final class UpdateDescription {
|
||||||
}
|
}
|
||||||
|
|
||||||
@AnyThread
|
@AnyThread
|
||||||
public Collection<ACI> getMentioned() {
|
public Collection<ServiceId> getMentioned() {
|
||||||
return mentioned;
|
return mentioned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +150,7 @@ public final class UpdateDescription {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<ACI> allMentioned = new HashSet<>();
|
Set<ServiceId> allMentioned = new HashSet<>();
|
||||||
|
|
||||||
for (UpdateDescription updateDescription : updateDescriptions) {
|
for (UpdateDescription updateDescription : updateDescriptions) {
|
||||||
allMentioned.addAll(updateDescription.getMentioned());
|
allMentioned.addAll(updateDescription.getMentioned());
|
||||||
|
|
|
@ -104,7 +104,7 @@ final class GroupManagerV2 {
|
||||||
this.groupsV2Operations = ApplicationDependencies.getGroupsV2Operations();
|
this.groupsV2Operations = ApplicationDependencies.getGroupsV2Operations();
|
||||||
this.authorization = ApplicationDependencies.getGroupsV2Authorization();
|
this.authorization = ApplicationDependencies.getGroupsV2Authorization();
|
||||||
this.groupsV2StateProcessor = ApplicationDependencies.getGroupsV2StateProcessor();
|
this.groupsV2StateProcessor = ApplicationDependencies.getGroupsV2StateProcessor();
|
||||||
this.selfAci = Recipient.self().requireAci();
|
this.selfAci = SignalStore.account().requireAci();
|
||||||
this.groupCandidateHelper = new GroupCandidateHelper(context);
|
this.groupCandidateHelper = new GroupCandidateHelper(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ final class GroupManagerV2 {
|
||||||
|
|
||||||
Map<UUID, UuidCiphertext> uuidCipherTexts = new HashMap<>();
|
Map<UUID, UuidCiphertext> uuidCipherTexts = new HashMap<>();
|
||||||
for (Recipient recipient : recipients) {
|
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;
|
return uuidCipherTexts;
|
||||||
|
@ -389,7 +389,7 @@ final class GroupManagerV2 {
|
||||||
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
|
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
|
||||||
{
|
{
|
||||||
Set<UUID> uuids = Stream.of(recipientIds)
|
Set<UUID> uuids = Stream.of(recipientIds)
|
||||||
.map(r -> Recipient.resolved(r).requireAci().uuid())
|
.map(r -> Recipient.resolved(r).requireServiceId().uuid())
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
return commitChangeWithConflictResolution(groupOperations.createApproveGroupJoinRequest(uuids));
|
return commitChangeWithConflictResolution(groupOperations.createApproveGroupJoinRequest(uuids));
|
||||||
|
@ -400,7 +400,7 @@ final class GroupManagerV2 {
|
||||||
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
|
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
|
||||||
{
|
{
|
||||||
Set<UUID> uuids = Stream.of(recipientIds)
|
Set<UUID> uuids = Stream.of(recipientIds)
|
||||||
.map(r -> Recipient.resolved(r).requireAci().uuid())
|
.map(r -> Recipient.resolved(r).requireServiceId().uuid())
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
return commitChangeWithConflictResolution(groupOperations.createRefuseGroupJoinRequest(uuids));
|
return commitChangeWithConflictResolution(groupOperations.createRefuseGroupJoinRequest(uuids));
|
||||||
|
@ -412,7 +412,7 @@ final class GroupManagerV2 {
|
||||||
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
|
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException
|
||||||
{
|
{
|
||||||
Recipient recipient = Recipient.resolved(recipientId);
|
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
|
@WorkerThread
|
||||||
|
@ -441,7 +441,7 @@ final class GroupManagerV2 {
|
||||||
{
|
{
|
||||||
Recipient recipient = Recipient.resolved(recipientId);
|
Recipient recipient = Recipient.resolved(recipientId);
|
||||||
|
|
||||||
return commitChangeWithConflictResolution(groupOperations.createRemoveMembersChange(Collections.singleton(recipient.requireAci().uuid())));
|
return commitChangeWithConflictResolution(groupOperations.createRemoveMembersChange(Collections.singleton(recipient.requireServiceId().uuid())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
|
@ -449,7 +449,7 @@ final class GroupManagerV2 {
|
||||||
throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException
|
throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException
|
||||||
{
|
{
|
||||||
Recipient self = Recipient.self();
|
Recipient self = Recipient.self();
|
||||||
List<UUID> newAdminRecipients = Stream.of(newAdmins).map(id -> Recipient.resolved(id).requireAci().uuid()).toList();
|
List<UUID> newAdminRecipients = Stream.of(newAdmins).map(id -> Recipient.resolved(id).requireServiceId().uuid()).toList();
|
||||||
|
|
||||||
return commitChangeWithConflictResolution(groupOperations.createLeaveAndPromoteMembersToAdmin(selfAci.uuid(),
|
return commitChangeWithConflictResolution(groupOperations.createLeaveAndPromoteMembersToAdmin(selfAci.uuid(),
|
||||||
newAdminRecipients));
|
newAdminRecipients));
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.PartialDecryptedGroup;
|
import org.whispersystems.signalservice.api.groupsv2.PartialDecryptedGroup;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.api.util.UuidUtil;
|
||||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
|
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
|
||||||
|
|
||||||
|
@ -85,24 +86,24 @@ public final class GroupProtoUtil {
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public static Recipient uuidByteStringToRecipient(@NonNull Context context, @NonNull ByteString uuidByteString) {
|
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.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Recipient.externalPush(context, aci, null, false);
|
return Recipient.externalPush(serviceId, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public static @NonNull RecipientId uuidByteStringToRecipientId(@NonNull ByteString uuidByteString) {
|
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.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RecipientId.from(aci, null);
|
return RecipientId.from(serviceId, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isMember(@NonNull UUID uuid, @NonNull List<DecryptedMember> membersList) {
|
public static boolean isMember(@NonNull UUID uuid, @NonNull List<DecryptedMember> membersList) {
|
||||||
|
|
|
@ -99,7 +99,7 @@ public final class GroupV1MessageProcessor {
|
||||||
|
|
||||||
if (group.getMembers().isPresent()) {
|
if (group.getMembers().isPresent()) {
|
||||||
for (SignalServiceAddress member : group.getMembers().get()) {
|
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()) {
|
if (group.getMembers().isPresent()) {
|
||||||
for (SignalServiceAddress messageMember : group.getMembers().get()) {
|
for (SignalServiceAddress messageMember : group.getMembers().get()) {
|
||||||
messageMembers.add(Recipient.externalGV1Member(context, messageMember).getId());
|
messageMembers.add(Recipient.externalGV1Member(messageMember).getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -232,7 +232,7 @@ public final class GroupsV1MigrationUtil {
|
||||||
* True if the user meets all the requirements to be auto-migrated, otherwise false.
|
* True if the user meets all the requirements to be auto-migrated, otherwise false.
|
||||||
*/
|
*/
|
||||||
public static boolean isAutoMigratable(@NonNull Recipient recipient) {
|
public static boolean isAutoMigratable(@NonNull Recipient recipient) {
|
||||||
return recipient.hasAci() &&
|
return recipient.hasServiceId() &&
|
||||||
recipient.getGroupsV2Capability() == Recipient.Capability.SUPPORTED &&
|
recipient.getGroupsV2Capability() == Recipient.Capability.SUPPORTED &&
|
||||||
recipient.getGroupsV1MigrationCapability() == Recipient.Capability.SUPPORTED &&
|
recipient.getGroupsV1MigrationCapability() == Recipient.Capability.SUPPORTED &&
|
||||||
recipient.getRegistered() == RecipientDatabase.RegisteredState.REGISTERED &&
|
recipient.getRegistered() == RecipientDatabase.RegisteredState.REGISTERED &&
|
||||||
|
|
|
@ -91,7 +91,7 @@ public final class GroupsV2CapabilityChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!member.hasAci()) {
|
if (!member.hasServiceId()) {
|
||||||
noUuidCount++;
|
noUuidCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
|
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.api.util.UuidUtil;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -109,7 +110,7 @@ public final class LiveGroup {
|
||||||
|
|
||||||
return Stream.of(requestingMembersList)
|
return Stream.of(requestingMembersList)
|
||||||
.map(requestingMember -> {
|
.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);
|
return new GroupMemberEntry.RequestingMember(recipient, selfAdmin);
|
||||||
})
|
})
|
||||||
.toList();
|
.toList();
|
||||||
|
|
|
@ -54,7 +54,7 @@ final class PendingMemberInvitesRepository {
|
||||||
List<DecryptedPendingMember> pendingMembersList = decryptedGroup.getPendingMembersList();
|
List<DecryptedPendingMember> pendingMembersList = decryptedGroup.getPendingMembersList();
|
||||||
List<SinglePendingMemberInvitedByYou> byMe = new ArrayList<>(pendingMembersList.size());
|
List<SinglePendingMemberInvitedByYou> byMe = new ArrayList<>(pendingMembersList.size());
|
||||||
List<MultiplePendingMembersInvitedByAnother> byOthers = new ArrayList<>(pendingMembersList.size());
|
List<MultiplePendingMembersInvitedByAnother> byOthers = new ArrayList<>(pendingMembersList.size());
|
||||||
ByteString self = Recipient.self().requireAci().toByteString();
|
ByteString self = Recipient.self().requireServiceId().toByteString();
|
||||||
boolean selfIsAdmin = v2GroupProperties.isAdmin(Recipient.self());
|
boolean selfIsAdmin = v2GroupProperties.isAdmin(Recipient.self());
|
||||||
|
|
||||||
Stream.of(pendingMembersList)
|
Stream.of(pendingMembersList)
|
||||||
|
|
|
@ -95,7 +95,7 @@ final class GroupsV1MigrationRepository {
|
||||||
group = group.fresh();
|
group = group.fresh();
|
||||||
|
|
||||||
List<Recipient> ineligible = Stream.of(group.getParticipants())
|
List<Recipient> ineligible = Stream.of(group.getParticipants())
|
||||||
.filter(r -> !r.hasAci() ||
|
.filter(r -> !r.hasServiceId() ||
|
||||||
r.getGroupsV2Capability() != Recipient.Capability.SUPPORTED ||
|
r.getGroupsV2Capability() != Recipient.Capability.SUPPORTED ||
|
||||||
r.getGroupsV1MigrationCapability() != Recipient.Capability.SUPPORTED ||
|
r.getGroupsV1MigrationCapability() != Recipient.Capability.SUPPORTED ||
|
||||||
r.getRegistered() != RecipientDatabase.RegisteredState.REGISTERED)
|
r.getRegistered() != RecipientDatabase.RegisteredState.REGISTERED)
|
||||||
|
|
|
@ -18,6 +18,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.GroupCandidate;
|
import org.whispersystems.signalservice.api.groupsv2.GroupCandidate;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ACI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -47,13 +48,13 @@ public final class GroupCandidateHelper {
|
||||||
{
|
{
|
||||||
final Recipient recipient = Recipient.resolved(recipientId);
|
final Recipient recipient = Recipient.resolved(recipientId);
|
||||||
|
|
||||||
ACI aci = recipient.getAci().orNull();
|
ServiceId serviceId = recipient.getServiceId().orNull();
|
||||||
if (aci == null) {
|
if (serviceId == null) {
|
||||||
throw new AssertionError("Non UUID members should have need detected by now");
|
throw new AssertionError("Non UUID members should have need detected by now");
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<ProfileKeyCredential> profileKeyCredential = Optional.fromNullable(recipient.getProfileKeyCredential());
|
Optional<ProfileKeyCredential> profileKeyCredential = Optional.fromNullable(recipient.getProfileKeyCredential());
|
||||||
GroupCandidate candidate = new GroupCandidate(aci.uuid(), profileKeyCredential);
|
GroupCandidate candidate = new GroupCandidate(serviceId.uuid(), profileKeyCredential);
|
||||||
|
|
||||||
if (!candidate.hasProfileKeyCredential()) {
|
if (!candidate.hasProfileKeyCredential()) {
|
||||||
ProfileKey profileKey = ProfileKeyUtil.profileKeyOrNull(recipient.getProfileKey());
|
ProfileKey profileKey = ProfileKeyUtil.profileKeyOrNull(recipient.getProfileKey());
|
||||||
|
@ -61,7 +62,7 @@ public final class GroupCandidateHelper {
|
||||||
if (profileKey != null) {
|
if (profileKey != null) {
|
||||||
Log.i(TAG, String.format("No profile key credential on recipient %s, fetching", recipient.getId()));
|
Log.i(TAG, String.format("No profile key credential on recipient %s, fetching", recipient.getId()));
|
||||||
|
|
||||||
Optional<ProfileKeyCredential> profileKeyCredentialOptional = signalServiceAccountManager.resolveProfileKeyCredential(aci, profileKey, Locale.getDefault());
|
Optional<ProfileKeyCredential> profileKeyCredentialOptional = signalServiceAccountManager.resolveProfileKeyCredential(serviceId, profileKey, Locale.getDefault());
|
||||||
|
|
||||||
if (profileKeyCredentialOptional.isPresent()) {
|
if (profileKeyCredentialOptional.isPresent()) {
|
||||||
boolean updatedProfileKey = recipientDatabase.setProfileKeyCredential(recipient.getId(), profileKey, profileKeyCredentialOptional.get());
|
boolean updatedProfileKey = recipientDatabase.setProfileKeyCredential(recipient.getId(), profileKey, profileKeyCredentialOptional.get());
|
||||||
|
|
|
@ -103,7 +103,7 @@ public final class GroupsV2StateProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public StateProcessorForGroup forGroup(@NonNull GroupMasterKey groupMasterKey) {
|
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);
|
ProfileAndMessageHelper profileAndMessageHelper = new ProfileAndMessageHelper(context, selfAci, groupMasterKey, GroupId.v2(groupMasterKey), recipientDatabase);
|
||||||
|
|
||||||
return new StateProcessorForGroup(selfAci, context, groupDatabase, groupsV2Api, groupsV2Authorization, groupMasterKey, profileAndMessageHelper);
|
return new StateProcessorForGroup(selfAci, context, groupDatabase, groupsV2Api, groupsV2Authorization, groupMasterKey, profileAndMessageHelper);
|
||||||
|
@ -546,14 +546,14 @@ public final class GroupsV2StateProcessor {
|
||||||
static class ProfileAndMessageHelper {
|
static class ProfileAndMessageHelper {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final ACI aci;
|
private final ACI selfAci;
|
||||||
private final GroupMasterKey masterKey;
|
private final GroupMasterKey masterKey;
|
||||||
private final GroupId.V2 groupId;
|
private final GroupId.V2 groupId;
|
||||||
private final RecipientDatabase recipientDatabase;
|
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.context = context;
|
||||||
this.aci = aci;
|
this.selfAci = selfAci;
|
||||||
this.masterKey = masterKey;
|
this.masterKey = masterKey;
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
this.recipientDatabase = recipientDatabase;
|
this.recipientDatabase = recipientDatabase;
|
||||||
|
@ -561,14 +561,14 @@ public final class GroupsV2StateProcessor {
|
||||||
|
|
||||||
void determineProfileSharing(@NonNull GlobalGroupState inputGroupState, @NonNull DecryptedGroup newLocalState) {
|
void determineProfileSharing(@NonNull GlobalGroupState inputGroupState, @NonNull DecryptedGroup newLocalState) {
|
||||||
if (inputGroupState.getLocalState() != null) {
|
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) {
|
if (wasAMemberAlready) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<DecryptedMember> selfAsMemberOptional = DecryptedGroupUtil.findMemberByUuid(newLocalState.getMembersList(), aci.uuid());
|
Optional<DecryptedMember> selfAsMemberOptional = DecryptedGroupUtil.findMemberByUuid(newLocalState.getMembersList(), selfAci.uuid());
|
||||||
|
|
||||||
if (selfAsMemberOptional.isPresent()) {
|
if (selfAsMemberOptional.isPresent()) {
|
||||||
DecryptedMember selfAsMember = selfAsMemberOptional.get();
|
DecryptedMember selfAsMember = selfAsMemberOptional.get();
|
||||||
|
@ -579,7 +579,7 @@ public final class GroupsV2StateProcessor {
|
||||||
.filter(c -> c != null && c.getRevision() == revisionJoinedAt)
|
.filter(c -> c != null && c.getRevision() == revisionJoinedAt)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.map(c -> Optional.fromNullable(UuidUtil.fromByteStringOrNull(c.getEditor()))
|
.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());
|
.orElse(Optional.absent());
|
||||||
|
|
||||||
if (addedByOptional.isPresent()) {
|
if (addedByOptional.isPresent()) {
|
||||||
|
@ -652,7 +652,7 @@ public final class GroupsV2StateProcessor {
|
||||||
void storeMessage(@NonNull DecryptedGroupV2Context decryptedGroupV2Context, long timestamp) {
|
void storeMessage(@NonNull DecryptedGroupV2Context decryptedGroupV2Context, long timestamp) {
|
||||||
Optional<ACI> editor = getEditor(decryptedGroupV2Context).transform(ACI::from);
|
Optional<ACI> editor = getEditor(decryptedGroupV2Context).transform(ACI::from);
|
||||||
|
|
||||||
boolean outgoing = !editor.isPresent() || aci.equals(editor.get());
|
boolean outgoing = !editor.isPresent() || selfAci.equals(editor.get());
|
||||||
|
|
||||||
if (outgoing) {
|
if (outgoing) {
|
||||||
try {
|
try {
|
||||||
|
@ -690,7 +690,7 @@ public final class GroupsV2StateProcessor {
|
||||||
if (changeEditor.isPresent()) {
|
if (changeEditor.isPresent()) {
|
||||||
return changeEditor;
|
return changeEditor;
|
||||||
} else {
|
} else {
|
||||||
Optional<DecryptedPendingMember> pendingByUuid = DecryptedGroupUtil.findPendingByUuid(decryptedGroupV2Context.getGroupState().getPendingMembersList(), aci.uuid());
|
Optional<DecryptedPendingMember> pendingByUuid = DecryptedGroupUtil.findPendingByUuid(decryptedGroupV2Context.getGroupState().getPendingMembersList(), selfAci.uuid());
|
||||||
if (pendingByUuid.isPresent()) {
|
if (pendingByUuid.isPresent()) {
|
||||||
return Optional.fromNullable(UuidUtil.fromByteStringOrNull(pendingByUuid.get().getAddedByUuid()));
|
return Optional.fromNullable(UuidUtil.fromByteStringOrNull(pendingByUuid.get().getAddedByUuid()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,8 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||||
import org.whispersystems.libsignal.state.SignalProtocolStore;
|
import org.whispersystems.libsignal.state.SignalProtocolStore;
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
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 org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -70,27 +71,27 @@ public class CreateSignedPreKeyJob extends BaseJob {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
createPreKeys(SignalStore.account().getAci(), ApplicationDependencies.getProtocolStore().aci(), SignalStore.account().aciPreKeys());
|
createPreKeys(ServiceIdType.ACI, SignalStore.account().getAci(), ApplicationDependencies.getProtocolStore().aci(), SignalStore.account().aciPreKeys());
|
||||||
createPreKeys(SignalStore.account().getPni(), ApplicationDependencies.getProtocolStore().pni(), SignalStore.account().pniPreKeys());
|
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
|
throws IOException
|
||||||
{
|
{
|
||||||
if (accountId == null) {
|
if (serviceId == null) {
|
||||||
warn(TAG, "AccountId not set!");
|
warn(TAG, "AccountId not set!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metadataStore.isSignedPreKeyRegistered()) {
|
if (metadataStore.isSignedPreKeyRegistered()) {
|
||||||
warn(TAG, "Signed prekey for " + (accountId.isAci() ? "ACI" : "PNI") + " already registered...");
|
warn(TAG, "Signed prekey for " + serviceIdType + " already registered...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
||||||
SignedPreKeyRecord signedPreKeyRecord = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore, true);
|
SignedPreKeyRecord signedPreKeyRecord = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore, true);
|
||||||
|
|
||||||
accountManager.setSignedPreKey(accountId, signedPreKeyRecord);
|
accountManager.setSignedPreKey(serviceIdType, signedPreKeyRecord);
|
||||||
metadataStore.setSignedPreKeyRegistered(true);
|
metadataStore.setSignedPreKeyRegistered(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ public class MultiDeviceBlockedUpdateJob extends BaseJob {
|
||||||
while ((recipient = reader.getNext()) != null) {
|
while ((recipient = reader.getNext()) != null) {
|
||||||
if (recipient.isPushGroup()) {
|
if (recipient.isPushGroup()) {
|
||||||
blockedGroups.add(recipient.requireGroupId().getDecodedId());
|
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));
|
blockedIndividuals.add(RecipientUtil.toSignalServiceAddress(context, recipient));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ class MultiDeviceContactSyncJob(parameters: Parameters, private val attachmentPo
|
||||||
|
|
||||||
var contact: DeviceContact? = deviceContacts.read()
|
var contact: DeviceContact? = deviceContacts.read()
|
||||||
while (contact != null) {
|
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) {
|
if (recipient.isSelf) {
|
||||||
contact = deviceContacts.read()
|
contact = deviceContacts.read()
|
||||||
|
|
|
@ -101,8 +101,8 @@ public class MultiDeviceMessageRequestResponseJob extends BaseJob {
|
||||||
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
|
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
|
||||||
Recipient recipient = Recipient.resolved(threadRecipient);
|
Recipient recipient = Recipient.resolved(threadRecipient);
|
||||||
|
|
||||||
if (!recipient.hasServiceIdentifier()) {
|
if (!recipient.hasServiceId()) {
|
||||||
Log.i(TAG, "Queued for recipient without service identifier");
|
Log.i(TAG, "Queued for recipient without ServiceId");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ public final class MultiDeviceOutgoingPaymentSyncJob extends BaseJob {
|
||||||
|
|
||||||
Optional<SignalServiceAddress> uuid;
|
Optional<SignalServiceAddress> uuid;
|
||||||
if (!defrag && payment.getPayee().hasRecipientId()) {
|
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 {
|
} else {
|
||||||
uuid = Optional.absent();
|
uuid = Optional.absent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,8 +74,8 @@ public final class PushGroupSilentUpdateSendJob extends BaseJob {
|
||||||
|
|
||||||
Set<RecipientId> recipients = Stream.concat(Stream.of(memberUuids), Stream.of(pendingUuids))
|
Set<RecipientId> recipients = Stream.concat(Stream.of(memberUuids), Stream.of(pendingUuids))
|
||||||
.filter(uuid -> !UuidUtil.UNKNOWN_UUID.equals(uuid))
|
.filter(uuid -> !UuidUtil.UNKNOWN_UUID.equals(uuid))
|
||||||
.filter(uuid -> !Recipient.self().requireAci().uuid().equals(uuid))
|
.filter(uuid -> !Recipient.self().requireServiceId().uuid().equals(uuid))
|
||||||
.map(uuid -> Recipient.externalPush(context, ACI.from(uuid), null, false))
|
.map(uuid -> Recipient.externalPush(ACI.from(uuid), null, false))
|
||||||
.filter(recipient -> recipient.getRegistered() != RecipientDatabase.RegisteredState.NOT_REGISTERED)
|
.filter(recipient -> recipient.getRegistered() != RecipientDatabase.RegisteredState.NOT_REGISTERED)
|
||||||
.map(Recipient::getId)
|
.map(Recipient::getId)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
|
@ -41,7 +41,6 @@ import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview;
|
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.messages.shared.SharedContact;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
|
import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
|
||||||
|
@ -75,8 +74,8 @@ public class PushMediaSendJob extends PushSendJob {
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public static void enqueue(@NonNull Context context, @NonNull JobManager jobManager, long messageId, @NonNull Recipient recipient) {
|
public static void enqueue(@NonNull Context context, @NonNull JobManager jobManager, long messageId, @NonNull Recipient recipient) {
|
||||||
try {
|
try {
|
||||||
if (!recipient.hasServiceIdentifier()) {
|
if (!recipient.hasServiceId()) {
|
||||||
throw new AssertionError();
|
throw new AssertionError("No ServiceId!");
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageDatabase database = SignalDatabase.mms();
|
MessageDatabase database = SignalDatabase.mms();
|
||||||
|
@ -226,7 +225,7 @@ public class PushMediaSendJob extends PushSendJob {
|
||||||
.asExpirationUpdate(message.isExpirationUpdate())
|
.asExpirationUpdate(message.isExpirationUpdate())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (Util.equals(SignalStore.account().getAci(), address.getAci())) {
|
if (Util.equals(SignalStore.account().getAci(), address.getServiceId())) {
|
||||||
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
|
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
|
||||||
SendMessageResult result = messageSender.sendSyncMessage(mediaMessage);
|
SendMessageResult result = messageSender.sendSyncMessage(mediaMessage);
|
||||||
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true));
|
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true));
|
||||||
|
|
|
@ -49,17 +49,13 @@ import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||||
import org.thoughtcrime.securesms.util.Hex;
|
import org.thoughtcrime.securesms.util.Hex;
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
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.SignalServiceAttachment;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview;
|
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.messages.shared.SharedContact;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||||
|
@ -70,7 +66,6 @@ import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -409,7 +404,7 @@ public abstract class PushSendJob extends SendJob {
|
||||||
|
|
||||||
List<SignalServiceDataMessage.Mention> getMentionsFor(@NonNull List<Mention> mentions) {
|
List<SignalServiceDataMessage.Mention> getMentionsFor(@NonNull List<Mention> mentions) {
|
||||||
return Stream.of(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();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
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.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
|
import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
|
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
|
||||||
|
@ -188,7 +187,7 @@ public class PushTextSendJob extends PushSendJob {
|
||||||
.asEndSessionMessage(message.isEndSession())
|
.asEndSessionMessage(message.isEndSession())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (Util.equals(SignalStore.account().getAci(), address.getAci())) {
|
if (Util.equals(SignalStore.account().getAci(), address.getServiceId())) {
|
||||||
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
|
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
|
||||||
|
|
||||||
SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId);
|
SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId);
|
||||||
|
|
|
@ -17,8 +17,9 @@ import org.whispersystems.libsignal.state.SignalProtocolStore;
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.PNI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||||
|
|
||||||
|
@ -81,19 +82,17 @@ public class RefreshPreKeysJob extends BaseJob {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ACI aci = SignalStore.account().getAci();
|
|
||||||
SignalProtocolStore aciProtocolStore = ApplicationDependencies.getProtocolStore().aci();
|
SignalProtocolStore aciProtocolStore = ApplicationDependencies.getProtocolStore().aci();
|
||||||
PreKeyMetadataStore aciPreKeyStore = SignalStore.account().aciPreKeys();
|
PreKeyMetadataStore aciPreKeyStore = SignalStore.account().aciPreKeys();
|
||||||
|
|
||||||
PNI pni = SignalStore.account().getPni();
|
|
||||||
SignalProtocolStore pniProtocolStore = ApplicationDependencies.getProtocolStore().pni();
|
SignalProtocolStore pniProtocolStore = ApplicationDependencies.getProtocolStore().pni();
|
||||||
PreKeyMetadataStore pniPreKeyStore = SignalStore.account().pniPreKeys();
|
PreKeyMetadataStore pniPreKeyStore = SignalStore.account().pniPreKeys();
|
||||||
|
|
||||||
if (refreshKeys(aci, aciProtocolStore, aciPreKeyStore)) {
|
if (refreshKeys(ServiceIdType.ACI, aciProtocolStore, aciPreKeyStore)) {
|
||||||
PreKeyUtil.cleanSignedPreKeys(aciProtocolStore, aciPreKeyStore);
|
PreKeyUtil.cleanSignedPreKeys(aciProtocolStore, aciPreKeyStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refreshKeys(pni, pniProtocolStore, pniPreKeyStore)) {
|
if (refreshKeys(ServiceIdType.PNI, pniProtocolStore, pniPreKeyStore)) {
|
||||||
PreKeyUtil.cleanSignedPreKeys(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.
|
* @return True if we need to clean prekeys, otherwise false.
|
||||||
*/
|
*/
|
||||||
private boolean refreshKeys(@Nullable AccountIdentifier accountId, @NonNull SignalProtocolStore protocolStore, @NonNull PreKeyMetadataStore metadataStore) throws IOException {
|
private boolean refreshKeys(@NonNull ServiceIdType serviceIdType, @NonNull SignalProtocolStore protocolStore, @NonNull PreKeyMetadataStore metadataStore) throws IOException {
|
||||||
if (accountId == null) {
|
String logPrefix = "[" + serviceIdType + "] ";
|
||||||
throw new IOException("Unset identifier!");
|
|
||||||
}
|
|
||||||
|
|
||||||
String logPrefix = "[" + (accountId.isAci() ? "ACI" : "PNI") + "] ";
|
|
||||||
|
|
||||||
SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
||||||
|
|
||||||
int availableKeys = accountManager.getPreKeysCount(accountId);
|
int availableKeys = accountManager.getPreKeysCount(serviceIdType);
|
||||||
log(TAG, logPrefix + "Available keys: " + availableKeys);
|
log(TAG, logPrefix + "Available keys: " + availableKeys);
|
||||||
|
|
||||||
if (availableKeys >= PREKEY_MINIMUM && metadataStore.isSignedPreKeyRegistered()) {
|
if (availableKeys >= PREKEY_MINIMUM && metadataStore.isSignedPreKeyRegistered()) {
|
||||||
|
@ -127,7 +122,7 @@ public class RefreshPreKeysJob extends BaseJob {
|
||||||
|
|
||||||
log(TAG, logPrefix + "Registering new prekeys...");
|
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.setActiveSignedPreKeyId(signedPreKeyRecord.getId());
|
||||||
metadataStore.setSignedPreKeyRegistered(true);
|
metadataStore.setSignedPreKeyRegistered(true);
|
||||||
|
|
|
@ -158,7 +158,7 @@ public class ResendMessageJob extends BaseJob {
|
||||||
List<SignalProtocolAddress> addresses = result.getSuccess()
|
List<SignalProtocolAddress> addresses = result.getSuccess()
|
||||||
.getDevices()
|
.getDevices()
|
||||||
.stream()
|
.stream()
|
||||||
.map(device -> new SignalProtocolAddress(recipient.requireServiceId(), device))
|
.map(device -> recipient.requireServiceId().toProtocolAddress(device))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
ApplicationDependencies.getProtocolStore().aci().markSenderKeySharedWith(distributionId, addresses);
|
ApplicationDependencies.getProtocolStore().aci().markSenderKeySharedWith(distributionId, addresses);
|
||||||
|
|
|
@ -47,7 +47,7 @@ import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
|
||||||
import org.whispersystems.signalservice.api.crypto.ProfileCipher;
|
import org.whispersystems.signalservice.api.crypto.ProfileCipher;
|
||||||
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
||||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
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.api.services.ProfileService;
|
||||||
import org.whispersystems.signalservice.internal.ServiceResponse;
|
import org.whispersystems.signalservice.internal.ServiceResponse;
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ public class RetrieveProfileJob extends BaseJob {
|
||||||
ApplicationDependencies.getSignalWebSocket());
|
ApplicationDependencies.getSignalWebSocket());
|
||||||
|
|
||||||
List<Observable<Pair<Recipient, ServiceResponse<ProfileAndCredential>>>> requests = Stream.of(recipients)
|
List<Observable<Pair<Recipient, ServiceResponse<ProfileAndCredential>>>> requests = Stream.of(recipients)
|
||||||
.filter(Recipient::hasServiceIdentifier)
|
.filter(Recipient::hasServiceId)
|
||||||
.map(r -> ProfileUtil.retrieveProfile(context, r, getRequestType(r), profileService).toObservable())
|
.map(r -> ProfileUtil.retrieveProfile(context, r, getRequestType(r), profileService).toObservable())
|
||||||
.toList();
|
.toList();
|
||||||
stopwatch.split("requests");
|
stopwatch.split("requests");
|
||||||
|
@ -288,11 +288,11 @@ public class RetrieveProfileJob extends BaseJob {
|
||||||
|
|
||||||
Set<RecipientId> success = SetUtil.difference(recipientIds, operationState.retries);
|
Set<RecipientId> success = SetUtil.difference(recipientIds, operationState.retries);
|
||||||
|
|
||||||
Map<RecipientId, ACI> newlyRegistered = Stream.of(operationState.profiles)
|
Map<RecipientId, ServiceId> newlyRegistered = Stream.of(operationState.profiles)
|
||||||
.map(Pair::first)
|
.map(Pair::first)
|
||||||
.filterNot(Recipient::isRegistered)
|
.filterNot(Recipient::isRegistered)
|
||||||
.collect(Collectors.toMap(Recipient::getId,
|
.collect(Collectors.toMap(Recipient::getId,
|
||||||
r -> r.getAci().orNull()));
|
r -> r.getServiceId().orNull()));
|
||||||
|
|
||||||
|
|
||||||
//noinspection SimplifyStreamApiCallChains
|
//noinspection SimplifyStreamApiCallChains
|
||||||
|
@ -401,7 +401,7 @@ public class RetrieveProfileJob extends BaseJob {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityUtil.saveIdentity(recipient.requireServiceId(), identityKey);
|
IdentityUtil.saveIdentity(recipient.requireServiceId().toString(), identityKey);
|
||||||
} catch (InvalidKeyException | IOException e) {
|
} catch (InvalidKeyException | IOException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,13 @@ import org.thoughtcrime.securesms.jobmanager.Data;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
|
||||||
import org.whispersystems.libsignal.state.SignalProtocolStore;
|
import org.whispersystems.libsignal.state.SignalProtocolStore;
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.PNI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -73,17 +73,17 @@ public class RotateSignedPreKeyJob extends BaseJob {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rotate(aci, ApplicationDependencies.getProtocolStore().aci(), SignalStore.account().aciPreKeys());
|
rotate(ServiceIdType.ACI, ApplicationDependencies.getProtocolStore().aci(), SignalStore.account().aciPreKeys());
|
||||||
rotate(pni, ApplicationDependencies.getProtocolStore().pni(), SignalStore.account().pniPreKeys());
|
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
|
throws IOException
|
||||||
{
|
{
|
||||||
SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
||||||
SignedPreKeyRecord signedPreKeyRecord = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore, false);
|
SignedPreKeyRecord signedPreKeyRecord = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore, false);
|
||||||
|
|
||||||
accountManager.setSignedPreKey(accountId, signedPreKeyRecord);
|
accountManager.setSignedPreKey(serviceIdType, signedPreKeyRecord);
|
||||||
|
|
||||||
metadataStore.setActiveSignedPreKeyId(signedPreKeyRecord.getId());
|
metadataStore.setActiveSignedPreKeyId(signedPreKeyRecord.getId());
|
||||||
metadataStore.setSignedPreKeyRegistered(true);
|
metadataStore.setSignedPreKeyRegistered(true);
|
||||||
|
|
|
@ -107,7 +107,7 @@ public final class SenderKeyDistributionSendJob extends BaseJob {
|
||||||
List<SignalProtocolAddress> addresses = result.getSuccess()
|
List<SignalProtocolAddress> addresses = result.getSuccess()
|
||||||
.getDevices()
|
.getDevices()
|
||||||
.stream()
|
.stream()
|
||||||
.map(device -> new SignalProtocolAddress(recipient.requireServiceId(), device))
|
.map(device -> recipient.requireServiceId().toProtocolAddress(device))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
ApplicationDependencies.getProtocolStore().aci().markSenderKeySharedWith(distributionId, addresses);
|
ApplicationDependencies.getProtocolStore().aci().markSenderKeySharedWith(distributionId, addresses);
|
||||||
|
|
|
@ -176,7 +176,7 @@ public class StorageSyncJob extends BaseJob {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Recipient.self().hasE164() || !Recipient.self().hasAci()) {
|
if (!Recipient.self().hasE164() || !Recipient.self().hasServiceId()) {
|
||||||
Log.w(TAG, "Missing E164 or ACI!");
|
Log.w(TAG, "Missing E164 or ACI!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,11 @@ internal class AccountValues internal constructor(store: KeyValueStore) : Signal
|
||||||
val aci: ACI?
|
val aci: ACI?
|
||||||
get() = ACI.parseOrNull(getString(KEY_ACI, null))
|
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) {
|
fun setAci(aci: ACI) {
|
||||||
putString(KEY_ACI, aci.toString())
|
putString(KEY_ACI, aci.toString())
|
||||||
}
|
}
|
||||||
|
@ -96,6 +101,11 @@ internal class AccountValues internal constructor(store: KeyValueStore) : Signal
|
||||||
val pni: PNI?
|
val pni: PNI?
|
||||||
get() = PNI.parseOrNull(getString(KEY_PNI, null))
|
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) {
|
fun setPni(pni: PNI) {
|
||||||
putString(KEY_PNI, pni.toString())
|
putString(KEY_PNI, pni.toString())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.DistributionId;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
|
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.exceptions.InvalidUnidentifiedAccessHeaderException;
|
||||||
import org.whispersystems.signalservice.internal.push.http.CancelationSignal;
|
import org.whispersystems.signalservice.internal.push.http.CancelationSignal;
|
||||||
import org.whispersystems.signalservice.internal.push.http.PartialSendCompleteListener;
|
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());
|
boolean validMembership = groupRecord.isPresent() && groupRecord.get().getMembers().contains(recipient.getId());
|
||||||
|
|
||||||
if (recipient.getSenderKeyCapability() == Recipient.Capability.SUPPORTED &&
|
if (recipient.getSenderKeyCapability() == Recipient.Capability.SUPPORTED &&
|
||||||
recipient.hasAci() &&
|
recipient.hasServiceId() &&
|
||||||
access.isPresent() &&
|
access.isPresent() &&
|
||||||
access.get().getTargetUnidentifiedAccess().isPresent() &&
|
access.get().getTargetUnidentifiedAccess().isPresent() &&
|
||||||
validMembership)
|
validMembership)
|
||||||
|
@ -311,8 +310,8 @@ public final class GroupSendUtil {
|
||||||
Log.w(TAG, "There are " + unregisteredTargets.size() + " unregistered targets. Including failure results.");
|
Log.w(TAG, "There are " + unregisteredTargets.size() + " unregistered targets. Including failure results.");
|
||||||
|
|
||||||
List<SendMessageResult> unregisteredResults = unregisteredTargets.stream()
|
List<SendMessageResult> unregisteredResults = unregisteredTargets.stream()
|
||||||
.filter(Recipient::hasAci)
|
.filter(Recipient::hasServiceId)
|
||||||
.map(t -> SendMessageResult.unregisteredFailure(new SignalServiceAddress(t.requireAci(), t.getE164().orNull())))
|
.map(t -> SendMessageResult.unregisteredFailure(new SignalServiceAddress(t.requireServiceId(), t.getE164().orNull())))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
if (unregisteredResults.size() < unregisteredTargets.size()) {
|
if (unregisteredResults.size() < unregisteredTargets.size()) {
|
||||||
|
|
|
@ -652,7 +652,7 @@ public final class MessageContentProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationDependencies.getSignalCallManager()
|
ApplicationDependencies.getSignalCallManager()
|
||||||
.receivedOpaqueMessage(new WebRtcData.OpaqueMessageMetadata(senderRecipient.requireAci().uuid(),
|
.receivedOpaqueMessage(new WebRtcData.OpaqueMessageMetadata(senderRecipient.requireServiceId().uuid(),
|
||||||
message.getOpaque(),
|
message.getOpaque(),
|
||||||
content.getSenderDevice(),
|
content.getSenderDevice(),
|
||||||
messageAgeSeconds));
|
messageAgeSeconds));
|
||||||
|
@ -734,7 +734,7 @@ public final class MessageContentProcessor {
|
||||||
long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(recipient);
|
long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(recipient);
|
||||||
|
|
||||||
if (!recipient.isGroup()) {
|
if (!recipient.isGroup()) {
|
||||||
ApplicationDependencies.getProtocolStore().aci().deleteAllSessions(recipient.requireServiceId());
|
ApplicationDependencies.getProtocolStore().aci().deleteAllSessions(recipient.requireServiceId().toString());
|
||||||
|
|
||||||
SecurityEvent.broadcastSecurityUpdateEvent(context);
|
SecurityEvent.broadcastSecurityUpdateEvent(context);
|
||||||
|
|
||||||
|
@ -867,7 +867,7 @@ public final class MessageContentProcessor {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Recipient targetAuthor = Recipient.externalPush(context, reaction.getTargetAuthor());
|
Recipient targetAuthor = Recipient.externalPush(reaction.getTargetAuthor());
|
||||||
MessageRecord targetMessage = SignalDatabase.mmsSms().getMessageFor(reaction.getTargetSentTimestamp(), targetAuthor.getId());
|
MessageRecord targetMessage = SignalDatabase.mmsSms().getMessageFor(reaction.getTargetSentTimestamp(), targetAuthor.getId());
|
||||||
|
|
||||||
if (targetMessage == null) {
|
if (targetMessage == null) {
|
||||||
|
@ -1019,7 +1019,7 @@ public final class MessageContentProcessor {
|
||||||
Recipient recipient;
|
Recipient recipient;
|
||||||
|
|
||||||
if (response.getPerson().isPresent()) {
|
if (response.getPerson().isPresent()) {
|
||||||
recipient = Recipient.externalPush(context, response.getPerson().get());
|
recipient = Recipient.externalPush(response.getPerson().get());
|
||||||
} else if (response.getGroupId().isPresent()) {
|
} else if (response.getGroupId().isPresent()) {
|
||||||
GroupId groupId = GroupId.v1(response.getGroupId().get());
|
GroupId groupId = GroupId.v1(response.getGroupId().get());
|
||||||
recipient = Recipient.externalPossiblyMigratedGroup(context, groupId);
|
recipient = Recipient.externalPossiblyMigratedGroup(context, groupId);
|
||||||
|
@ -1271,7 +1271,7 @@ public final class MessageContentProcessor {
|
||||||
|
|
||||||
List<Long> toMarkViewed = Stream.of(viewedMessages)
|
List<Long> toMarkViewed = Stream.of(viewedMessages)
|
||||||
.map(message -> {
|
.map(message -> {
|
||||||
RecipientId author = Recipient.externalPush(context, message.getSender()).getId();
|
RecipientId author = Recipient.externalPush(message.getSender()).getId();
|
||||||
return SignalDatabase.mmsSms().getMessageFor(message.getTimestamp(), author);
|
return SignalDatabase.mmsSms().getMessageFor(message.getTimestamp(), author);
|
||||||
})
|
})
|
||||||
.filter(message -> message != null && message.isMms())
|
.filter(message -> message != null && message.isMms())
|
||||||
|
@ -1289,7 +1289,7 @@ public final class MessageContentProcessor {
|
||||||
private void handleSynchronizeViewOnceOpenMessage(@NonNull ViewOnceOpenMessage openMessage, long envelopeTimestamp) {
|
private void handleSynchronizeViewOnceOpenMessage(@NonNull ViewOnceOpenMessage openMessage, long envelopeTimestamp) {
|
||||||
log(envelopeTimestamp, "Handling a view-once open for message: " + openMessage.getTimestamp());
|
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();
|
long timestamp = openMessage.getTimestamp();
|
||||||
MessageRecord record = SignalDatabase.mmsSms().getMessageFor(timestamp, author);
|
MessageRecord record = SignalDatabase.mmsSms().getMessageFor(timestamp, author);
|
||||||
|
|
||||||
|
@ -1547,7 +1547,7 @@ public final class MessageContentProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<org.whispersystems.libsignal.util.Pair<RecipientId, Boolean>> unidentifiedStatus = Stream.of(members)
|
List<org.whispersystems.libsignal.util.Pair<RecipientId, Boolean>> 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();
|
.toList();
|
||||||
receiptDatabase.setUnidentified(unidentifiedStatus, messageId);
|
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 + ".");
|
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);
|
warn(content.getTimestamp(), "[RetryReceipt] Requester " + senderRecipient.getId() + " somehow has no UUID! timestamp: " + sentTimestamp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1953,7 +1953,7 @@ public final class MessageContentProcessor {
|
||||||
|
|
||||||
GroupId.V2 groupId = threadRecipient.requireGroupId().requireV2();
|
GroupId.V2 groupId = threadRecipient.requireGroupId().requireV2();
|
||||||
DistributionId distributionId = SignalDatabase.groups().getOrCreateDistributionId(groupId);
|
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));
|
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) {
|
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);
|
SessionRecord session = ApplicationDependencies.getProtocolStore().aci().loadSession(address);
|
||||||
|
|
||||||
return session.currentRatchetKeyMatches(ratchetKey);
|
return session.currentRatchetKeyMatches(ratchetKey);
|
||||||
|
@ -2064,7 +2064,7 @@ public final class MessageContentProcessor {
|
||||||
return Optional.absent();
|
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);
|
MessageRecord message = SignalDatabase.mmsSms().getMessageFor(quote.get().getId(), author);
|
||||||
|
|
||||||
if (message != null && !message.isRemoteDelete()) {
|
if (message != null && !message.isRemoteDelete()) {
|
||||||
|
@ -2200,7 +2200,7 @@ public final class MessageContentProcessor {
|
||||||
List<Mention> mentions = new ArrayList<>(signalServiceMentions.size());
|
List<Mention> mentions = new ArrayList<>(signalServiceMentions.size());
|
||||||
|
|
||||||
for (SignalServiceDataMessage.Mention mention : signalServiceMentions) {
|
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;
|
return mentions;
|
||||||
|
@ -2223,7 +2223,7 @@ public final class MessageContentProcessor {
|
||||||
private Recipient getSyncMessageDestination(@NonNull SentTranscriptMessage message)
|
private Recipient getSyncMessageDestination(@NonNull SentTranscriptMessage message)
|
||||||
throws BadGroupIdException
|
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 {
|
private Recipient getMessageDestination(@NonNull SignalServiceContent content) throws BadGroupIdException {
|
||||||
|
@ -2339,8 +2339,8 @@ public final class MessageContentProcessor {
|
||||||
if (recipient.hasE164()) {
|
if (recipient.hasE164()) {
|
||||||
unidentified |= message.isUnidentified(recipient.requireE164());
|
unidentified |= message.isUnidentified(recipient.requireE164());
|
||||||
}
|
}
|
||||||
if (recipient.hasAci()) {
|
if (recipient.hasServiceId()) {
|
||||||
unidentified |= message.isUnidentified(recipient.requireAci());
|
unidentified |= message.isUnidentified(recipient.requireServiceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
return unidentified;
|
return unidentified;
|
||||||
|
|
|
@ -44,7 +44,6 @@ import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||||
import org.whispersystems.libsignal.protocol.CiphertextMessage;
|
import org.whispersystems.libsignal.protocol.CiphertextMessage;
|
||||||
import org.whispersystems.libsignal.protocol.DecryptionErrorMessage;
|
import org.whispersystems.libsignal.protocol.DecryptionErrorMessage;
|
||||||
import org.whispersystems.libsignal.state.SignalProtocolStore;
|
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.InvalidMessageStructureException;
|
import org.whispersystems.signalservice.api.InvalidMessageStructureException;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountDataStore;
|
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) {
|
public static @NonNull DecryptionResult decrypt(@NonNull Context context, @NonNull SignalServiceEnvelope envelope) {
|
||||||
SignalServiceAccountDataStore protocolStore = ApplicationDependencies.getProtocolStore().aci();
|
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());
|
SignalServiceCipher cipher = new SignalServiceCipher(localAddress, SignalStore.account().getDeviceId(), protocolStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator());
|
||||||
List<Job> jobs = new LinkedList<>();
|
List<Job> jobs = new LinkedList<>();
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.whispersystems.libsignal.state.SignalProtocolStore;
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
import org.whispersystems.signalservice.api.push.PNI;
|
import org.whispersystems.signalservice.api.push.PNI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -71,7 +72,7 @@ public class PniAccountInitializationMigrationJob extends MigrationJob {
|
||||||
SignedPreKeyRecord signedPreKey = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore, true);
|
SignedPreKeyRecord signedPreKey = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore, true);
|
||||||
List<PreKeyRecord> oneTimePreKeys = PreKeyUtil.generateAndStoreOneTimePreKeys(protocolStore, metadataStore);
|
List<PreKeyRecord> 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);
|
metadataStore.setSignedPreKeyRegistered(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.util.Base64;
|
import org.thoughtcrime.securesms.util.Base64;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.api.util.UuidUtil;
|
||||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
||||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContextV2;
|
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContextV2;
|
||||||
|
@ -191,7 +192,7 @@ public final class MessageGroupContext {
|
||||||
List<RecipientId> members = new ArrayList<>(decryptedGroupV2Context.getGroupState().getMembersCount());
|
List<RecipientId> members = new ArrayList<>(decryptedGroupV2Context.getGroupState().getMembersCount());
|
||||||
|
|
||||||
for (DecryptedMember member : decryptedGroupV2Context.getGroupState().getMembersList()) {
|
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)) {
|
if (!Recipient.self().getId().equals(recipient)) {
|
||||||
members.add(recipient);
|
members.add(recipient);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,6 @@ import android.database.Cursor;
|
||||||
import androidx.annotation.AnyThread;
|
import androidx.annotation.AnyThread;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import net.zetetic.database.sqlcipher.SQLiteDatabase;
|
|
||||||
|
|
||||||
import org.signal.core.util.ThreadUtil;
|
import org.signal.core.util.ThreadUtil;
|
||||||
import org.signal.core.util.concurrent.SignalExecutors;
|
import org.signal.core.util.concurrent.SignalExecutors;
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
|
@ -153,7 +151,7 @@ public final class LiveRecipientCache {
|
||||||
String localE164 = SignalStore.account().getE164();
|
String localE164 = SignalStore.account().getE164();
|
||||||
|
|
||||||
if (localAci != null) {
|
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) {
|
} else if (localE164 != null) {
|
||||||
selfId = recipientDatabase.getByE164(localE164).orNull();
|
selfId = recipientDatabase.getByE164(localE164).orNull();
|
||||||
} else {
|
} else {
|
||||||
|
@ -235,6 +233,6 @@ public final class LiveRecipientCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidForCache(@NonNull Recipient recipient) {
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.libsignal.util.guava.Preconditions;
|
import org.whispersystems.libsignal.util.guava.Preconditions;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.PNI;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||||
|
@ -78,7 +79,7 @@ public class Recipient {
|
||||||
|
|
||||||
private final RecipientId id;
|
private final RecipientId id;
|
||||||
private final boolean resolving;
|
private final boolean resolving;
|
||||||
private final ACI aci;
|
private final ServiceId serviceId;
|
||||||
private final PNI pni;
|
private final PNI pni;
|
||||||
private final String username;
|
private final String username;
|
||||||
private final String e164;
|
private final String e164;
|
||||||
|
@ -166,8 +167,8 @@ public class Recipient {
|
||||||
* Returns a fully-populated {@link Recipient} and associates it with the provided username.
|
* Returns a fully-populated {@link Recipient} and associates it with the provided username.
|
||||||
*/
|
*/
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public static @NonNull Recipient externalUsername(@NonNull Context context, @NonNull ACI aci, @NonNull String username) {
|
public static @NonNull Recipient externalUsername(@NonNull ServiceId serviceId, @NonNull String username) {
|
||||||
Recipient recipient = externalPush(context, aci, null, false);
|
Recipient recipient = externalPush(serviceId, null, false);
|
||||||
SignalDatabase.recipients().setUsername(recipient.getId(), username);
|
SignalDatabase.recipients().setUsername(recipient.getId(), username);
|
||||||
return recipient;
|
return recipient;
|
||||||
}
|
}
|
||||||
|
@ -175,11 +176,11 @@ public class Recipient {
|
||||||
/**
|
/**
|
||||||
* Returns a fully-populated {@link Recipient} based off of a {@link SignalServiceAddress},
|
* Returns a fully-populated {@link Recipient} based off of a {@link SignalServiceAddress},
|
||||||
* creating one in the database if necessary. Convenience overload of
|
* creating one in the database if necessary. Convenience overload of
|
||||||
* {@link #externalPush(Context, ACI, String, boolean)}
|
* {@link #externalPush(ServiceId, String, boolean)}
|
||||||
*/
|
*/
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public static @NonNull Recipient externalPush(@NonNull Context context, @NonNull SignalServiceAddress signalServiceAddress) {
|
public static @NonNull Recipient externalPush(@NonNull SignalServiceAddress signalServiceAddress) {
|
||||||
return externalPush(context, signalServiceAddress.getAci(), signalServiceAddress.getNumber().orNull(), false);
|
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.
|
* prioritize E164 addresses and not use the UUIDs if possible.
|
||||||
*/
|
*/
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public static @NonNull Recipient externalGV1Member(@NonNull Context context, @NonNull SignalServiceAddress address) {
|
public static @NonNull Recipient externalGV1Member(@NonNull SignalServiceAddress address) {
|
||||||
if (address.getNumber().isPresent()) {
|
if (address.getNumber().isPresent()) {
|
||||||
return externalPush(context, null, address.getNumber().get(), false);
|
return externalPush(null, address.getNumber().get(), false);
|
||||||
} else {
|
} else {
|
||||||
return externalPush(context, address.getAci(), null, false);
|
return externalPush(address.getServiceId(), null, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +208,7 @@ public class Recipient {
|
||||||
*/
|
*/
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public static @NonNull Recipient externalHighTrustPush(@NonNull Context context, @NonNull SignalServiceAddress signalServiceAddress) {
|
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).
|
* that can be trusted as accurate (like an envelope).
|
||||||
*/
|
*/
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public static @NonNull Recipient externalPush(@NonNull Context context, @Nullable ACI aci, @Nullable String e164, boolean highTrust) {
|
public static @NonNull Recipient externalPush(@Nullable ServiceId serviceId, @Nullable String e164, boolean highTrust) {
|
||||||
if (ACI.UNKNOWN.equals(aci)) {
|
if (ServiceId.UNKNOWN.equals(serviceId)) {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
RecipientDatabase db = SignalDatabase.recipients();
|
RecipientDatabase db = SignalDatabase.recipients();
|
||||||
RecipientId recipientId = db.getAndPossiblyMerge(aci, e164, highTrust);
|
RecipientId recipientId = db.getAndPossiblyMerge(serviceId, e164, highTrust);
|
||||||
|
|
||||||
Recipient resolved = resolved(recipientId);
|
Recipient resolved = resolved(recipientId);
|
||||||
|
|
||||||
|
@ -237,9 +238,9 @@ public class Recipient {
|
||||||
Log.w(TAG, "Resolved " + recipientId + ", but got back a recipient with " + resolved.getId());
|
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.");
|
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()) {
|
} 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());
|
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.
|
* or serialized groupId.
|
||||||
*
|
*
|
||||||
* If the identifier is a UUID of a Signal user, prefer using
|
* 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.
|
* the phone number with the recipient.
|
||||||
*/
|
*/
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
|
@ -317,7 +318,7 @@ public class Recipient {
|
||||||
|
|
||||||
if (UuidUtil.isUuid(identifier)) {
|
if (UuidUtil.isUuid(identifier)) {
|
||||||
ACI uuid = ACI.parseOrThrow(identifier);
|
ACI uuid = ACI.parseOrThrow(identifier);
|
||||||
id = db.getOrInsertFromAci(uuid);
|
id = db.getOrInsertFromServiceId(uuid);
|
||||||
} else if (GroupId.isEncodedGroup(identifier)) {
|
} else if (GroupId.isEncodedGroup(identifier)) {
|
||||||
id = db.getOrInsertFromGroupId(GroupId.parseOrThrow(identifier));
|
id = db.getOrInsertFromGroupId(GroupId.parseOrThrow(identifier));
|
||||||
} else if (NumberUtil.isValidEmail(identifier)) {
|
} else if (NumberUtil.isValidEmail(identifier)) {
|
||||||
|
@ -337,7 +338,7 @@ public class Recipient {
|
||||||
Recipient(@NonNull RecipientId id) {
|
Recipient(@NonNull RecipientId id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.resolving = true;
|
this.resolving = true;
|
||||||
this.aci = null;
|
this.serviceId = null;
|
||||||
this.pni = null;
|
this.pni = null;
|
||||||
this.username = null;
|
this.username = null;
|
||||||
this.e164 = null;
|
this.e164 = null;
|
||||||
|
@ -392,9 +393,9 @@ public class Recipient {
|
||||||
|
|
||||||
public Recipient(@NonNull RecipientId id, @NonNull RecipientDetails details, boolean resolved) {
|
public Recipient(@NonNull RecipientId id, @NonNull RecipientDetails details, boolean resolved) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.resolving = !resolved;
|
this.resolving = !resolved;
|
||||||
this.aci = details.aci;
|
this.serviceId = details.serviceId;
|
||||||
this.pni = details.pni;
|
this.pni = details.pni;
|
||||||
this.username = details.username;
|
this.username = details.username;
|
||||||
this.e164 = details.e164;
|
this.e164 = details.e164;
|
||||||
this.email = details.email;
|
this.email = details.email;
|
||||||
|
@ -614,8 +615,8 @@ public class Recipient {
|
||||||
return StringUtil.isolateBidi(name);
|
return StringUtil.isolateBidi(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull Optional<ACI> getAci() {
|
public @NonNull Optional<ServiceId> getServiceId() {
|
||||||
return Optional.fromNullable(aci);
|
return Optional.fromNullable(serviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull Optional<PNI> getPni() {
|
public @NonNull Optional<PNI> getPni() {
|
||||||
|
@ -646,16 +647,6 @@ public class Recipient {
|
||||||
return Optional.fromNullable(e164).or(Optional.fromNullable(email));
|
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() {
|
public @NonNull PNI requirePni() {
|
||||||
PNI resolved = resolving ? resolve().pni : pni;
|
PNI resolved = resolving ? resolve().pni : pni;
|
||||||
|
|
||||||
|
@ -706,16 +697,12 @@ public class Recipient {
|
||||||
return getE164().isPresent();
|
return getE164().isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasAci() {
|
public boolean hasServiceId() {
|
||||||
return getAci().isPresent();
|
return getServiceId().isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPni() {
|
public boolean isServiceIdOnly() {
|
||||||
return getPni().isPresent();
|
return hasServiceId() && !hasSmsAddress();
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAciOnly() {
|
|
||||||
return hasAci() && !hasSmsAddress();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull GroupId requireGroupId() {
|
public @NonNull GroupId requireGroupId() {
|
||||||
|
@ -728,36 +715,31 @@ public class Recipient {
|
||||||
return resolved;
|
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
|
* The {@link ServiceId} of the user if available, otherwise throw.
|
||||||
* available, will return an E164 number.
|
|
||||||
*/
|
*/
|
||||||
public @NonNull String requireServiceId() {
|
public @NonNull ServiceId requireServiceId() {
|
||||||
Recipient resolved = resolving ? resolve() : this;
|
ServiceId resolved = resolving ? resolve().serviceId : serviceId;
|
||||||
|
|
||||||
if (resolved.getAci().isPresent()) {
|
if (resolved == null) {
|
||||||
return resolved.requireAci().toString();
|
throw new MissingAddressError(id);
|
||||||
} else {
|
|
||||||
return getE164().get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A single string to represent the recipient, in order of precedence:
|
* @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() {
|
public @NonNull String requireStringId() {
|
||||||
Recipient resolved = resolving ? resolve() : this;
|
Recipient resolved = resolving ? resolve() : this;
|
||||||
|
|
||||||
if (resolved.isGroup()) {
|
if (resolved.isGroup()) {
|
||||||
return resolved.requireGroupId().toString();
|
return resolved.requireGroupId().toString();
|
||||||
} else if (resolved.getAci().isPresent()) {
|
} else if (resolved.getServiceId().isPresent()) {
|
||||||
return resolved.requireAci().toString();
|
return resolved.requireServiceId().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return requireSmsAddress();
|
return requireSmsAddress();
|
||||||
|
@ -1214,7 +1196,7 @@ public class Recipient {
|
||||||
profileSharing == other.profileSharing &&
|
profileSharing == other.profileSharing &&
|
||||||
lastProfileFetch == other.lastProfileFetch &&
|
lastProfileFetch == other.lastProfileFetch &&
|
||||||
forceSmsSelection == other.forceSmsSelection &&
|
forceSmsSelection == other.forceSmsSelection &&
|
||||||
Objects.equals(aci, other.aci) &&
|
Objects.equals(serviceId, other.serviceId) &&
|
||||||
Objects.equals(username, other.username) &&
|
Objects.equals(username, other.username) &&
|
||||||
Objects.equals(e164, other.e164) &&
|
Objects.equals(e164, other.e164) &&
|
||||||
Objects.equals(email, other.email) &&
|
Objects.equals(email, other.email) &&
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ACI;
|
||||||
import org.whispersystems.signalservice.api.push.PNI;
|
import org.whispersystems.signalservice.api.push.PNI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -32,7 +33,7 @@ import java.util.List;
|
||||||
|
|
||||||
public class RecipientDetails {
|
public class RecipientDetails {
|
||||||
|
|
||||||
final ACI aci;
|
final ServiceId serviceId;
|
||||||
final PNI pni;
|
final PNI pni;
|
||||||
final String username;
|
final String username;
|
||||||
final String e164;
|
final String e164;
|
||||||
|
@ -99,7 +100,7 @@ public class RecipientDetails {
|
||||||
this.systemContactPhoto = Util.uri(record.getSystemContactPhotoUri());
|
this.systemContactPhoto = Util.uri(record.getSystemContactPhotoUri());
|
||||||
this.customLabel = record.getSystemPhoneLabel();
|
this.customLabel = record.getSystemPhoneLabel();
|
||||||
this.contactUri = Util.uri(record.getSystemContactUri());
|
this.contactUri = Util.uri(record.getSystemContactUri());
|
||||||
this.aci = record.getAci();
|
this.serviceId = record.getServiceId();
|
||||||
this.pni = record.getPni();
|
this.pni = record.getPni();
|
||||||
this.username = record.getUsername();
|
this.username = record.getUsername();
|
||||||
this.e164 = record.getE164();
|
this.e164 = record.getE164();
|
||||||
|
@ -156,9 +157,9 @@ public class RecipientDetails {
|
||||||
this.groupAvatarId = null;
|
this.groupAvatarId = null;
|
||||||
this.systemContactPhoto = null;
|
this.systemContactPhoto = null;
|
||||||
this.customLabel = null;
|
this.customLabel = null;
|
||||||
this.contactUri = null;
|
this.contactUri = null;
|
||||||
this.aci = null;
|
this.serviceId = null;
|
||||||
this.pni = null;
|
this.pni = null;
|
||||||
this.username = null;
|
this.username = null;
|
||||||
this.e164 = null;
|
this.e164 = null;
|
||||||
this.email = null;
|
this.email = null;
|
||||||
|
@ -210,7 +211,7 @@ public class RecipientDetails {
|
||||||
public static @NonNull RecipientDetails forIndividual(@NonNull Context context, @NonNull RecipientRecord settings) {
|
public static @NonNull RecipientDetails forIndividual(@NonNull Context context, @NonNull RecipientRecord settings) {
|
||||||
boolean systemContact = !settings.getSystemProfileName().isEmpty();
|
boolean systemContact = !settings.getSystemProfileName().isEmpty();
|
||||||
boolean isSelf = (settings.getE164() != null && settings.getE164().equals(SignalStore.account().getE164())) ||
|
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());
|
boolean isReleaseChannel = settings.getId().equals(SignalStore.releaseChannelValues().getReleaseChannelRecipientId());
|
||||||
|
|
||||||
RegisteredState registeredState = settings.getRegistered();
|
RegisteredState registeredState = settings.getRegistered();
|
||||||
|
|
|
@ -15,13 +15,13 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.util.DelimiterUtil;
|
import org.thoughtcrime.securesms.util.DelimiterUtil;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class RecipientId implements Parcelable, Comparable<RecipientId> {
|
public class RecipientId implements Parcelable, Comparable<RecipientId> {
|
||||||
|
@ -55,7 +55,7 @@ public class RecipientId implements Parcelable, Comparable<RecipientId> {
|
||||||
|
|
||||||
@AnyThread
|
@AnyThread
|
||||||
public static @NonNull RecipientId from(@NonNull SignalServiceAddress address) {
|
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<RecipientId> {
|
||||||
*/
|
*/
|
||||||
@AnyThread
|
@AnyThread
|
||||||
public static @NonNull RecipientId fromHighTrust(@NonNull SignalServiceAddress address) {
|
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<RecipientId> {
|
||||||
*/
|
*/
|
||||||
@AnyThread
|
@AnyThread
|
||||||
@SuppressLint("WrongThread")
|
@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);
|
return from(aci, e164, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AnyThread
|
@AnyThread
|
||||||
@SuppressLint("WrongThread")
|
@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);
|
RecipientId recipientId = RecipientIdCache.INSTANCE.get(aci, e164);
|
||||||
|
|
||||||
if (recipientId == null) {
|
if (recipientId == null) {
|
||||||
Recipient recipient = Recipient.externalPush(ApplicationDependencies.getApplication(), aci, e164, highTrust);
|
Recipient recipient = Recipient.externalPush(aci, e164, highTrust);
|
||||||
RecipientIdCache.INSTANCE.put(recipient);
|
RecipientIdCache.INSTANCE.put(recipient);
|
||||||
recipientId = recipient.getId();
|
recipientId = recipient.getId();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,10 @@ import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
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.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thread safe cache that allows faster looking up of {@link RecipientId}s without hitting the database.
|
* 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) {
|
synchronized void put(@NonNull Recipient recipient) {
|
||||||
RecipientId recipientId = recipient.getId();
|
RecipientId recipientId = recipient.getId();
|
||||||
Optional<String> e164 = recipient.getE164();
|
Optional<String> e164 = recipient.getE164();
|
||||||
Optional<ACI> aci = recipient.getAci();
|
Optional<ServiceId> serviceId = recipient.getServiceId();
|
||||||
|
|
||||||
if (e164.isPresent()) {
|
if (e164.isPresent()) {
|
||||||
ids.put(e164.get(), recipientId);
|
ids.put(e164.get(), recipientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aci.isPresent()) {
|
if (serviceId.isPresent()) {
|
||||||
ids.put(aci.get(), recipientId);
|
ids.put(serviceId.get(), recipientId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized @Nullable RecipientId get(@Nullable ACI aci, @Nullable String e164) {
|
synchronized @Nullable RecipientId get(@Nullable ServiceId serviceId, @Nullable String e164) {
|
||||||
if (aci != null && e164 != null) {
|
if (serviceId != null && e164 != null) {
|
||||||
RecipientId recipientIdByAci = ids.get(aci);
|
RecipientId recipientIdByAci = ids.get(serviceId);
|
||||||
if (recipientIdByAci == null) return null;
|
if (recipientIdByAci == null) return null;
|
||||||
|
|
||||||
RecipientId recipientIdByE164 = ids.get(e164);
|
RecipientId recipientIdByE164 = ids.get(e164);
|
||||||
|
@ -58,13 +57,13 @@ final class RecipientIdCache {
|
||||||
if (recipientIdByAci.equals(recipientIdByE164)) {
|
if (recipientIdByAci.equals(recipientIdByE164)) {
|
||||||
return recipientIdByAci;
|
return recipientIdByAci;
|
||||||
} else {
|
} else {
|
||||||
ids.remove(aci);
|
ids.remove(serviceId);
|
||||||
ids.remove(e164);
|
ids.remove(e164);
|
||||||
Log.w(TAG, "Seen invalid RecipientIdCacheState");
|
Log.w(TAG, "Seen invalid RecipientIdCacheState");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} else if (aci != null) {
|
} else if (serviceId != null) {
|
||||||
return ids.get(aci);
|
return ids.get(serviceId);
|
||||||
} else if (e164 != null) {
|
} else if (e164 != null) {
|
||||||
return ids.get(e164);
|
return ids.get(e164);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,11 +49,11 @@ public class RecipientUtil {
|
||||||
{
|
{
|
||||||
recipient = recipient.resolve();
|
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!");
|
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...");
|
Log.i(TAG, recipient.getId() + " is missing a UUID...");
|
||||||
RegisteredState state = DirectoryHelper.refreshDirectoryFor(context, recipient, false);
|
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);
|
Log.i(TAG, "Successfully performed a UUID fetch for " + recipient.getId() + ". Registered: " + state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recipient.hasAci()) {
|
if (recipient.hasServiceId()) {
|
||||||
return new SignalServiceAddress(recipient.requireAci(), Optional.fromNullable(recipient.resolve().getE164().orNull()));
|
return new SignalServiceAddress(recipient.requireServiceId(), Optional.fromNullable(recipient.resolve().getE164().orNull()));
|
||||||
} else {
|
} else {
|
||||||
throw new NotFoundException(recipient.getId() + " is not registered!");
|
throw new NotFoundException(recipient.getId() + " is not registered!");
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ public class RecipientUtil {
|
||||||
|
|
||||||
return Stream.of(recipients)
|
return Stream.of(recipients)
|
||||||
.map(Recipient::resolve)
|
.map(Recipient::resolve)
|
||||||
.map(r -> new SignalServiceAddress(r.requireAci(), r.getE164().orNull()))
|
.map(r -> new SignalServiceAddress(r.requireServiceId(), r.getE164().orNull()))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ public class RecipientUtil {
|
||||||
{
|
{
|
||||||
List<Recipient> recipientsWithoutUuids = Stream.of(recipients)
|
List<Recipient> recipientsWithoutUuids = Stream.of(recipients)
|
||||||
.map(Recipient::resolve)
|
.map(Recipient::resolve)
|
||||||
.filterNot(Recipient::hasAci)
|
.filterNot(Recipient::hasServiceId)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (recipientsWithoutUuids.size() > 0) {
|
if (recipientsWithoutUuids.size() > 0) {
|
||||||
|
@ -178,7 +178,7 @@ public class RecipientUtil {
|
||||||
ApplicationDependencies.getJobManager().add(new MultiDeviceBlockedUpdateJob());
|
ApplicationDependencies.getJobManager().add(new MultiDeviceBlockedUpdateJob());
|
||||||
StorageSyncHelper.scheduleSyncForDataChange();
|
StorageSyncHelper.scheduleSyncForDataChange();
|
||||||
|
|
||||||
if (recipient.hasServiceIdentifier()) {
|
if (recipient.hasServiceId()) {
|
||||||
ApplicationDependencies.getJobManager().add(MultiDeviceMessageRequestResponseJob.forAccept(recipient.getId()));
|
ApplicationDependencies.getJobManager().add(MultiDeviceMessageRequestResponseJob.forAccept(recipient.getId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,9 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.KbsPinData;
|
import org.whispersystems.signalservice.api.KbsPinData;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.PNI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.internal.ServiceResponse;
|
import org.whispersystems.signalservice.internal.ServiceResponse;
|
||||||
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
|
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
|
||||||
|
@ -142,15 +143,15 @@ public final class RegistrationRepository {
|
||||||
SignalServiceAccountDataStoreImpl aciProtocolStore = ApplicationDependencies.getProtocolStore().aci();
|
SignalServiceAccountDataStoreImpl aciProtocolStore = ApplicationDependencies.getProtocolStore().aci();
|
||||||
SignalServiceAccountDataStoreImpl pniProtocolStore = ApplicationDependencies.getProtocolStore().pni();
|
SignalServiceAccountDataStoreImpl pniProtocolStore = ApplicationDependencies.getProtocolStore().pni();
|
||||||
|
|
||||||
generateAndRegisterPreKeys(aci, accountManager, aciProtocolStore, SignalStore.account().aciPreKeys());
|
generateAndRegisterPreKeys(ServiceIdType.ACI, accountManager, aciProtocolStore, SignalStore.account().aciPreKeys());
|
||||||
generateAndRegisterPreKeys(pni, accountManager, pniProtocolStore, SignalStore.account().pniPreKeys());
|
generateAndRegisterPreKeys(ServiceIdType.PNI, accountManager, pniProtocolStore, SignalStore.account().pniPreKeys());
|
||||||
|
|
||||||
if (registrationData.isFcm()) {
|
if (registrationData.isFcm()) {
|
||||||
accountManager.setGcmId(Optional.fromNullable(registrationData.getFcmToken()));
|
accountManager.setGcmId(Optional.fromNullable(registrationData.getFcmToken()));
|
||||||
}
|
}
|
||||||
|
|
||||||
RecipientDatabase recipientDatabase = SignalDatabase.recipients();
|
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.setProfileSharing(selfId, true);
|
||||||
recipientDatabase.markRegisteredOrThrow(selfId, aci);
|
recipientDatabase.markRegisteredOrThrow(selfId, aci);
|
||||||
|
@ -175,7 +176,7 @@ public final class RegistrationRepository {
|
||||||
PinState.onRegistration(context, kbsData, pin, hasPin);
|
PinState.onRegistration(context, kbsData, pin, hasPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateAndRegisterPreKeys(@NonNull AccountIdentifier accountId,
|
private void generateAndRegisterPreKeys(@NonNull ServiceIdType serviceIdType,
|
||||||
@NonNull SignalServiceAccountManager accountManager,
|
@NonNull SignalServiceAccountManager accountManager,
|
||||||
@NonNull SignalProtocolStore protocolStore,
|
@NonNull SignalProtocolStore protocolStore,
|
||||||
@NonNull PreKeyMetadataStore metadataStore)
|
@NonNull PreKeyMetadataStore metadataStore)
|
||||||
|
@ -184,7 +185,7 @@ public final class RegistrationRepository {
|
||||||
SignedPreKeyRecord signedPreKey = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore, true);
|
SignedPreKeyRecord signedPreKey = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore, true);
|
||||||
List<PreKeyRecord> oneTimePreKeys = PreKeyUtil.generateAndStoreOneTimePreKeys(protocolStore, metadataStore);
|
List<PreKeyRecord> oneTimePreKeys = PreKeyUtil.generateAndStoreOneTimePreKeys(protocolStore, metadataStore);
|
||||||
|
|
||||||
accountManager.setPreKeys(accountId, protocolStore.getIdentityKeyPair().getPublicKey(), signedPreKey, oneTimePreKeys);
|
accountManager.setPreKeys(serviceIdType, protocolStore.getIdentityKeyPair().getPublicKey(), signedPreKey, oneTimePreKeys);
|
||||||
metadataStore.setSignedPreKeyRegistered(true);
|
metadataStore.setSignedPreKeyRegistered(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor {
|
||||||
seen.add(Recipient.self());
|
seen.add(Recipient.self());
|
||||||
|
|
||||||
for (GroupCall.RemoteDeviceState device : remoteDeviceStates) {
|
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());
|
CallParticipantId callParticipantId = new CallParticipantId(device.getDemuxId(), recipient.getId());
|
||||||
CallParticipant callParticipant = participants.get(callParticipantId);
|
CallParticipant callParticipant = participants.get(callParticipantId);
|
||||||
|
|
||||||
|
|
|
@ -123,8 +123,8 @@ public class GroupConnectedActionProcessor extends GroupActionProcessor {
|
||||||
webRtcInteractor.sendGroupCallMessage(currentState.getCallInfoState().getCallRecipient(), eraId);
|
webRtcInteractor.sendGroupCallMessage(currentState.getCallInfoState().getCallRecipient(), eraId);
|
||||||
|
|
||||||
List<UUID> members = new ArrayList<>(peekInfo.getJoinedMembers());
|
List<UUID> members = new ArrayList<>(peekInfo.getJoinedMembers());
|
||||||
if (!members.contains(Recipient.self().requireAci().uuid())) {
|
if (!members.contains(Recipient.self().requireServiceId().uuid())) {
|
||||||
members.add(Recipient.self().requireAci().uuid());
|
members.add(Recipient.self().requireServiceId().uuid());
|
||||||
}
|
}
|
||||||
webRtcInteractor.updateGroupCallUpdateMessage(currentState.getCallInfoState().getCallRecipient().getId(), eraId, members, WebRtcUtil.isCallFull(peekInfo));
|
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);
|
String eraId = WebRtcUtil.getGroupCallEraId(groupCall);
|
||||||
webRtcInteractor.sendGroupCallMessage(currentState.getCallInfoState().getCallRecipient(), eraId);
|
webRtcInteractor.sendGroupCallMessage(currentState.getCallInfoState().getCallRecipient(), eraId);
|
||||||
|
|
||||||
List<UUID> members = Stream.of(currentState.getCallInfoState().getRemoteCallParticipants()).map(p -> p.getRecipient().requireAci().uuid()).toList();
|
List<UUID> members = Stream.of(currentState.getCallInfoState().getRemoteCallParticipants()).map(p -> p.getRecipient().requireServiceId().uuid()).toList();
|
||||||
webRtcInteractor.updateGroupCallUpdateMessage(currentState.getCallInfoState().getCallRecipient().getId(), eraId, members, false);
|
webRtcInteractor.updateGroupCallUpdateMessage(currentState.getCallInfoState().getCallRecipient().getId(), eraId, members, false);
|
||||||
|
|
||||||
currentState = currentState.builder()
|
currentState = currentState.builder()
|
||||||
|
|
|
@ -114,7 +114,7 @@ public class GroupPreJoinActionProcessor extends GroupActionProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Recipient> callParticipants = Stream.of(peekInfo.getJoinedMembers())
|
List<Recipient> 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();
|
.toList();
|
||||||
|
|
||||||
WebRtcServiceStateBuilder.CallInfoStateBuilder builder = currentState.builder()
|
WebRtcServiceStateBuilder.CallInfoStateBuilder builder = currentState.builder()
|
||||||
|
|
|
@ -138,7 +138,7 @@ public final class IncomingGroupCallActionProcessor extends DeviceAwareActionPro
|
||||||
.changeCallSetupState(RemotePeer.GROUP_CALL_ID)
|
.changeCallSetupState(RemotePeer.GROUP_CALL_ID)
|
||||||
.isRemoteVideoOffer(true)
|
.isRemoteVideoOffer(true)
|
||||||
.ringId(ringId)
|
.ringId(ringId)
|
||||||
.ringerRecipient(Recipient.externalPush(context, ACI.from(uuid), null, false))
|
.ringerRecipient(Recipient.externalPush(ACI.from(uuid), null, false))
|
||||||
.commit()
|
.commit()
|
||||||
.changeCallInfoState()
|
.changeCallInfoState()
|
||||||
.activePeer(new RemotePeer(currentState.getCallInfoState().getCallRecipient().getId(), RemotePeer.GROUP_CALL_ID))
|
.activePeer(new RemotePeer(currentState.getCallInfoState().getCallRecipient().getId(), RemotePeer.GROUP_CALL_ID))
|
||||||
|
|
|
@ -154,7 +154,7 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
|
||||||
serviceExecutor.execute(() -> {
|
serviceExecutor.execute(() -> {
|
||||||
if (needsToSetSelfUuid) {
|
if (needsToSetSelfUuid) {
|
||||||
try {
|
try {
|
||||||
callManager.setSelfUuid(Recipient.self().requireAci().uuid());
|
callManager.setSelfUuid(Recipient.self().requireServiceId().uuid());
|
||||||
needsToSetSelfUuid = false;
|
needsToSetSelfUuid = false;
|
||||||
} catch (CallException e) {
|
} catch (CallException e) {
|
||||||
Log.w(TAG, "Unable to set self UUID on CallManager", e);
|
Log.w(TAG, "Unable to set self UUID on CallManager", e);
|
||||||
|
|
|
@ -13,9 +13,9 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
|
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
|
||||||
import org.whispersystems.signalservice.internal.storage.protos.ContactRecord.IdentityState;
|
import org.whispersystems.signalservice.internal.storage.protos.ContactRecord.IdentityState;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -51,10 +51,10 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||||
if (address == null) {
|
if (address == null) {
|
||||||
Log.w(TAG, "No address on the ContentRecord -- marking as invalid.");
|
Log.w(TAG, "No address on the ContentRecord -- marking as invalid.");
|
||||||
return true;
|
return true;
|
||||||
} else if (!address.hasValidAci()) {
|
} else if (!address.hasValidServiceId()) {
|
||||||
Log.w(TAG, "Found a ContactRecord without a UUID -- marking as invalid.");
|
Log.w(TAG, "Found a ContactRecord without a UUID -- marking as invalid.");
|
||||||
return true;
|
return true;
|
||||||
} else if ((self.getAci().isPresent() && address.getAci().equals(self.requireAci())) ||
|
} else if ((self.getServiceId().isPresent() && address.getServiceId().equals(self.requireServiceId())) ||
|
||||||
(self.getE164().isPresent() && address.getNumber().equals(self.getE164())))
|
(self.getE164().isPresent() && address.getNumber().equals(self.getE164())))
|
||||||
{
|
{
|
||||||
Log.w(TAG, "Found a ContactRecord for ourselves -- marking as invalid.");
|
Log.w(TAG, "Found a ContactRecord for ourselves -- marking as invalid.");
|
||||||
|
@ -67,7 +67,7 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||||
@Override
|
@Override
|
||||||
@NonNull Optional<SignalContactRecord> getMatching(@NonNull SignalContactRecord remote, @NonNull StorageKeyGenerator keyGenerator) {
|
@NonNull Optional<SignalContactRecord> getMatching(@NonNull SignalContactRecord remote, @NonNull StorageKeyGenerator keyGenerator) {
|
||||||
SignalServiceAddress address = remote.getAddress();
|
SignalServiceAddress address = remote.getAddress();
|
||||||
Optional<RecipientId> byUuid = recipientDatabase.getByAci(address.getAci());
|
Optional<RecipientId> byUuid = recipientDatabase.getByServiceId(address.getServiceId());
|
||||||
Optional<RecipientId> byE164 = address.getNumber().isPresent() ? recipientDatabase.getByE164(address.getNumber().get()) : Optional.absent();
|
Optional<RecipientId> byE164 = address.getNumber().isPresent() ? recipientDatabase.getByE164(address.getNumber().get()) : Optional.absent();
|
||||||
|
|
||||||
return byUuid.or(byE164).transform(recipientDatabase::getRecordForSync)
|
return byUuid.or(byE164).transform(recipientDatabase::getRecordForSync)
|
||||||
|
@ -98,9 +98,9 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] unknownFields = remote.serializeUnknownFields();
|
byte[] unknownFields = remote.serializeUnknownFields();
|
||||||
ACI aci = local.getAddress().getAci() == ACI.UNKNOWN ? remote.getAddress().getAci() : local.getAddress().getAci();
|
ServiceId serviceId = local.getAddress().getServiceId() == ServiceId.UNKNOWN ? remote.getAddress().getServiceId() : local.getAddress().getServiceId();
|
||||||
String e164 = remote.getAddress().getNumber().or(local.getAddress().getNumber()).orNull();
|
String e164 = remote.getAddress().getNumber().or(local.getAddress().getNumber()).orNull();
|
||||||
SignalServiceAddress address = new SignalServiceAddress(aci, e164);
|
SignalServiceAddress address = new SignalServiceAddress(serviceId, e164);
|
||||||
byte[] profileKey = remote.getProfileKey().or(local.getProfileKey()).orNull();
|
byte[] profileKey = remote.getProfileKey().or(local.getProfileKey()).orNull();
|
||||||
String username = remote.getUsername().or(local.getUsername()).or("");
|
String username = remote.getUsername().or(local.getUsername()).or("");
|
||||||
IdentityState identityState = remote.getIdentityState();
|
IdentityState identityState = remote.getIdentityState();
|
||||||
|
@ -146,7 +146,7 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor<Signal
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(@NonNull SignalContactRecord lhs, @NonNull SignalContactRecord rhs) {
|
public int compare(@NonNull SignalContactRecord lhs, @NonNull SignalContactRecord rhs) {
|
||||||
if (Objects.equals(lhs.getAddress().getAci(), rhs.getAddress().getAci()) ||
|
if (Objects.equals(lhs.getAddress().getServiceId(), rhs.getAddress().getServiceId()) ||
|
||||||
Objects.equals(lhs.getAddress().getNumber(), rhs.getAddress().getNumber()))
|
Objects.equals(lhs.getAddress().getNumber(), rhs.getAddress().getNumber()))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.groups.GroupId;
|
||||||
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues;
|
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues;
|
||||||
import org.thoughtcrime.securesms.subscription.Subscriber;
|
import org.thoughtcrime.securesms.subscription.Subscriber;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
|
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
|
||||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
|
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
|
||||||
|
@ -83,7 +84,7 @@ public final class StorageSyncModels {
|
||||||
|
|
||||||
private static @NonNull SignalAccountRecord.PinnedConversation localToRemotePinnedConversation(@NonNull RecipientRecord settings) {
|
private static @NonNull SignalAccountRecord.PinnedConversation localToRemotePinnedConversation(@NonNull RecipientRecord settings) {
|
||||||
switch (settings.getGroupType()) {
|
switch (settings.getGroupType()) {
|
||||||
case NONE : return SignalAccountRecord.PinnedConversation.forContact(new SignalServiceAddress(settings.getAci(), settings.getE164()));
|
case NONE : return SignalAccountRecord.PinnedConversation.forContact(new SignalServiceAddress(settings.getServiceId(), settings.getE164()));
|
||||||
case SIGNAL_V1: return SignalAccountRecord.PinnedConversation.forGroupV1(settings.getGroupId().requireV1().getDecodedId());
|
case SIGNAL_V1: return SignalAccountRecord.PinnedConversation.forGroupV1(settings.getGroupId().requireV1().getDecodedId());
|
||||||
case SIGNAL_V2: return SignalAccountRecord.PinnedConversation.forGroupV2(settings.getSyncExtras().getGroupMasterKey().serialize());
|
case SIGNAL_V2: return SignalAccountRecord.PinnedConversation.forGroupV2(settings.getSyncExtras().getGroupMasterKey().serialize());
|
||||||
default : throw new AssertionError("Unexpected group type!");
|
default : throw new AssertionError("Unexpected group type!");
|
||||||
|
@ -91,13 +92,13 @@ public final class StorageSyncModels {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NonNull SignalContactRecord localToRemoteContact(@NonNull RecipientRecord recipient, byte[] rawStorageId) {
|
private static @NonNull SignalContactRecord localToRemoteContact(@NonNull RecipientRecord recipient, byte[] rawStorageId) {
|
||||||
if (recipient.getAci() == null && recipient.getE164() == null) {
|
if (recipient.getServiceId() == null && recipient.getE164() == null) {
|
||||||
throw new AssertionError("Must have either a UUID or a phone number!");
|
throw new AssertionError("Must have either a UUID or a phone number!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ACI aci = recipient.getAci() != null ? recipient.getAci() : ACI.UNKNOWN;
|
ServiceId serviceId = recipient.getServiceId() != null ? recipient.getServiceId() : ServiceId.UNKNOWN;
|
||||||
|
|
||||||
return new SignalContactRecord.Builder(rawStorageId, new SignalServiceAddress(aci, recipient.getE164()), recipient.getSyncExtras().getStorageProto())
|
return new SignalContactRecord.Builder(rawStorageId, new SignalServiceAddress(serviceId, recipient.getE164()), recipient.getSyncExtras().getStorageProto())
|
||||||
.setProfileKey(recipient.getProfileKey())
|
.setProfileKey(recipient.getProfileKey())
|
||||||
.setGivenName(recipient.getProfileName().getGivenName())
|
.setGivenName(recipient.getProfileName().getGivenName())
|
||||||
.setFamilyName(recipient.getProfileName().getFamilyName())
|
.setFamilyName(recipient.getProfileName().getFamilyName())
|
||||||
|
|
|
@ -142,7 +142,7 @@ public final class StorageSyncValidations {
|
||||||
|
|
||||||
if (insert.getContact().isPresent()) {
|
if (insert.getContact().isPresent()) {
|
||||||
SignalServiceAddress address = insert.getContact().get().getAddress();
|
SignalServiceAddress address = insert.getContact().get().getAddress();
|
||||||
if (self.requireE164().equals(address.getNumber().or("")) || self.requireAci().equals(address.getAci())) {
|
if (self.requireE164().equals(address.getNumber().or("")) || self.requireServiceId().equals(address.getServiceId())) {
|
||||||
throw new SelfAddedAsContactError();
|
throw new SelfAddedAsContactError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ public final class BucketingUtil {
|
||||||
* Calculate a user bucket for a given feature flag, uuid, and part per modulus.
|
* Calculate a user bucket for a given feature flag, uuid, and part per modulus.
|
||||||
*
|
*
|
||||||
* @param key Feature flag key (e.g., "research.megaphone.1")
|
* @param key Feature flag key (e.g., "research.megaphone.1")
|
||||||
* @param uuid Current user's UUID (see {@link Recipient#getAci()})
|
* @param uuid Current user's UUID (see {@link Recipient#getServiceId()})
|
||||||
* @param modulus Drives the bucketing parts per N (e.g., passing 1,000,000 indicates bucketing into parts per million)
|
* @param modulus Drives the bucketing parts per N (e.g., passing 1,000,000 indicates bucketing into parts per million)
|
||||||
*/
|
*/
|
||||||
public static long bucket(@NonNull String key, @NonNull UUID uuid, long modulus) {
|
public static long bucket(@NonNull String key, @NonNull UUID uuid, long modulus) {
|
||||||
|
|
|
@ -240,7 +240,7 @@ public class CommunicationActions {
|
||||||
SimpleTask.run(() -> {
|
SimpleTask.run(() -> {
|
||||||
Recipient recipient = Recipient.external(activity, e164);
|
Recipient recipient = Recipient.external(activity, e164);
|
||||||
|
|
||||||
if (!recipient.isRegistered() || !recipient.hasAci()) {
|
if (!recipient.isRegistered() || !recipient.hasServiceId()) {
|
||||||
try {
|
try {
|
||||||
DirectoryHelper.refreshDirectoryFor(activity, recipient, false);
|
DirectoryHelper.refreshDirectoryFor(activity, recipient, false);
|
||||||
recipient = Recipient.resolved(recipient.getId());
|
recipient = Recipient.resolved(recipient.getId());
|
||||||
|
|
|
@ -161,7 +161,7 @@ public final class IdentityUtil {
|
||||||
public static void processVerifiedMessage(Context context, VerifiedMessage verifiedMessage) {
|
public static void processVerifiedMessage(Context context, VerifiedMessage verifiedMessage) {
|
||||||
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||||
SignalIdentityKeyStore identityStore = ApplicationDependencies.getProtocolStore().aci().identities();
|
SignalIdentityKeyStore identityStore = ApplicationDependencies.getProtocolStore().aci().identities();
|
||||||
Recipient recipient = Recipient.externalPush(context, verifiedMessage.getDestination());
|
Recipient recipient = Recipient.externalPush(verifiedMessage.getDestination());
|
||||||
Optional<IdentityRecord> identityRecord = identityStore.getIdentityRecord(recipient.getId());
|
Optional<IdentityRecord> identityRecord = identityStore.getIdentityRecord(recipient.getId());
|
||||||
|
|
||||||
if (!identityRecord.isPresent() && verifiedMessage.getVerified() == VerifiedMessage.VerifiedState.DEFAULT) {
|
if (!identityRecord.isPresent() && verifiedMessage.getVerified() == VerifiedMessage.VerifiedState.DEFAULT) {
|
||||||
|
|
|
@ -76,12 +76,12 @@ public final class LocaleFeatureFlags {
|
||||||
Map<String, Integer> countryCodeValues = parseCountryValues(serialized, 0);
|
Map<String, Integer> countryCodeValues = parseCountryValues(serialized, 0);
|
||||||
Recipient self = Recipient.self();
|
Recipient self = Recipient.self();
|
||||||
|
|
||||||
if (countryCodeValues.isEmpty() || !self.getE164().isPresent() || !self.getAci().isPresent()) {
|
if (countryCodeValues.isEmpty() || !self.getE164().isPresent() || !self.getServiceId().isPresent()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
long countEnabled = getCountryValue(countryCodeValues, self.getE164().or(""), 0);
|
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;
|
return countEnabled > currentUserBucket;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import org.signal.core.util.logging.Log;
|
||||||
import org.signal.zkgroup.InvalidInputException;
|
import org.signal.zkgroup.InvalidInputException;
|
||||||
import org.signal.zkgroup.profiles.ProfileKey;
|
import org.signal.zkgroup.profiles.ProfileKey;
|
||||||
import org.thoughtcrime.securesms.badges.models.Badge;
|
import org.thoughtcrime.securesms.badges.models.Badge;
|
||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
|
||||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
|
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
|
||||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||||
|
@ -284,7 +283,7 @@ public final class ProfileUtil {
|
||||||
|
|
||||||
ProfileKey profileKey = ProfileKeyUtil.getSelfProfileKey();
|
ProfileKey profileKey = ProfileKeyUtil.getSelfProfileKey();
|
||||||
SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
|
||||||
String avatarPath = accountManager.setVersionedProfile(Recipient.self().requireAci(),
|
String avatarPath = accountManager.setVersionedProfile(SignalStore.account().requireAci(),
|
||||||
profileKey,
|
profileKey,
|
||||||
profileName.serialize(),
|
profileName.serialize(),
|
||||||
about,
|
about,
|
||||||
|
@ -321,8 +320,8 @@ public final class ProfileUtil {
|
||||||
|
|
||||||
private static @NonNull SignalServiceAddress toSignalServiceAddress(@NonNull Context context, @NonNull Recipient recipient) throws IOException {
|
private static @NonNull SignalServiceAddress toSignalServiceAddress(@NonNull Context context, @NonNull Recipient recipient) throws IOException {
|
||||||
if (recipient.getRegistered() == RecipientDatabase.RegisteredState.NOT_REGISTERED) {
|
if (recipient.getRegistered() == RecipientDatabase.RegisteredState.NOT_REGISTERED) {
|
||||||
if (recipient.hasAci()) {
|
if (recipient.hasServiceId()) {
|
||||||
return new SignalServiceAddress(recipient.requireAci(), recipient.getE164().orNull());
|
return new SignalServiceAddress(recipient.requireServiceId(), recipient.getE164().orNull());
|
||||||
} else {
|
} else {
|
||||||
throw new IOException(recipient.getId() + " not registered!");
|
throw new IOException(recipient.getId() + " not registered!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package org.thoughtcrime.securesms.util
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
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
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,10 +11,10 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||||
*/
|
*/
|
||||||
class RecipientAccessList(private val recipients: List<Recipient>) : List<Recipient> by recipients {
|
class RecipientAccessList(private val recipients: List<Recipient>) : List<Recipient> by recipients {
|
||||||
|
|
||||||
private val byAci: Map<ACI, Recipient> by lazy {
|
private val byServiceId: Map<ServiceId, Recipient> by lazy {
|
||||||
recipients
|
recipients
|
||||||
.filter { it.hasAci() }
|
.filter { it.hasServiceId() }
|
||||||
.associateBy { it.requireAci() }
|
.associateBy { it.requireServiceId() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val byE164: Map<String, Recipient> by lazy {
|
private val byE164: Map<String, Recipient> by lazy {
|
||||||
|
@ -24,8 +24,8 @@ class RecipientAccessList(private val recipients: List<Recipient>) : List<Recipi
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requireByAddress(address: SignalServiceAddress): Recipient {
|
fun requireByAddress(address: SignalServiceAddress): Recipient {
|
||||||
if (byAci.containsKey(address.aci)) {
|
if (byServiceId.containsKey(address.serviceId)) {
|
||||||
return byAci[address.aci]!!
|
return byServiceId[address.serviceId]!!
|
||||||
} else if (address.number.isPresent && byE164.containsKey(address.number.get())) {
|
} else if (address.number.isPresent && byE164.containsKey(address.number.get())) {
|
||||||
return byE164[address.number.get()]!!
|
return byE164[address.number.get()]!!
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ACI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -51,15 +52,15 @@ public class UsernameUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
public static @NonNull Optional<ACI> fetchAciForUsername(@NonNull Context context, @NonNull String username) {
|
public static @NonNull Optional<ServiceId> fetchAciForUsername(@NonNull String username) {
|
||||||
Optional<RecipientId> localId = SignalDatabase.recipients().getByUsername(username);
|
Optional<RecipientId> localId = SignalDatabase.recipients().getByUsername(username);
|
||||||
|
|
||||||
if (localId.isPresent()) {
|
if (localId.isPresent()) {
|
||||||
Recipient recipient = Recipient.resolved(localId.get());
|
Recipient recipient = Recipient.resolved(localId.get());
|
||||||
|
|
||||||
if (recipient.getAci().isPresent()) {
|
if (recipient.getServiceId().isPresent()) {
|
||||||
Log.i(TAG, "Found username locally -- using associated UUID.");
|
Log.i(TAG, "Found username locally -- using associated UUID.");
|
||||||
return recipient.getAci();
|
return recipient.getServiceId();
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Found username locally, but it had no associated UUID! Clearing it.");
|
Log.w(TAG, "Found username locally, but it had no associated UUID! Clearing it.");
|
||||||
SignalDatabase.recipients().clearUsernameIfExists(username);
|
SignalDatabase.recipients().clearUsernameIfExists(username);
|
||||||
|
|
|
@ -16,7 +16,6 @@ import android.text.TextUtils;
|
||||||
import android.text.method.LinkMovementMethod;
|
import android.text.method.LinkMovementMethod;
|
||||||
import android.view.ContextMenu;
|
import android.view.ContextMenu;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -35,7 +34,6 @@ import android.widget.Toast;
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
|
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
|
||||||
|
@ -212,18 +210,18 @@ public class VerifyDisplayFragment extends Fragment implements ViewTreeObserver.
|
||||||
//noinspection WrongThread
|
//noinspection WrongThread
|
||||||
Recipient resolved = recipient.resolve();
|
Recipient resolved = recipient.resolve();
|
||||||
|
|
||||||
if (FeatureFlags.verifyV2() && resolved.getAci().isPresent()) {
|
if (FeatureFlags.verifyV2() && resolved.getServiceId().isPresent()) {
|
||||||
Log.i(TAG, "Using UUID (version 2).");
|
Log.i(TAG, "Using UUID (version 2).");
|
||||||
version = 2;
|
version = 2;
|
||||||
localId = Recipient.self().requireAci().toByteArray();
|
localId = Recipient.self().requireServiceId().toByteArray();
|
||||||
remoteId = resolved.requireAci().toByteArray();
|
remoteId = resolved.requireServiceId().toByteArray();
|
||||||
} else if (!FeatureFlags.verifyV2() && resolved.getE164().isPresent()) {
|
} else if (!FeatureFlags.verifyV2() && resolved.getE164().isPresent()) {
|
||||||
Log.i(TAG, "Using E164 (version 1).");
|
Log.i(TAG, "Using E164 (version 1).");
|
||||||
version = 1;
|
version = 1;
|
||||||
localId = Recipient.self().requireE164().getBytes();
|
localId = Recipient.self().requireE164().getBytes();
|
||||||
remoteId = resolved.requireE164().getBytes();
|
remoteId = resolved.requireE164().getBytes();
|
||||||
} else {
|
} 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())
|
new MaterialAlertDialogBuilder(requireContext())
|
||||||
.setMessage(getString(R.string.VerifyIdentityActivity_you_must_first_exchange_messages_in_order_to_view, resolved.getDisplayName(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())
|
.setPositiveButton(android.R.string.ok, (dialog, which) -> requireActivity().finish())
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedMember;
|
||||||
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
|
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember;
|
||||||
import org.thoughtcrime.securesms.testutil.MainThreadUtil;
|
import org.thoughtcrime.securesms.testutil.MainThreadUtil;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.api.util.UuidUtil;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -1351,14 +1352,14 @@ public final class GroupsV2UpdateMessageProducerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertSingleChangeMentioning(DecryptedGroupChange change, List<UUID> expectedMentions) {
|
private void assertSingleChangeMentioning(DecryptedGroupChange change, List<UUID> expectedMentions) {
|
||||||
List<ACI> expectedMentionAcis = expectedMentions.stream().map(ACI::from).collect(Collectors.toList());
|
List<ServiceId> expectedMentionSids = expectedMentions.stream().map(ServiceId::from).collect(Collectors.toList());
|
||||||
|
|
||||||
List<UpdateDescription> changes = producer.describeChanges(null, change);
|
List<UpdateDescription> changes = producer.describeChanges(null, change);
|
||||||
|
|
||||||
assertThat(changes.size(), is(1));
|
assertThat(changes.size(), is(1));
|
||||||
|
|
||||||
UpdateDescription description = changes.get(0);
|
UpdateDescription description = changes.get(0);
|
||||||
assertThat(description.getMentioned(), is(expectedMentionAcis));
|
assertThat(description.getMentioned(), is(expectedMentionSids));
|
||||||
|
|
||||||
if (expectedMentions.isEmpty()) {
|
if (expectedMentions.isEmpty()) {
|
||||||
assertTrue(description.isStringStatic());
|
assertTrue(description.isStringStatic());
|
||||||
|
@ -1397,8 +1398,8 @@ public final class GroupsV2UpdateMessageProducerTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NonNull GroupsV2UpdateMessageProducer.DescribeMemberStrategy createDescriber(@NonNull Map<UUID, String> map) {
|
private static @NonNull GroupsV2UpdateMessageProducer.DescribeMemberStrategy createDescriber(@NonNull Map<UUID, String> map) {
|
||||||
return aci -> {
|
return serviceId -> {
|
||||||
String name = map.get(aci.uuid());
|
String name = map.get(serviceId.uuid());
|
||||||
assertNotNull(name);
|
assertNotNull(name);
|
||||||
return name;
|
return name;
|
||||||
};
|
};
|
||||||
|
|
|
@ -266,7 +266,7 @@ public final class RecipientIdCacheTest {
|
||||||
Recipient mock = mock(Recipient.class);
|
Recipient mock = mock(Recipient.class);
|
||||||
|
|
||||||
when(mock.getId()).thenReturn(recipientId);
|
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));
|
when(mock.getE164()).thenReturn(Optional.fromNullable(e164));
|
||||||
|
|
||||||
return mock;
|
return mock;
|
||||||
|
|
|
@ -27,10 +27,8 @@ import org.whispersystems.signalservice.api.storage.StorageId;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertTrue;
|
import static junit.framework.TestCase.assertTrue;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -57,7 +55,7 @@ public final class StorageSyncHelperTest {
|
||||||
|
|
||||||
private static final Recipient SELF = mock(Recipient.class);
|
private static final Recipient SELF = mock(Recipient.class);
|
||||||
static {
|
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.getE164()).thenReturn(Optional.of(E164_SELF));
|
||||||
when(SELF.resolve()).thenReturn(SELF);
|
when(SELF.resolve()).thenReturn(SELF);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,9 @@ import org.whispersystems.signalservice.api.payments.CurrencyConversions;
|
||||||
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
||||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfileWrite;
|
import org.whispersystems.signalservice.api.profiles.SignalServiceProfileWrite;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.PNI;
|
||||||
|
import org.whispersystems.signalservice.api.push.ServiceIdType;
|
||||||
import org.whispersystems.signalservice.api.push.SignedPreKeyEntity;
|
import org.whispersystems.signalservice.api.push.SignedPreKeyEntity;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.NoContentException;
|
import org.whispersystems.signalservice.api.push.exceptions.NoContentException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||||
|
@ -420,18 +421,18 @@ public class SignalServiceAccountManager {
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void setPreKeys(AccountIdentifier accountId, IdentityKey identityKey, SignedPreKeyRecord signedPreKey, List<PreKeyRecord> oneTimePreKeys)
|
public void setPreKeys(ServiceIdType serviceIdType, IdentityKey identityKey, SignedPreKeyRecord signedPreKey, List<PreKeyRecord> oneTimePreKeys)
|
||||||
throws IOException
|
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.
|
* @return The server's count of currently available (eg. unused) prekeys for this user.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public int getPreKeysCount(AccountIdentifier accountId) throws IOException {
|
public int getPreKeysCount(ServiceIdType serviceIdType) throws IOException {
|
||||||
return this.pushServiceSocket.getAvailablePreKeys(accountId);
|
return this.pushServiceSocket.getAvailablePreKeys(serviceIdType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -440,22 +441,22 @@ public class SignalServiceAccountManager {
|
||||||
* @param signedPreKey The client's new signed prekey.
|
* @param signedPreKey The client's new signed prekey.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void setSignedPreKey(AccountIdentifier accountId, SignedPreKeyRecord signedPreKey) throws IOException {
|
public void setSignedPreKey(ServiceIdType serviceIdType, SignedPreKeyRecord signedPreKey) throws IOException {
|
||||||
this.pushServiceSocket.setCurrentSignedPreKey(accountId, signedPreKey);
|
this.pushServiceSocket.setCurrentSignedPreKey(serviceIdType, signedPreKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The server's view of the client's current signed prekey.
|
* @return The server's view of the client's current signed prekey.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public SignedPreKeyEntity getSignedPreKey(AccountIdentifier accountId) throws IOException {
|
public SignedPreKeyEntity getSignedPreKey(ServiceIdType serviceIdType) throws IOException {
|
||||||
return this.pushServiceSocket.getCurrentSignedPreKey(accountId);
|
return this.pushServiceSocket.getCurrentSignedPreKey(serviceIdType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if the identifier corresponds to a registered user, otherwise false.
|
* @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);
|
return pushServiceSocket.isIdentifierRegistered(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,11 +816,11 @@ public class SignalServiceAccountManager {
|
||||||
profileAvatarData);
|
profileAvatarData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ProfileKeyCredential> resolveProfileKeyCredential(ACI aci, ProfileKey profileKey, Locale locale)
|
public Optional<ProfileKeyCredential> resolveProfileKeyCredential(ServiceId serviceId, ProfileKey profileKey, Locale locale)
|
||||||
throws NonSuccessfulResponseCodeException, PushNetworkException
|
throws NonSuccessfulResponseCodeException, PushNetworkException
|
||||||
{
|
{
|
||||||
try {
|
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();
|
return credential.getProfileKeyCredential();
|
||||||
} catch (InterruptedException | TimeoutException e) {
|
} catch (InterruptedException | TimeoutException e) {
|
||||||
throw new PushNetworkException(e);
|
throw new PushNetworkException(e);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.whispersystems.signalservice.api;
|
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
|
* 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.
|
* @return A {@link SignalServiceAccountDataStore} for the specified account.
|
||||||
*/
|
*/
|
||||||
SignalServiceAccountDataStore get(AccountIdentifier accountIdentifier);
|
SignalServiceAccountDataStore get(ServiceId accountIdentifier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A {@link SignalServiceAccountDataStore} for the ACI account.
|
* @return A {@link SignalServiceAccountDataStore} for the ACI account.
|
||||||
|
|
|
@ -21,10 +21,10 @@ import org.whispersystems.signalservice.api.messages.SignalServiceStickerManifes
|
||||||
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
||||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException;
|
import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException;
|
||||||
import org.whispersystems.signalservice.api.util.CredentialsProvider;
|
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.configuration.SignalServiceConfiguration;
|
||||||
import org.whispersystems.signalservice.internal.push.PushServiceSocket;
|
import org.whispersystems.signalservice.internal.push.PushServiceSocket;
|
||||||
import org.whispersystems.signalservice.internal.push.SignalServiceEnvelopeEntity;
|
import org.whispersystems.signalservice.internal.push.SignalServiceEnvelopeEntity;
|
||||||
|
@ -43,7 +43,6 @@ import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The primary interface for receiving Signal Service messages.
|
* The primary interface for receiving Signal Service messages.
|
||||||
|
@ -91,13 +90,13 @@ public class SignalServiceMessageReceiver {
|
||||||
SignalServiceProfile.RequestType requestType,
|
SignalServiceProfile.RequestType requestType,
|
||||||
Locale locale)
|
Locale locale)
|
||||||
{
|
{
|
||||||
ACI aci = address.getAci();
|
ServiceId serviceId = address.getServiceId();
|
||||||
|
|
||||||
if (profileKey.isPresent()) {
|
if (profileKey.isPresent()) {
|
||||||
if (requestType == SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL) {
|
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 {
|
} 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,
|
return new ProfileAndCredential(profile,
|
||||||
SignalServiceProfile.RequestType.PROFILE,
|
SignalServiceProfile.RequestType.PROFILE,
|
||||||
Optional.absent());
|
Optional.absent());
|
||||||
|
|
|
@ -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.messages.shared.SharedContact;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ACI;
|
||||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
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.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException;
|
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.signalservice.internal.util.Util;
|
||||||
import org.whispersystems.util.Base64;
|
import org.whispersystems.util.Base64;
|
||||||
import org.whispersystems.util.ByteArrayUtil;
|
import org.whispersystems.util.ByteArrayUtil;
|
||||||
import org.whispersystems.util.FlagUtil;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -795,7 +795,7 @@ public class SignalServiceMessageSender {
|
||||||
DataMessage.Quote.Builder quoteBuilder = DataMessage.Quote.newBuilder()
|
DataMessage.Quote.Builder quoteBuilder = DataMessage.Quote.newBuilder()
|
||||||
.setId(message.getQuote().get().getId())
|
.setId(message.getQuote().get().getId())
|
||||||
.setText(message.getQuote().get().getText())
|
.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()) {
|
if (!message.getQuote().get().getMentions().isEmpty()) {
|
||||||
for (SignalServiceDataMessage.Mention mention : message.getQuote().get().getMentions()) {
|
for (SignalServiceDataMessage.Mention mention : message.getQuote().get().getMentions()) {
|
||||||
|
@ -891,7 +891,7 @@ public class SignalServiceMessageSender {
|
||||||
.setEmoji(message.getReaction().get().getEmoji())
|
.setEmoji(message.getReaction().get().getEmoji())
|
||||||
.setRemove(message.getReaction().get().isRemove())
|
.setRemove(message.getReaction().get().isRemove())
|
||||||
.setTargetSentTimestamp(message.getReaction().get().getTargetSentTimestamp())
|
.setTargetSentTimestamp(message.getReaction().get().getTargetSentTimestamp())
|
||||||
.setTargetAuthorUuid(message.getReaction().get().getTargetAuthor().getAci().toString());
|
.setTargetAuthorUuid(message.getReaction().get().getTargetAuthor().getServiceId().toString());
|
||||||
|
|
||||||
builder.setReaction(reactionBuilder.build());
|
builder.setReaction(reactionBuilder.build());
|
||||||
builder.setRequiredProtocolVersion(Math.max(DataMessage.ProtocolVersion.REACTIONS_VALUE, builder.getRequiredProtocolVersion()));
|
builder.setRequiredProtocolVersion(Math.max(DataMessage.ProtocolVersion.REACTIONS_VALUE, builder.getRequiredProtocolVersion()));
|
||||||
|
@ -1071,7 +1071,7 @@ public class SignalServiceMessageSender {
|
||||||
if (result.getSuccess() != null) {
|
if (result.getSuccess() != null) {
|
||||||
SyncMessage.Sent.UnidentifiedDeliveryStatus.Builder builder = SyncMessage.Sent.UnidentifiedDeliveryStatus.newBuilder();
|
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()) {
|
if (result.getAddress().getNumber().isPresent()) {
|
||||||
builder.setDestinationE164(result.getAddress().getNumber().get());
|
builder.setDestinationE164(result.getAddress().getNumber().get());
|
||||||
|
@ -1084,7 +1084,7 @@ public class SignalServiceMessageSender {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recipient.isPresent()) {
|
if (recipient.isPresent()) {
|
||||||
sentMessage.setDestinationUuid(recipient.get().getAci().toString());
|
sentMessage.setDestinationUuid(recipient.get().getServiceId().toString());
|
||||||
|
|
||||||
if (recipient.get().getNumber().isPresent()) {
|
if (recipient.get().getNumber().isPresent()) {
|
||||||
sentMessage.setDestinationE164(recipient.get().getNumber().get());
|
sentMessage.setDestinationE164(recipient.get().getNumber().get());
|
||||||
|
@ -1112,7 +1112,7 @@ public class SignalServiceMessageSender {
|
||||||
for (ReadMessage readMessage : readMessages) {
|
for (ReadMessage readMessage : readMessages) {
|
||||||
SyncMessage.Read.Builder readBuilder = SyncMessage.Read.newBuilder().setTimestamp(readMessage.getTimestamp());
|
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()) {
|
if (readMessage.getSender().getNumber().isPresent()) {
|
||||||
readBuilder.setSenderE164(readMessage.getSender().getNumber().get());
|
readBuilder.setSenderE164(readMessage.getSender().getNumber().get());
|
||||||
|
@ -1131,7 +1131,7 @@ public class SignalServiceMessageSender {
|
||||||
for (ViewedMessage readMessage : readMessages) {
|
for (ViewedMessage readMessage : readMessages) {
|
||||||
SyncMessage.Viewed.Builder viewedBuilder = SyncMessage.Viewed.newBuilder().setTimestamp(readMessage.getTimestamp());
|
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()) {
|
if (readMessage.getSender().getNumber().isPresent()) {
|
||||||
viewedBuilder.setSenderE164(readMessage.getSender().getNumber().get());
|
viewedBuilder.setSenderE164(readMessage.getSender().getNumber().get());
|
||||||
|
@ -1148,7 +1148,7 @@ public class SignalServiceMessageSender {
|
||||||
SyncMessage.Builder builder = createSyncMessageBuilder();
|
SyncMessage.Builder builder = createSyncMessageBuilder();
|
||||||
SyncMessage.ViewOnceOpen.Builder viewOnceBuilder = SyncMessage.ViewOnceOpen.newBuilder().setTimestamp(readMessage.getTimestamp());
|
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()) {
|
if (readMessage.getSender().getNumber().isPresent()) {
|
||||||
viewOnceBuilder.setSenderE164(readMessage.getSender().getNumber().get());
|
viewOnceBuilder.setSenderE164(readMessage.getSender().getNumber().get());
|
||||||
|
@ -1165,7 +1165,7 @@ public class SignalServiceMessageSender {
|
||||||
SyncMessage.Blocked.Builder blockedMessage = SyncMessage.Blocked.newBuilder();
|
SyncMessage.Blocked.Builder blockedMessage = SyncMessage.Blocked.newBuilder();
|
||||||
|
|
||||||
for (SignalServiceAddress address : blocked.getAddresses()) {
|
for (SignalServiceAddress address : blocked.getAddresses()) {
|
||||||
blockedMessage.addUuids(address.getAci().toString());
|
blockedMessage.addUuids(address.getServiceId().toString());
|
||||||
if (address.getNumber().isPresent()) {
|
if (address.getNumber().isPresent()) {
|
||||||
blockedMessage.addNumbers(address.getNumber().get());
|
blockedMessage.addNumbers(address.getNumber().get());
|
||||||
}
|
}
|
||||||
|
@ -1268,7 +1268,7 @@ public class SignalServiceMessageSender {
|
||||||
if (message.getPerson().get().getNumber().isPresent()) {
|
if (message.getPerson().get().getNumber().isPresent()) {
|
||||||
responseMessage.setThreadE164(message.getPerson().get().getNumber().get());
|
responseMessage.setThreadE164(message.getPerson().get().getNumber().get());
|
||||||
}
|
}
|
||||||
responseMessage.setThreadUuid(message.getPerson().get().getAci().toString());
|
responseMessage.setThreadUuid(message.getPerson().get().getServiceId().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (message.getType()) {
|
switch (message.getType()) {
|
||||||
|
@ -1301,7 +1301,7 @@ public class SignalServiceMessageSender {
|
||||||
SyncMessage.OutgoingPayment.Builder paymentMessage = SyncMessage.OutgoingPayment.newBuilder();
|
SyncMessage.OutgoingPayment.Builder paymentMessage = SyncMessage.OutgoingPayment.newBuilder();
|
||||||
|
|
||||||
if (message.getRecipient().isPresent()) {
|
if (message.getRecipient().isPresent()) {
|
||||||
paymentMessage.setRecipientUuid(message.getRecipient().get().getAci().toString());
|
paymentMessage.setRecipientUuid(message.getRecipient().get().getServiceId().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.getNote().isPresent()) {
|
if (message.getNote().isPresent()) {
|
||||||
|
@ -1353,7 +1353,7 @@ public class SignalServiceMessageSender {
|
||||||
|
|
||||||
verifiedMessageBuilder.setNullMessage(ByteString.copyFrom(nullMessage));
|
verifiedMessageBuilder.setNullMessage(ByteString.copyFrom(nullMessage));
|
||||||
verifiedMessageBuilder.setIdentityKey(ByteString.copyFrom(verifiedMessage.getIdentityKey().serialize()));
|
verifiedMessageBuilder.setIdentityKey(ByteString.copyFrom(verifiedMessage.getIdentityKey().serialize()));
|
||||||
verifiedMessageBuilder.setDestinationUuid(verifiedMessage.getDestination().getAci().toString());
|
verifiedMessageBuilder.setDestinationUuid(verifiedMessage.getDestination().getServiceId().toString());
|
||||||
|
|
||||||
if (verifiedMessage.getDestination().getNumber().isPresent()) {
|
if (verifiedMessage.getDestination().getNumber().isPresent()) {
|
||||||
verifiedMessageBuilder.setDestinationE164(verifiedMessage.getDestination().getNumber().get());
|
verifiedMessageBuilder.setDestinationE164(verifiedMessage.getDestination().getNumber().get());
|
||||||
|
@ -1745,12 +1745,12 @@ public class SignalServiceMessageSender {
|
||||||
|
|
||||||
Preconditions.checkArgument(recipients.size() == unidentifiedAccess.size(), "[" + timestamp + "] Unidentified access mismatch!");
|
Preconditions.checkArgument(recipients.size() == unidentifiedAccess.size(), "[" + timestamp + "] Unidentified access mismatch!");
|
||||||
|
|
||||||
Map<ACI, UnidentifiedAccess> accessByAci = new HashMap<>();
|
Map<ServiceId, UnidentifiedAccess> accessBySid = new HashMap<>();
|
||||||
Iterator<SignalServiceAddress> addressIterator = recipients.iterator();
|
Iterator<SignalServiceAddress> addressIterator = recipients.iterator();
|
||||||
Iterator<UnidentifiedAccess> accessIterator = unidentifiedAccess.iterator();
|
Iterator<UnidentifiedAccess> accessIterator = unidentifiedAccess.iterator();
|
||||||
|
|
||||||
while (addressIterator.hasNext()) {
|
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++) {
|
for (int i = 0; i < RETRY_COUNT; i++) {
|
||||||
|
@ -1758,7 +1758,7 @@ public class SignalServiceMessageSender {
|
||||||
Set<SignalProtocolAddress> sharedWith = store.getSenderKeySharedWith(distributionId);
|
Set<SignalProtocolAddress> sharedWith = store.getSenderKeySharedWith(distributionId);
|
||||||
List<SignalServiceAddress> needsSenderKey = targetInfo.destinations.stream()
|
List<SignalServiceAddress> needsSenderKey = targetInfo.destinations.stream()
|
||||||
.filter(a -> !sharedWith.contains(a))
|
.filter(a -> !sharedWith.contains(a))
|
||||||
.map(a -> ACI.parseOrThrow(a.getName()))
|
.map(a -> ServiceId.parseOrThrow(a.getName()))
|
||||||
.distinct()
|
.distinct()
|
||||||
.map(SignalServiceAddress::new)
|
.map(SignalServiceAddress::new)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
@ -1767,7 +1767,7 @@ public class SignalServiceMessageSender {
|
||||||
SenderKeyDistributionMessage message = getOrCreateNewGroupSession(distributionId);
|
SenderKeyDistributionMessage message = getOrCreateNewGroupSession(distributionId);
|
||||||
List<Optional<UnidentifiedAccessPair>> access = needsSenderKey.stream()
|
List<Optional<UnidentifiedAccessPair>> access = needsSenderKey.stream()
|
||||||
.map(r -> {
|
.map(r -> {
|
||||||
UnidentifiedAccess targetAccess = accessByAci.get(r.getAci());
|
UnidentifiedAccess targetAccess = accessBySid.get(r.getServiceId());
|
||||||
return Optional.of(new UnidentifiedAccessPair(targetAccess, targetAccess));
|
return Optional.of(new UnidentifiedAccessPair(targetAccess, targetAccess));
|
||||||
})
|
})
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
@ -1779,8 +1779,8 @@ public class SignalServiceMessageSender {
|
||||||
.map(SendMessageResult::getAddress)
|
.map(SendMessageResult::getAddress)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
Set<String> successAcis = successes.stream().map(a -> a.getAci().toString()).collect(Collectors.toSet());
|
Set<String> successSids = successes.stream().map(a -> a.getServiceId().toString()).collect(Collectors.toSet());
|
||||||
Set<SignalProtocolAddress> successAddresses = targetInfo.destinations.stream().filter(a -> successAcis.contains(a.getName())).collect(Collectors.toSet());
|
Set<SignalProtocolAddress> successAddresses = targetInfo.destinations.stream().filter(a -> successSids.contains(a.getName())).collect(Collectors.toSet());
|
||||||
|
|
||||||
store.markSenderKeySharedWith(distributionId, successAddresses);
|
store.markSenderKeySharedWith(distributionId, successAddresses);
|
||||||
|
|
||||||
|
@ -1794,12 +1794,12 @@ public class SignalServiceMessageSender {
|
||||||
.filter(r -> !r.isSuccess())
|
.filter(r -> !r.isSuccess())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
Set<ACI> failedAddresses = trueFailures.stream()
|
Set<ServiceId> failedAddresses = trueFailures.stream()
|
||||||
.map(result -> result.getAddress().getAci())
|
.map(result -> result.getAddress().getServiceId())
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
List<SendMessageResult> fakeNetworkFailures = recipients.stream()
|
List<SendMessageResult> fakeNetworkFailures = recipients.stream()
|
||||||
.filter(r -> !failedAddresses.contains(r.getAci()))
|
.filter(r -> !failedAddresses.contains(r.getServiceId()))
|
||||||
.map(SendMessageResult::networkFailure)
|
.map(SendMessageResult::networkFailure)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
@ -1914,7 +1914,7 @@ public class SignalServiceMessageSender {
|
||||||
|
|
||||||
List<SendMessageResult> success = recipients.keySet()
|
List<SendMessageResult> success = recipients.keySet()
|
||||||
.stream()
|
.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)))
|
.map(a -> SendMessageResult.success(a, recipients.get(a), true, store.isMultiDevice(), -1, Optional.of(content)))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
@ -2064,7 +2064,7 @@ public class SignalServiceMessageSender {
|
||||||
List<SignalProtocolAddress> addresses = new ArrayList<>(devices.size());
|
List<SignalProtocolAddress> addresses = new ArrayList<>(devices.size());
|
||||||
|
|
||||||
for (int staleDeviceId : devices) {
|
for (int staleDeviceId : devices) {
|
||||||
addresses.add(new SignalProtocolAddress(recipient.getAci().toString(), staleDeviceId));
|
addresses.add(new SignalProtocolAddress(recipient.getServiceId().toString(), staleDeviceId));
|
||||||
|
|
||||||
if (recipient.getNumber().isPresent()) {
|
if (recipient.getNumber().isPresent()) {
|
||||||
addresses.add(new SignalProtocolAddress(recipient.getNumber().get(), staleDeviceId));
|
addresses.add(new SignalProtocolAddress(recipient.getNumber().get(), staleDeviceId));
|
||||||
|
|
|
@ -100,7 +100,7 @@ public class SignalServiceCipher {
|
||||||
PushTransportDetails transport = new PushTransportDetails();
|
PushTransportDetails transport = new PushTransportDetails();
|
||||||
SignalProtocolAddress localProtocolAddress = new SignalProtocolAddress(localAddress.getIdentifier(), localDeviceId);
|
SignalProtocolAddress localProtocolAddress = new SignalProtocolAddress(localAddress.getIdentifier(), localDeviceId);
|
||||||
SignalGroupCipher groupCipher = new SignalGroupCipher(sessionLock, new GroupCipher(signalProtocolStore, localProtocolAddress));
|
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));
|
CiphertextMessage message = groupCipher.encrypt(distributionId.asUuid(), transport.getPaddedMessageBody(unpaddedMessage));
|
||||||
UnidentifiedSenderMessageContent messageContent = new UnidentifiedSenderMessageContent(message,
|
UnidentifiedSenderMessageContent messageContent = new UnidentifiedSenderMessageContent(message,
|
||||||
senderCertificate,
|
senderCertificate,
|
||||||
|
@ -117,7 +117,7 @@ public class SignalServiceCipher {
|
||||||
{
|
{
|
||||||
if (unidentifiedAccess.isPresent()) {
|
if (unidentifiedAccess.isPresent()) {
|
||||||
SignalSessionCipher sessionCipher = new SignalSessionCipher(sessionLock, new SessionCipher(signalProtocolStore, destination));
|
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());
|
return content.processSealedSender(sessionCipher, sealedSessionCipher, destination, unidentifiedAccess.get().getUnidentifiedCertificate());
|
||||||
} else {
|
} else {
|
||||||
|
@ -208,7 +208,7 @@ public class SignalServiceCipher {
|
||||||
paddedMessage = new PlaintextContent(ciphertext).getBody();
|
paddedMessage = new PlaintextContent(ciphertext).getBody();
|
||||||
metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), envelope.getServerReceivedTimestamp(), envelope.getServerDeliveredTimestamp(), false, envelope.getServerGuid(), Optional.absent());
|
metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), envelope.getServerReceivedTimestamp(), envelope.getServerDeliveredTimestamp(), false, envelope.getServerGuid(), Optional.absent());
|
||||||
} else if (envelope.isUnidentifiedSender()) {
|
} 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());
|
DecryptionResult result = sealedSessionCipher.decrypt(certificateValidator, ciphertext, envelope.getServerReceivedTimestamp());
|
||||||
SignalServiceAddress resultAddress = new SignalServiceAddress(ACI.parseOrThrow(result.getSenderUuid()), result.getSenderE164());
|
SignalServiceAddress resultAddress = new SignalServiceAddress(ACI.parseOrThrow(result.getSenderUuid()), result.getSenderE164());
|
||||||
Optional<byte[]> groupId = result.getGroupId();
|
Optional<byte[]> groupId = result.getGroupId();
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.whispersystems.libsignal.InvalidMessageException;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
|
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
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.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.util.OptionalUtil;
|
import org.whispersystems.signalservice.api.util.OptionalUtil;
|
||||||
|
|
||||||
|
@ -610,17 +611,17 @@ public class SignalServiceDataMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Mention {
|
public static class Mention {
|
||||||
private final ACI aci;
|
private final ServiceId aci;
|
||||||
private final int start;
|
private final int start;
|
||||||
private final int length;
|
private final int length;
|
||||||
|
|
||||||
public Mention(ACI aci, int start, int length) {
|
public Mention(ServiceId aci, int start, int length) {
|
||||||
this.aci = aci;
|
this.aci = aci;
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ACI getAci() {
|
public ServiceId getAci() {
|
||||||
return aci;
|
return aci;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.push.ACI;
|
import org.whispersystems.signalservice.api.push.ACI;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
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.push.SignalServiceProtos.Envelope;
|
||||||
import org.whispersystems.signalservice.internal.serialize.protos.SignalServiceEnvelopeProto;
|
import org.whispersystems.signalservice.internal.serialize.protos.SignalServiceEnvelopeProto;
|
||||||
import org.whispersystems.util.Base64;
|
import org.whispersystems.util.Base64;
|
||||||
|
@ -71,7 +70,7 @@ public class SignalServiceEnvelope {
|
||||||
.setServerTimestamp(serverReceivedTimestamp);
|
.setServerTimestamp(serverReceivedTimestamp);
|
||||||
|
|
||||||
if (sender.isPresent()) {
|
if (sender.isPresent()) {
|
||||||
builder.setSourceUuid(sender.get().getAci().toString());
|
builder.setSourceUuid(sender.get().getServiceId().toString());
|
||||||
|
|
||||||
if (sender.get().getNumber().isPresent()) {
|
if (sender.get().getNumber().isPresent()) {
|
||||||
builder.setSourceE164(sender.get().getNumber().get());
|
builder.setSourceE164(sender.get().getNumber().get());
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class DeviceContactsOutputStream extends ChunkedOutputStream {
|
||||||
private void writeContactDetails(DeviceContact contact) throws IOException {
|
private void writeContactDetails(DeviceContact contact) throws IOException {
|
||||||
SignalServiceProtos.ContactDetails.Builder contactDetails = SignalServiceProtos.ContactDetails.newBuilder();
|
SignalServiceProtos.ContactDetails.Builder contactDetails = SignalServiceProtos.ContactDetails.newBuilder();
|
||||||
|
|
||||||
contactDetails.setUuid(contact.getAddress().getAci().toString());
|
contactDetails.setUuid(contact.getAddress().getServiceId().toString());
|
||||||
|
|
||||||
if (contact.getAddress().getNumber().isPresent()) {
|
if (contact.getAddress().getNumber().isPresent()) {
|
||||||
contactDetails.setNumber(contact.getAddress().getNumber().get());
|
contactDetails.setNumber(contact.getAddress().getNumber().get());
|
||||||
|
@ -69,7 +69,7 @@ public class DeviceContactsOutputStream extends ChunkedOutputStream {
|
||||||
|
|
||||||
SignalServiceProtos.Verified.Builder verifiedBuilder = SignalServiceProtos.Verified.newBuilder()
|
SignalServiceProtos.Verified.Builder verifiedBuilder = SignalServiceProtos.Verified.newBuilder()
|
||||||
.setIdentityKey(ByteString.copyFrom(contact.getVerified().get().getIdentityKey().serialize()))
|
.setIdentityKey(ByteString.copyFrom(contact.getVerified().get().getIdentityKey().serialize()))
|
||||||
.setDestinationUuid(contact.getVerified().get().getDestination().getAci().toString())
|
.setDestinationUuid(contact.getVerified().get().getDestination().getServiceId().toString())
|
||||||
.setState(state);
|
.setState(state);
|
||||||
|
|
||||||
if (contact.getVerified().get().getDestination().getNumber().isPresent()) {
|
if (contact.getVerified().get().getDestination().getNumber().isPresent()) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ package org.whispersystems.signalservice.api.messages.multidevice;
|
||||||
|
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
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 org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -21,26 +21,29 @@ public class SentTranscriptMessage {
|
||||||
private final long timestamp;
|
private final long timestamp;
|
||||||
private final long expirationStartTimestamp;
|
private final long expirationStartTimestamp;
|
||||||
private final SignalServiceDataMessage message;
|
private final SignalServiceDataMessage message;
|
||||||
private final Map<String, Boolean> unidentifiedStatusByAci;
|
private final Map<String, Boolean> unidentifiedStatusBySid;
|
||||||
private final Map<String, Boolean> unidentifiedStatusByE164;
|
private final Map<String, Boolean> unidentifiedStatusByE164;
|
||||||
private final Set<SignalServiceAddress> recipients;
|
private final Set<SignalServiceAddress> recipients;
|
||||||
private final boolean isRecipientUpdate;
|
private final boolean isRecipientUpdate;
|
||||||
|
|
||||||
public SentTranscriptMessage(Optional<SignalServiceAddress> destination, long timestamp, SignalServiceDataMessage message,
|
public SentTranscriptMessage(Optional<SignalServiceAddress> destination,
|
||||||
long expirationStartTimestamp, Map<SignalServiceAddress, Boolean> unidentifiedStatus,
|
long timestamp,
|
||||||
|
SignalServiceDataMessage message,
|
||||||
|
long expirationStartTimestamp,
|
||||||
|
Map<SignalServiceAddress, Boolean> unidentifiedStatus,
|
||||||
boolean isRecipientUpdate)
|
boolean isRecipientUpdate)
|
||||||
{
|
{
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.expirationStartTimestamp = expirationStartTimestamp;
|
this.expirationStartTimestamp = expirationStartTimestamp;
|
||||||
this.unidentifiedStatusByAci = new HashMap<>();
|
this.unidentifiedStatusBySid = new HashMap<>();
|
||||||
this.unidentifiedStatusByE164 = new HashMap<>();
|
this.unidentifiedStatusByE164 = new HashMap<>();
|
||||||
this.recipients = unidentifiedStatus.keySet();
|
this.recipients = unidentifiedStatus.keySet();
|
||||||
this.isRecipientUpdate = isRecipientUpdate;
|
this.isRecipientUpdate = isRecipientUpdate;
|
||||||
|
|
||||||
for (Map.Entry<SignalServiceAddress, Boolean> entry : unidentifiedStatus.entrySet()) {
|
for (Map.Entry<SignalServiceAddress, Boolean> entry : unidentifiedStatus.entrySet()) {
|
||||||
unidentifiedStatusByAci.put(entry.getKey().getAci().toString(), entry.getValue());
|
unidentifiedStatusBySid.put(entry.getKey().getServiceId().toString(), entry.getValue());
|
||||||
|
|
||||||
if (entry.getKey().getNumber().isPresent()) {
|
if (entry.getKey().getNumber().isPresent()) {
|
||||||
unidentifiedStatusByE164.put(entry.getKey().getNumber().get(), entry.getValue());
|
unidentifiedStatusByE164.put(entry.getKey().getNumber().get(), entry.getValue());
|
||||||
|
@ -64,13 +67,13 @@ public class SentTranscriptMessage {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUnidentified(ACI aci) {
|
public boolean isUnidentified(ServiceId serviceId) {
|
||||||
return isUnidentified(aci.toString());
|
return isUnidentified(serviceId.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUnidentified(String destination) {
|
public boolean isUnidentified(String destination) {
|
||||||
if (unidentifiedStatusByAci.containsKey(destination)) {
|
if (unidentifiedStatusBySid.containsKey(destination)) {
|
||||||
return unidentifiedStatusByAci.get(destination);
|
return unidentifiedStatusBySid.get(destination);
|
||||||
} else if (unidentifiedStatusByE164.containsKey(destination)) {
|
} else if (unidentifiedStatusByE164.containsKey(destination)) {
|
||||||
return unidentifiedStatusByE164.get(destination);
|
return unidentifiedStatusByE164.get(destination);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,19 +2,15 @@ package org.whispersystems.signalservice.api.push;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
|
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
|
||||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
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
|
* 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.
|
* 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);
|
public static final ACI UNKNOWN = ACI.from(UuidUtil.UNKNOWN_UUID);
|
||||||
|
|
||||||
|
@ -22,51 +18,15 @@ public final class ACI extends AccountIdentifier {
|
||||||
return new ACI(uuid);
|
return new ACI(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<ACI> parse(String raw) {
|
|
||||||
return UuidUtil.parse(raw).transform(ACI::from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ACI parseOrThrow(String raw) {
|
public static ACI parseOrThrow(String raw) {
|
||||||
return from(UUID.fromString(raw));
|
return from(UUID.fromString(raw));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ACI parseOrThrow(byte[] raw) {
|
|
||||||
return from(UuidUtil.parseOrThrow(raw));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ACI parseOrNull(String raw) {
|
public static ACI parseOrNull(String raw) {
|
||||||
UUID uuid = UuidUtil.parseOrNull(raw);
|
UUID uuid = UuidUtil.parseOrNull(raw);
|
||||||
return uuid != null ? from(uuid) : null;
|
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<ACI> filterKnown(Collection<ACI> acis) {
|
|
||||||
return acis.stream().filter(aci -> !aci.equals(UNKNOWN)).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ACI(UUID uuid) {
|
private ACI(UUID uuid) {
|
||||||
super(uuid);
|
super(uuid);
|
||||||
}
|
}
|
||||||
|
@ -79,13 +39,13 @@ public final class ACI extends AccountIdentifier {
|
||||||
return UuidUtil.toByteArray(uuid);
|
return UuidUtil.toByteArray(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUnknown() {
|
|
||||||
return this.equals(UNKNOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAci() {
|
public boolean equals(Object other) {
|
||||||
return true;
|
if (other instanceof ServiceId) {
|
||||||
|
return uuid.equals(((ServiceId) other).uuid);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -93,15 +53,6 @@ public final class ACI extends AccountIdentifier {
|
||||||
return uuid.hashCode();
|
return uuid.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (other instanceof ACI) {
|
|
||||||
return uuid.equals(((ACI) other).uuid);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return uuid.toString();
|
return uuid.toString();
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
* 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.
|
* this *specific type* of UUID.
|
||||||
*/
|
*/
|
||||||
public final class PNI extends AccountIdentifier {
|
public final class PNI extends ServiceId {
|
||||||
|
|
||||||
public static PNI from(UUID uuid) {
|
public static PNI from(UUID uuid) {
|
||||||
return new PNI(uuid);
|
return new PNI(uuid);
|
||||||
|
@ -27,11 +27,6 @@ public final class PNI extends AccountIdentifier {
|
||||||
super(uuid);
|
super(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAci() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return uuid.hashCode();
|
return uuid.hashCode();
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue