Add support for rendering session switchover events.

This commit is contained in:
Greyson Parrelli
2023-02-07 11:26:57 -05:00
parent 03c68375db
commit 9e056e5dd0
11 changed files with 229 additions and 878 deletions

View File

@@ -2406,6 +2406,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
@VisibleForTesting
fun writePnpChangeSetToDisk(changeSet: PnpChangeSet, inputPni: PNI?): RecipientId {
var hadThreadMerge = false
for (operation in changeSet.operations) {
@Exhaustive
when (operation) {
@@ -2465,16 +2466,21 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
.run()
}
is PnpOperation.Merge -> {
merge(operation.primaryId, operation.secondaryId, inputPni)
val mergeResult: MergeResult = merge(operation.primaryId, operation.secondaryId, inputPni)
hadThreadMerge = hadThreadMerge || mergeResult.neededThreadMerge
}
is PnpOperation.SessionSwitchoverInsert -> {
val threadId: Long? = threads.getThreadIdFor(operation.recipientId)
if (threadId != null) {
val event = SessionSwitchoverEvent
.newBuilder()
.setE164(operation.e164 ?: "")
.build()
SignalDatabase.messages.insertSessionSwitchoverEvent(operation.recipientId, threadId, event)
if (hadThreadMerge) {
Log.d(TAG, "Skipping SSE insert because we already had a thread merge event.")
} else {
val threadId: Long? = threads.getThreadIdFor(operation.recipientId)
if (threadId != null) {
val event = SessionSwitchoverEvent
.newBuilder()
.setE164(operation.e164 ?: "")
.build()
SignalDatabase.messages.insertSessionSwitchoverEvent(operation.recipientId, threadId, event)
}
}
}
is PnpOperation.ChangeNumberInsert -> {
@@ -2622,6 +2628,14 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
)
}
if (!pniVerified && fullData.pniSidRecord != null && finalData.aciSidRecord != null && sessions.hasAnySessionFor(fullData.pniSidRecord.serviceId.toString())) {
breadCrumbs += "FinalUpdateSSE"
operations += PnpOperation.SessionSwitchoverInsert(
recipientId = primaryId,
e164 = finalData.e164
)
}
return PnpChangeSet(
id = PnpIdResolver.PnpNoopId(primaryId),
operations = operations,
@@ -3644,7 +3658,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
* Merges one ACI recipient with an E164 recipient. It is assumed that the E164 recipient does
* *not* have an ACI.
*/
private fun merge(primaryId: RecipientId, secondaryId: RecipientId, newPni: PNI? = null): RecipientId {
private fun merge(primaryId: RecipientId, secondaryId: RecipientId, newPni: PNI? = null): MergeResult {
ensureInTransaction()
val db = writableDatabase
val primaryRecord = getRecord(primaryId)
@@ -3656,7 +3670,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
}
// Threads
val threadMerge = threads.merge(primaryId, secondaryId)
val threadMerge: ThreadTable.MergeResult = threads.merge(primaryId, secondaryId)
threads.setLastScrolled(threadMerge.threadId, 0)
threads.update(threadMerge.threadId, false, false)
@@ -3721,7 +3735,11 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
}
db.update(TABLE_NAME, uuidValues, ID_WHERE, SqlUtil.buildArgs(primaryId))
return primaryId
return MergeResult(
finalId = primaryId,
neededThreadMerge = threadMerge.neededMerge
)
}
private fun ensureInTransaction() {
@@ -3845,6 +3863,8 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
* get them back through CDS).
*/
fun debugClearServiceIds(recipientId: RecipientId? = null) {
check(FeatureFlags.internalUser())
writableDatabase
.update(TABLE_NAME)
.values(
@@ -3868,6 +3888,8 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
* Should only be used for debugging! A very destructive action that clears all known profile keys and credentials.
*/
fun debugClearProfileData(recipientId: RecipientId? = null) {
check(FeatureFlags.internalUser())
writableDatabase
.update(TABLE_NAME)
.values(
@@ -3896,6 +3918,8 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
* Should only be used for debugging! Clears the E164 and PNI from a recipient.
*/
fun debugClearE164AndPni(recipientId: RecipientId) {
check(FeatureFlags.internalUser())
writableDatabase
.update(TABLE_NAME)
.values(
@@ -3905,7 +3929,28 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
.where(ID_WHERE, recipientId)
.run()
Recipient.live(recipientId).refresh()
ApplicationDependencies.getRecipientCache().clear()
RecipientId.clearCache()
}
/**
* Should only be used for debugging! Clears the ACI from a contact.
* Only works if the recipient has a PNI.
*/
fun debugRemoveAci(recipientId: RecipientId) {
check(FeatureFlags.internalUser())
writableDatabase.execSQL(
"""
UPDATE $TABLE_NAME
SET $SERVICE_ID = $PNI_COLUMN
WHERE $ID = ? AND $PNI_COLUMN NOT NULL
""".toSingleLine(),
SqlUtil.buildArgs(recipientId)
)
ApplicationDependencies.getRecipientCache().clear()
RecipientId.clearCache()
}
fun getRecord(context: Context, cursor: Cursor): RecipientRecord {
@@ -4131,6 +4176,11 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
)
}
private data class MergeResult(
val finalId: RecipientId,
val neededThreadMerge: Boolean
)
inner class BulkOperationsHandle internal constructor(private val database: SQLiteDatabase) {
private val pendingRecipients: MutableSet<RecipientId> = mutableSetOf()

View File

@@ -48,6 +48,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context;
import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateDetails;
import org.thoughtcrime.securesms.database.model.databaseprotos.ProfileChangeDetails;
import org.thoughtcrime.securesms.database.model.databaseprotos.SessionSwitchoverEvent;
import org.thoughtcrime.securesms.database.model.databaseprotos.ThreadMergeEvent;
import org.thoughtcrime.securesms.emoji.EmojiSource;
import org.thoughtcrime.securesms.emoji.JumboEmoji;
@@ -235,6 +236,18 @@ public abstract class MessageRecord extends DisplayRecord {
} catch (InvalidProtocolBufferException e) {
throw new AssertionError(e);
}
} else if (isSessionSwitchoverEventType()) {
try {
SessionSwitchoverEvent event = SessionSwitchoverEvent.parseFrom(Base64.decodeOrThrow(getBody()));
if (event.getE164().isEmpty()) {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)), R.drawable.ic_update_safety_number_16);
} else {
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_belongs_to_s, PhoneNumberFormatter.prettyPrint(r.requireE164()), r.getDisplayName(context)), R.drawable.ic_update_info_16);
}
} catch (InvalidProtocolBufferException e) {
throw new AssertionError(e);
}
} else if (isSmsExportType()) {
int messageResource = SignalStore.misc().getSmsExportPhase().isSmsSupported() ? R.string.MessageRecord__you_will_no_longer_be_able_to_send_sms_messages_from_signal_soon
: R.string.MessageRecord__you_can_no_longer_send_sms_messages_in_signal;
@@ -551,6 +564,10 @@ public abstract class MessageRecord extends DisplayRecord {
return MessageTypes.isThreadMergeType(type);
}
public boolean isSessionSwitchoverEventType() {
return MessageTypes.isSessionSwitchoverType(type);
}
public boolean isSmsExportType() {
return MessageTypes.isSmsExport(type);
}
@@ -575,7 +592,7 @@ public abstract class MessageRecord extends DisplayRecord {
return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() ||
isProfileChange() || isGroupV1MigrationEvent() || isChatSessionRefresh() || isBadDecryptType() ||
isChangeNumber() || isBoostRequest() || isThreadMergeEventType() || isSmsExportType() ||
isChangeNumber() || isBoostRequest() || isThreadMergeEventType() || isSmsExportType() || isSessionSwitchoverEventType() ||
isPaymentsRequestToActivate() || isPaymentsActivated();
}