Use raw values for learned profile name event.

This commit is contained in:
Cody Henthorne
2024-05-24 14:56:53 -04:00
parent d84612ebf4
commit 2737e5613c
9 changed files with 88 additions and 26 deletions
@@ -448,7 +448,7 @@ class SyncMessageProcessorTest_synchronizeDeleteForMe {
// Detected changes
SignalDatabase.messages.insertProfileNameChangeMessages(alice, "new name", "previous name")
SignalDatabase.messages.insertLearnedProfileNameChangeMessage(alice, "previous display name")
SignalDatabase.messages.insertLearnedProfileNameChangeMessage(alice, null, "username.42")
SignalDatabase.messages.insertNumberChangeMessages(alice.id)
SignalDatabase.messages.insertSmsExportMessage(alice.id, SignalDatabase.threads.getThreadIdFor(messageHelper.alice)!!)
SignalDatabase.messages.insertSessionSwitchoverEvent(alice.id, aliceThreadId, SessionSwitchoverEvent())
@@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.backup.v2.proto.ExpirationTimerChatUpdate
import org.thoughtcrime.securesms.backup.v2.proto.FilePointer
import org.thoughtcrime.securesms.backup.v2.proto.GroupCall
import org.thoughtcrime.securesms.backup.v2.proto.IndividualCall
import org.thoughtcrime.securesms.backup.v2.proto.LearnedProfileChatUpdate
import org.thoughtcrime.securesms.backup.v2.proto.MessageAttachment
import org.thoughtcrime.securesms.backup.v2.proto.PaymentNotification
import org.thoughtcrime.securesms.backup.v2.proto.ProfileChangeChatUpdate
@@ -147,21 +148,19 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
builder.expiresInMs = 0
}
MessageTypes.isProfileChange(record.type) -> {
if (record.body == null) continue
builder.updateMessage = ChatUpdateMessage(
profileChange = try {
val decoded: ByteArray = Base64.decode(record.body!!)
val profileChangeDetails = ProfileChangeDetails.ADAPTER.decode(decoded)
if (profileChangeDetails.profileNameChange != null) {
ProfileChangeChatUpdate(previousName = profileChangeDetails.profileNameChange.previous, newName = profileChangeDetails.profileNameChange.newValue)
} else {
ProfileChangeChatUpdate()
}
} catch (e: IOException) {
Log.w(TAG, "Profile name change details could not be read", e)
ProfileChangeChatUpdate()
}
)
val profileChangeDetails = if (record.messageExtras != null) {
record.messageExtras.profileChangeDetails
} else {
Base64.decodeOrNull(record.body)?.let { ProfileChangeDetails.ADAPTER.decode(it) }
}
builder.updateMessage = if (profileChangeDetails?.profileNameChange != null) {
ChatUpdateMessage(profileChange = ProfileChangeChatUpdate(previousName = profileChangeDetails.profileNameChange.previous, newName = profileChangeDetails.profileNameChange.newValue))
} else if (profileChangeDetails?.learnedProfileName != null) {
ChatUpdateMessage(learnedProfileChange = LearnedProfileChatUpdate(e164 = profileChangeDetails.learnedProfileName.e164?.e164ToLong(), username = profileChangeDetails.learnedProfileName.username))
} else {
continue
}
builder.sms = false
}
MessageTypes.isSessionSwitchoverType(record.type) -> {
@@ -475,8 +475,14 @@ class ChatItemImportInserter(
updateMessage.profileChange != null -> {
typeFlags = MessageTypes.PROFILE_CHANGE_TYPE
val profileChangeDetails = ProfileChangeDetails(profileNameChange = ProfileChangeDetails.StringChange(previous = updateMessage.profileChange.previousName, newValue = updateMessage.profileChange.newName))
.encode()
put(MessageTable.BODY, Base64.encodeWithPadding(profileChangeDetails))
val messageExtras = MessageExtras(profileChangeDetails = profileChangeDetails).encode()
put(MessageTable.MESSAGE_EXTRAS, Base64.encodeWithPadding(messageExtras))
}
updateMessage.learnedProfileChange != null -> {
typeFlags = MessageTypes.PROFILE_CHANGE_TYPE
val profileChangeDetails = ProfileChangeDetails(learnedProfileName = ProfileChangeDetails.LearnedProfileName(e164 = updateMessage.learnedProfileChange.e164?.toString(), username = updateMessage.learnedProfileChange.username))
val messageExtras = MessageExtras(profileChangeDetails = profileChangeDetails).encode()
put(MessageTable.MESSAGE_EXTRAS, Base64.encodeWithPadding(messageExtras))
}
updateMessage.sessionSwitchover != null -> {
typeFlags = MessageTypes.SESSION_SWITCHOVER_TYPE or (getAsLong(MessageTable.TYPE) and MessageTypes.BASE_TYPE_MASK.inv())
@@ -1118,12 +1118,17 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
}
}
fun insertLearnedProfileNameChangeMessage(recipient: Recipient, previousDisplayName: String) {
fun insertLearnedProfileNameChangeMessage(recipient: Recipient, e164: String?, username: String?) {
if ((e164 == null && username == null) || (e164 != null && username != null)) {
Log.w(TAG, "Learn profile event expects an e164 or username")
return
}
val threadId: Long? = SignalDatabase.threads.getThreadIdFor(recipient.id)
if (threadId != null) {
val extras = MessageExtras(
profileChangeDetails = ProfileChangeDetails(learnedProfileName = ProfileChangeDetails.StringChange(previous = previousDisplayName))
profileChangeDetails = ProfileChangeDetails(learnedProfileName = ProfileChangeDetails.LearnedProfileName(e164 = e164, username = username))
)
writableDatabase
@@ -32,6 +32,7 @@ import androidx.core.content.ContextCompat;
import com.annimon.stream.Stream;
import org.signal.core.util.Base64;
import org.signal.core.util.StringUtil;
import org.signal.core.util.logging.Log;
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
@@ -57,7 +58,6 @@ import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
import org.thoughtcrime.securesms.profiles.ProfileName;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.signal.core.util.Base64;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.ExpirationUtil;
import org.thoughtcrime.securesms.util.GroupUtil;
@@ -461,8 +461,19 @@ public abstract class MessageRecord extends DisplayRecord {
}
return staticUpdateDescription(updateMessage, R.drawable.ic_update_profile_16);
} else if (profileChangeDetails.deprecatedLearnedProfileName != null) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_started_this_chat, profileChangeDetails.deprecatedLearnedProfileName.previous), R.drawable.symbol_thread_16);
} else if (profileChangeDetails.learnedProfileName != null) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_started_this_chat, profileChangeDetails.learnedProfileName.previous), R.drawable.symbol_thread_16);
String previouslyKnownAs;
if (!Util.isEmpty(profileChangeDetails.learnedProfileName.e164)) {
previouslyKnownAs = PhoneNumberFormatter.prettyPrint(profileChangeDetails.learnedProfileName.e164);
} else {
previouslyKnownAs = profileChangeDetails.learnedProfileName.username;
}
if (!Util.isEmpty(previouslyKnownAs)) {
return staticUpdateDescription(context.getString(R.string.MessageRecord_started_this_chat, previouslyKnownAs), R.drawable.symbol_thread_16);
}
}
}
@@ -376,8 +376,15 @@ class RetrieveProfileJob private constructor(parameters: Parameters, private val
!recipient.isGroup &&
!recipient.isSelf
) {
Log.i(TAG, "Learned profile name for first time, insert event")
SignalDatabase.messages.insertLearnedProfileNameChangeMessage(recipient, recipient.getDisplayName(context))
val username = SignalDatabase.recipients.getUsername(recipient.id)
val e164 = if (username == null) SignalDatabase.recipients.getE164sForIds(listOf(recipient.id)).firstOrNull() else null
if (username != null || e164 != null) {
Log.i(TAG, "Learned profile name for first time, inserting event")
SignalDatabase.messages.insertLearnedProfileNameChangeMessage(recipient, e164, username)
} else {
Log.w(TAG, "Learned profile name for first time, but do not have username or e164 for ${recipient.id}")
}
}
if (remoteProfileName != localProfileName) {
+8
View File
@@ -648,6 +648,7 @@ message ChatUpdateMessage {
SessionSwitchoverChatUpdate sessionSwitchover = 6;
IndividualCall individualCall = 7;
GroupCall groupCall = 8;
LearnedProfileChatUpdate learnedProfileChange = 9;
}
}
@@ -744,6 +745,13 @@ message ProfileChangeChatUpdate {
string newName = 2;
}
message LearnedProfileChatUpdate {
oneof previousName {
uint64 e164 = 1;
string username = 2;
}
}
message ThreadMergeChatUpdate {
uint64 previousE164 = 1;
}
+11 -2
View File
@@ -72,8 +72,17 @@ message ProfileChangeDetails {
string newValue = 2;
}
StringChange profileNameChange = 1;
StringChange learnedProfileName = 2;
message LearnedProfileName {
oneof PreviouslyKnownAs {
string e164 = 1;
string username = 2;
}
}
StringChange profileNameChange = 1;
// Deprecated - Use learnedProfileName instead
StringChange deprecatedLearnedProfileName = 2;
LearnedProfileName learnedProfileName = 3;
}
message BodyRangeList {
@@ -71,6 +71,23 @@ object Base64 {
}
}
/**
* The same as [decode], except that instead of requiring you to handle an exception, this will return null
* if the input is null or cannot be decoded.
*/
@JvmStatic
fun decodeOrNull(value: String?): ByteArray? {
if (value == null) {
return null
}
return try {
decode(value)
} catch (e: IOException) {
null
}
}
/**
* The same as [decode], except that instead of requiring you to handle an exception, this will just crash on invalid base64 strings.
* Should only be used if the value is definitely a valid base64 string.