Strongly type UUIDs as ACIs.

This commit is contained in:
Greyson Parrelli
2021-10-28 15:39:36 -04:00
parent 6c7d837964
commit 5bb48caafd
120 changed files with 1020 additions and 947 deletions

View File

@@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor;
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.push.DistributionId;
import org.thoughtcrime.securesms.groups.GroupAccessControl;
import org.thoughtcrime.securesms.groups.GroupId;
@@ -804,10 +805,10 @@ private static final String[] GROUP_PROJECTION = {
}
private static boolean gv2GroupActive(@NonNull DecryptedGroup decryptedGroup) {
UUID uuid = Recipient.self().getUuid().get();
ACI aci = Recipient.self().requireAci();
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), uuid).isPresent() ||
DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), uuid).isPresent();
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), aci.uuid()).isPresent() ||
DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), aci.uuid()).isPresent();
}
private List<RecipientId> getCurrentMembers(@NonNull GroupId groupId) {
@@ -868,7 +869,7 @@ private static final String[] GROUP_PROJECTION = {
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
Log.w(TAG, "Seen unknown UUID in members list");
} else {
groupMembers.add(RecipientId.from(uuid, null));
groupMembers.add(RecipientId.from(ACI.from(uuid), null));
}
}
@@ -1186,9 +1187,9 @@ private static final String[] GROUP_PROJECTION = {
*/
public boolean isPendingMember(@NonNull Recipient recipient) {
if (isV2Group()) {
Optional<UUID> uuid = recipient.getUuid();
if (uuid.isPresent()) {
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().getDecryptedGroup().getPendingMembersList(), uuid.get())
Optional<ACI> aci = recipient.getAci();
if (aci.isPresent()) {
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().getDecryptedGroup().getPendingMembersList(), aci.get().uuid())
.isPresent();
}
}
@@ -1229,13 +1230,13 @@ private static final String[] GROUP_PROJECTION = {
}
public boolean isAdmin(@NonNull Recipient recipient) {
Optional<UUID> uuid = recipient.getUuid();
Optional<ACI> aci = recipient.getAci();
if (!uuid.isPresent()) {
if (!aci.isPresent()) {
return false;
}
return DecryptedGroupUtil.findMemberByUuid(getDecryptedGroup().getMembersList(), uuid.get())
return DecryptedGroupUtil.findMemberByUuid(getDecryptedGroup().getMembersList(), aci.get().uuid())
.transform(t -> t.getRole() == Member.Role.ADMINISTRATOR)
.or(false);
}
@@ -1245,21 +1246,21 @@ private static final String[] GROUP_PROJECTION = {
}
public MemberLevel memberLevel(@NonNull Recipient recipient) {
Optional<UUID> uuid = recipient.getUuid();
Optional<ACI> aci = recipient.getAci();
if (!uuid.isPresent()) {
if (!aci.isPresent()) {
return MemberLevel.NOT_A_MEMBER;
}
DecryptedGroup decryptedGroup = getDecryptedGroup();
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), uuid.get())
return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), aci.get().uuid())
.transform(member -> member.getRole() == Member.Role.ADMINISTRATOR
? MemberLevel.ADMINISTRATOR
: MemberLevel.FULL_MEMBER)
.or(() -> DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), uuid.get())
.or(() -> DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), aci.get().uuid())
.transform(m -> MemberLevel.PENDING_MEMBER)
.or(() -> DecryptedGroupUtil.findRequestingByUuid(decryptedGroup.getRequestingMembersList(), uuid.get())
.or(() -> DecryptedGroupUtil.findRequestingByUuid(decryptedGroup.getRequestingMembersList(), aci.get().uuid())
.transform(m -> MemberLevel.REQUESTING_MEMBER)
.or(MemberLevel.NOT_A_MEMBER)));
}
@@ -1271,7 +1272,7 @@ private static final String[] GROUP_PROJECTION = {
public List<RecipientId> getMemberRecipientIds(@NonNull MemberSet memberSet) {
boolean includeSelf = memberSet.includeSelf;
DecryptedGroup groupV2 = getDecryptedGroup();
UUID selfUuid = Recipient.self().getUuid().get();
UUID selfUuid = Recipient.self().requireAci().uuid();
List<RecipientId> recipients = new ArrayList<>(groupV2.getMembersCount() + groupV2.getPendingMembersCount());
int unknownMembers = 0;
int unknownPending = 0;
@@ -1280,7 +1281,7 @@ private static final String[] GROUP_PROJECTION = {
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
unknownMembers++;
} else if (includeSelf || !selfUuid.equals(uuid)) {
recipients.add(RecipientId.from(uuid, null));
recipients.add(RecipientId.from(ACI.from(uuid), null));
}
}
if (memberSet.includePending) {
@@ -1288,7 +1289,7 @@ private static final String[] GROUP_PROJECTION = {
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
unknownPending++;
} else if (includeSelf || !selfUuid.equals(uuid)) {
recipients.add(RecipientId.from(uuid, null));
recipients.add(RecipientId.from(ACI.from(uuid), null));
}
}
}

View File

@@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.ArrayList;
@@ -105,7 +106,7 @@ public final class MentionUtil {
BodyRangeList.Builder builder = BodyRangeList.newBuilder();
for (Mention mention : mentions) {
String uuid = Recipient.resolved(mention.getRecipientId()).requireUuid().toString();
String uuid = Recipient.resolved(mention.getRecipientId()).requireAci().toString();
builder.addRanges(BodyRangeList.BodyRange.newBuilder()
.setMentionUuid(uuid)
.setStart(mention.getStart())
@@ -121,7 +122,7 @@ public final class MentionUtil {
return Stream.of(BodyRangeList.parseFrom(data).getRangesList())
.filter(bodyRange -> bodyRange.getAssociatedValueCase() == BodyRangeList.BodyRange.AssociatedValueCase.MENTIONUUID)
.map(mention -> {
RecipientId id = Recipient.externalPush(context, UuidUtil.parseOrThrow(mention.getMentionUuid()), null, false).getId();
RecipientId id = Recipient.externalPush(context, ACI.parseOrThrow(mention.getMentionUuid()), null, false).getId();
return new Mention(id, mention.getStart(), mention.getLength());
})
.toList();

View File

@@ -81,6 +81,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.Pair;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.push.ACI;
import java.io.IOException;
import java.security.SecureRandom;
@@ -1559,7 +1560,7 @@ public class MmsDatabase extends MessageDatabase {
MessageGroupContext.GroupV2Properties groupV2Properties = outgoingGroupUpdateMessage.requireGroupV2Properties();
members.addAll(Stream.of(groupV2Properties.getAllActivePendingAndRemovedMembers())
.distinct()
.map(uuid -> RecipientId.from(uuid, null))
.map(uuid -> RecipientId.from(ACI.from(uuid), null))
.toList());
members.remove(Recipient.self().getId());
} else {

View File

@@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.whispersystems.signalservice.api.push.ACI;
import org.thoughtcrime.securesms.database.model.IdentityRecord;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.database.model.databaseprotos.BadgeList;
@@ -80,7 +81,6 @@ import org.whispersystems.signalservice.api.storage.SignalContactRecord;
import org.whispersystems.signalservice.api.storage.SignalGroupV1Record;
import org.whispersystems.signalservice.api.storage.SignalGroupV2Record;
import org.whispersystems.signalservice.api.storage.StorageId;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.io.Closeable;
import java.io.IOException;
@@ -107,7 +107,7 @@ public class RecipientDatabase extends Database {
static final String TABLE_NAME = "recipient";
public static final String ID = "_id";
private static final String UUID = "uuid";
private static final String ACI_COLUMN = "uuid";
private static final String USERNAME = "username";
public static final String PHONE = "phone";
public static final String EMAIL = "email";
@@ -178,7 +178,7 @@ public class RecipientDatabase extends Database {
}
private static final String[] RECIPIENT_PROJECTION = new String[] {
ID, UUID, USERNAME, PHONE, EMAIL, GROUP_ID, GROUP_TYPE,
ID, ACI_COLUMN, USERNAME, PHONE, EMAIL, GROUP_ID, GROUP_TYPE,
BLOCKED, MESSAGE_RINGTONE, CALL_RINGTONE, MESSAGE_VIBRATE, CALL_VIBRATE, MUTE_UNTIL, AVATAR_COLOR, SEEN_INVITE_REMINDER, DEFAULT_SUBSCRIPTION_ID, MESSAGE_EXPIRATION_TIME, REGISTERED,
PROFILE_KEY, PROFILE_KEY_CREDENTIAL,
SYSTEM_JOINED_NAME, SYSTEM_GIVEN_NAME, SYSTEM_FAMILY_NAME, SYSTEM_PHOTO_URI, SYSTEM_PHONE_LABEL, SYSTEM_PHONE_TYPE, SYSTEM_CONTACT_URI,
@@ -329,7 +329,7 @@ public class RecipientDatabase extends Database {
public static final String CREATE_TABLE =
"CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
UUID + " TEXT UNIQUE DEFAULT NULL, " +
ACI_COLUMN + " TEXT UNIQUE DEFAULT NULL, " +
USERNAME + " TEXT UNIQUE DEFAULT NULL, " +
PHONE + " TEXT UNIQUE DEFAULT NULL, " +
EMAIL + " TEXT UNIQUE DEFAULT NULL, " +
@@ -398,7 +398,7 @@ public class RecipientDatabase extends Database {
public @NonNull boolean containsPhoneOrUuid(@NonNull String id) {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
String query = UUID + " = ? OR " + PHONE + " = ?";
String query = ACI_COLUMN + " = ? OR " + PHONE + " = ?";
String[] args = new String[]{id, id};
try (Cursor cursor = db.query(TABLE_NAME, new String[] { ID }, query, args, null, null, null)) {
@@ -421,8 +421,8 @@ public class RecipientDatabase extends Database {
}
public @NonNull
Optional<RecipientId> getByUuid(@NonNull UUID uuid) {
return getByColumn(UUID, uuid.toString());
Optional<RecipientId> getByAci(@NonNull ACI uuid) {
return getByColumn(ACI_COLUMN, uuid.toString());
}
public @NonNull
@@ -430,12 +430,12 @@ public class RecipientDatabase extends Database {
return getByColumn(USERNAME, username);
}
public @NonNull RecipientId getAndPossiblyMerge(@Nullable UUID uuid, @Nullable String e164, boolean highTrust) {
return getAndPossiblyMerge(uuid, e164, highTrust, false);
public @NonNull RecipientId getAndPossiblyMerge(@Nullable ACI aci, @Nullable String e164, boolean highTrust) {
return getAndPossiblyMerge(aci, e164, highTrust, false);
}
public @NonNull RecipientId getAndPossiblyMerge(@Nullable UUID uuid, @Nullable String e164, boolean highTrust, boolean changeSelf) {
if (uuid == null && e164 == null) {
public @NonNull RecipientId getAndPossiblyMerge(@Nullable ACI aci, @Nullable String e164, boolean highTrust, boolean changeSelf) {
if (aci == null && e164 == null) {
throw new IllegalArgumentException("Must provide a UUID or E164!");
}
@@ -449,115 +449,115 @@ public class RecipientDatabase extends Database {
try {
Optional<RecipientId> byE164 = e164 != null ? getByE164(e164) : Optional.absent();
Optional<RecipientId> byUuid = uuid != null ? getByUuid(uuid) : Optional.absent();
Optional<RecipientId> byAci = aci != null ? getByAci(aci) : Optional.absent();
RecipientId finalId;
if (!byE164.isPresent() && !byUuid.isPresent()) {
if (!byE164.isPresent() && !byAci.isPresent()) {
Log.i(TAG, "Discovered a completely new user. Inserting.", true);
if (highTrust) {
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(e164, uuid));
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(e164, aci));
finalId = RecipientId.from(id);
} else {
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(uuid == null ? e164 : null, uuid));
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(aci == null ? e164 : null, aci));
finalId = RecipientId.from(id);
}
} else if (byE164.isPresent() && !byUuid.isPresent()) {
if (uuid != null) {
} else if (byE164.isPresent() && !byAci.isPresent()) {
if (aci != null) {
RecipientSettings e164Settings = getRecipientSettings(byE164.get());
if (e164Settings.uuid != null) {
if (e164Settings.aci != null) {
if (highTrust) {
Log.w(TAG, String.format(Locale.US, "Found out about a UUID (%s) for a known E164 user (%s), but that user already has a UUID (%s). Likely a case of re-registration. High-trust, so stripping the E164 from the existing account and assigning it to a new entry.", uuid, byE164.get(), e164Settings.uuid), true);
Log.w(TAG, String.format(Locale.US, "Found out about an ACI (%s) for a known E164 user (%s), but that user already has an ACI (%s). Likely a case of re-registration. High-trust, so stripping the E164 from the existing account and assigning it to a new entry.", aci, byE164.get(), e164Settings.aci), true);
removePhoneNumber(byE164.get(), db);
recipientNeedingRefresh = byE164.get();
ContentValues insertValues = buildContentValuesForNewUser(e164, uuid);
ContentValues insertValues = buildContentValuesForNewUser(e164, aci);
insertValues.put(BLOCKED, e164Settings.blocked ? 1 : 0);
long id = db.insert(TABLE_NAME, null, insertValues);
finalId = RecipientId.from(id);
} else {
Log.w(TAG, String.format(Locale.US, "Found out about a UUID (%s) for a known E164 user (%s), but that user already has a UUID (%s). Likely a case of re-registration. Low-trust, so making a new user for the UUID.", uuid, byE164.get(), e164Settings.uuid), true);
Log.w(TAG, String.format(Locale.US, "Found out about an ACI (%s) for a known E164 user (%s), but that user already has an ACI (%s). Likely a case of re-registration. Low-trust, so making a new user for the UUID.", aci, byE164.get(), e164Settings.aci), true);
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(null, uuid));
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(null, aci));
finalId = RecipientId.from(id);
}
} else {
if (highTrust) {
Log.i(TAG, String.format(Locale.US, "Found out about a UUID (%s) for a known E164 user (%s). High-trust, so updating.", uuid, byE164.get()), true);
markRegisteredOrThrow(byE164.get(), uuid);
Log.i(TAG, String.format(Locale.US, "Found out about an ACI (%s) for a known E164 user (%s). High-trust, so updating.", aci, byE164.get()), true);
markRegisteredOrThrow(byE164.get(), aci);
finalId = byE164.get();
} else {
Log.i(TAG, String.format(Locale.US, "Found out about a UUID (%s) for a known E164 user (%s). Low-trust, so making a new user for the UUID.", uuid, byE164.get()), true);
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(null, uuid));
Log.i(TAG, String.format(Locale.US, "Found out about an ACI (%s) for a known E164 user (%s). Low-trust, so making a new user for the ACI.", aci, byE164.get()), true);
long id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(null, aci));
finalId = RecipientId.from(id);
}
}
} else {
finalId = byE164.get();
}
} else if (!byE164.isPresent() && byUuid.isPresent()) {
} else if (!byE164.isPresent() && byAci.isPresent()) {
if (e164 != null) {
if (highTrust) {
if (Objects.equals(uuid, TextSecurePreferences.getLocalUuid(context)) && !changeSelf) {
Log.w(TAG, String.format(Locale.US, "Found out about an E164 (%s) for our own UUID user (%s). High-trust but not change self, doing nothing.", e164, byUuid.get()), true);
finalId = byUuid.get();
if (Objects.equals(aci, TextSecurePreferences.getLocalAci(context)) && !changeSelf) {
Log.w(TAG, String.format(Locale.US, "Found out about an E164 (%s) for our own ACI user (%s). High-trust but not change self, doing nothing.", e164, byAci.get()), true);
finalId = byAci.get();
} else {
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known UUID user (%s). High-trust, so updating.", e164, byUuid.get()), true);
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known ACI user (%s). High-trust, so updating.", e164, byAci.get()), true);
RecipientSettings byUuidSettings = getRecipientSettings(byUuid.get());
RecipientSettings byUuidSettings = getRecipientSettings(byAci.get());
setPhoneNumberOrThrow(byUuid.get(), e164);
finalId = byUuid.get();
setPhoneNumberOrThrow(byAci.get(), e164);
finalId = byAci.get();
if (!Util.isEmpty(byUuidSettings.e164) && !byUuidSettings.e164.equals(e164)) {
recipientChangedNumber = finalId;
}
}
} else {
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known UUID user (%s). Low-trust, so doing nothing.", e164, byUuid.get()), true);
finalId = byUuid.get();
Log.i(TAG, String.format(Locale.US, "Found out about an E164 (%s) for a known ACI user (%s). Low-trust, so doing nothing.", e164, byAci.get()), true);
finalId = byAci.get();
}
} else {
finalId = byUuid.get();
finalId = byAci.get();
}
} else {
if (byE164.equals(byUuid)) {
finalId = byUuid.get();
if (byE164.equals(byAci)) {
finalId = byAci.get();
} else {
Log.w(TAG, String.format(Locale.US, "Hit a conflict between %s (E164 of %s) and %s (UUID %s). They map to different recipients.", byE164.get(), e164, byUuid.get(), uuid), new Throwable(), true);
Log.w(TAG, String.format(Locale.US, "Hit a conflict between %s (E164 of %s) and %s (ACI %s). They map to different recipients.", byE164.get(), e164, byAci.get(), aci), new Throwable(), true);
RecipientSettings e164Settings = getRecipientSettings(byE164.get());
if (e164Settings.getUuid() != null) {
if (e164Settings.getAci() != null) {
if (highTrust) {
Log.w(TAG, "The E164 contact has a different UUID. Likely a case of re-registration. High-trust, so stripping the E164 from the existing account and assigning it to the UUID entry.", true);
Log.w(TAG, "The E164 contact has a different ACI. Likely a case of re-registration. High-trust, so stripping the E164 from the existing account and assigning it to the ACI entry.", true);
removePhoneNumber(byE164.get(), db);
recipientNeedingRefresh = byE164.get();
RecipientSettings byUuidSettings = getRecipientSettings(byUuid.get());
RecipientSettings byUuidSettings = getRecipientSettings(byAci.get());
setPhoneNumberOrThrow(byUuid.get(), Objects.requireNonNull(e164));
finalId = byUuid.get();
setPhoneNumberOrThrow(byAci.get(), Objects.requireNonNull(e164));
finalId = byAci.get();
if (!Util.isEmpty(byUuidSettings.e164) && !byUuidSettings.e164.equals(e164)) {
recipientChangedNumber = finalId;
}
} else {
Log.w(TAG, "The E164 contact has a different UUID. Likely a case of re-registration. Low-trust, so doing nothing.", true);
finalId = byUuid.get();
Log.w(TAG, "The E164 contact has a different ACI. Likely a case of re-registration. Low-trust, so doing nothing.", true);
finalId = byAci.get();
}
} else {
if (highTrust) {
Log.w(TAG, "We have one contact with just an E164, and another with UUID. High-trust, so merging the two rows together.", true);
finalId = merge(byUuid.get(), byE164.get());
recipientNeedingRefresh = byUuid.get();
remapped = new Pair<>(byE164.get(), byUuid.get());
Log.w(TAG, "We have one contact with just an E164, and another with just an ACI. High-trust, so merging the two rows together.", true);
finalId = merge(byAci.get(), byE164.get());
recipientNeedingRefresh = byAci.get();
remapped = new Pair<>(byE164.get(), byAci.get());
} else {
Log.w(TAG, "We have one contact with just an E164, and another with UUID. Low-trust, so doing nothing.", true);
finalId = byUuid.get();
Log.w(TAG, "We have one contact with just an E164, and another with just an ACI. Low-trust, so doing nothing.", true);
finalId = byAci.get();
}
}
}
@@ -592,13 +592,13 @@ public class RecipientDatabase extends Database {
}
}
private static ContentValues buildContentValuesForNewUser(@Nullable String e164, @Nullable UUID uuid) {
private static ContentValues buildContentValuesForNewUser(@Nullable String e164, @Nullable ACI aci) {
ContentValues values = new ContentValues();
values.put(PHONE, e164);
if (uuid != null) {
values.put(UUID, uuid.toString().toLowerCase());
if (aci != null) {
values.put(ACI_COLUMN, aci.toString().toLowerCase());
values.put(REGISTERED, RegisteredState.REGISTERED.getId());
values.put(STORAGE_SERVICE_ID, Base64.encodeBytes(StorageSyncHelper.generateKey()));
values.put(AVATAR_COLOR, AvatarColor.random().serialize());
@@ -608,8 +608,8 @@ public class RecipientDatabase extends Database {
}
public @NonNull RecipientId getOrInsertFromUuid(@NonNull UUID uuid) {
return getOrInsertByColumn(UUID, uuid.toString()).recipientId;
public @NonNull RecipientId getOrInsertFromAci(@NonNull ACI aci) {
return getOrInsertByColumn(ACI_COLUMN, aci.toString()).recipientId;
}
public @NonNull RecipientId getOrInsertFromE164(@NonNull String e164) {
@@ -829,13 +829,13 @@ public class RecipientDatabase extends Database {
if (id < 0) {
Log.w(TAG, "[applyStorageSyncContactInsert] Failed to insert. Possibly merging.");
recipientId = getAndPossiblyMerge(insert.getAddress().hasValidUuid() ? insert.getAddress().getUuid() : null, insert.getAddress().getNumber().get(), true);
recipientId = getAndPossiblyMerge(insert.getAddress().hasValidAci() ? insert.getAddress().getAci() : null, insert.getAddress().getNumber().get(), true);
db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId));
} else {
recipientId = RecipientId.from(id);
}
if (insert.getIdentityKey().isPresent() && insert.getAddress().hasValidUuid()) {
if (insert.getIdentityKey().isPresent() && insert.getAddress().hasValidAci()) {
try {
IdentityKey identityKey = new IdentityKey(insert.getIdentityKey().get(), 0);
@@ -864,7 +864,7 @@ public class RecipientDatabase extends Database {
RecipientId recipientId = getByColumn(STORAGE_SERVICE_ID, Base64.encodeBytes(update.getOld().getId().getRaw())).get();
Log.w(TAG, "[applyStorageSyncContactUpdate] Found user " + recipientId + ". Possibly merging.");
recipientId = getAndPossiblyMerge(update.getNew().getAddress().hasValidUuid() ? update.getNew().getAddress().getUuid() : null, update.getNew().getAddress().getNumber().orNull(), true);
recipientId = getAndPossiblyMerge(update.getNew().getAddress().hasValidAci() ? update.getNew().getAddress().getAci() : null, update.getNew().getAddress().getNumber().orNull(), true);
Log.w(TAG, "[applyStorageSyncContactUpdate] Merged into " + recipientId);
db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId));
@@ -881,7 +881,7 @@ public class RecipientDatabase extends Database {
try {
Optional<IdentityRecord> oldIdentityRecord = identityStore.getIdentityRecord(recipientId);
if (update.getNew().getIdentityKey().isPresent() && update.getNew().getAddress().hasValidUuid()) {
if (update.getNew().getIdentityKey().isPresent() && update.getNew().getAddress().hasValidAci()) {
IdentityKey identityKey = new IdentityKey(update.getNew().getIdentityKey().get(), 0);
DatabaseFactory.getIdentityDatabase(context).updateIdentityAfterSync(update.getNew().getAddress().getIdentifier(), recipientId, identityKey, StorageSyncModels.remoteToLocalIdentityStatus(update.getNew().getIdentityState()));
}
@@ -1059,8 +1059,8 @@ public class RecipientDatabase extends Database {
ProfileName profileName = ProfileName.fromParts(contact.getGivenName().orNull(), contact.getFamilyName().orNull());
String username = contact.getUsername().orNull();
if (contact.getAddress().hasValidUuid()) {
values.put(UUID, contact.getAddress().getUuid().toString());
if (contact.getAddress().hasValidAci()) {
values.put(ACI_COLUMN, contact.getAddress().getAci().toString());
}
values.put(PHONE, contact.getAddress().getNumber().orNull());
@@ -1133,9 +1133,9 @@ public class RecipientDatabase extends Database {
private List<RecipientSettings> getRecipientSettingsForSync(@Nullable String query, @Nullable String[] args) {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
String table = TABLE_NAME + " LEFT OUTER JOIN " + IdentityDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + UUID + " = " + IdentityDatabase.TABLE_NAME + "." + IdentityDatabase.ADDRESS
+ " LEFT OUTER JOIN " + GroupDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + GROUP_ID + " = " + GroupDatabase.TABLE_NAME + "." + GroupDatabase.GROUP_ID
+ " LEFT OUTER JOIN " + ThreadDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + ID + " = " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID;
String table = TABLE_NAME + " LEFT OUTER JOIN " + IdentityDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + ACI_COLUMN + " = " + IdentityDatabase.TABLE_NAME + "." + IdentityDatabase.ADDRESS
+ " LEFT OUTER JOIN " + GroupDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + GROUP_ID + " = " + GroupDatabase.TABLE_NAME + "." + GroupDatabase.GROUP_ID
+ " LEFT OUTER JOIN " + ThreadDatabase.TABLE_NAME + " ON " + TABLE_NAME + "." + ID + " = " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID;
List<RecipientSettings> out = new ArrayList<>();
String[] columns = Stream.of(TYPED_RECIPIENT_PROJECTION,
@@ -1169,7 +1169,7 @@ public class RecipientDatabase extends Database {
*/
public @NonNull Map<RecipientId, StorageId> getContactStorageSyncIdsMap() {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
String query = STORAGE_SERVICE_ID + " NOT NULL AND " + UUID + " NOT NULL AND " + ID + " != ? AND " + GROUP_TYPE + " != ?";
String query = STORAGE_SERVICE_ID + " NOT NULL AND " + ACI_COLUMN + " NOT NULL AND " + ID + " != ? AND " + GROUP_TYPE + " != ?";
String[] args = SqlUtil.buildArgs(Recipient.self().getId(), String.valueOf(GroupType.SIGNAL_V2.getId()));
Map<RecipientId, StorageId> out = new HashMap<>();
@@ -1215,7 +1215,7 @@ public class RecipientDatabase extends Database {
static @NonNull RecipientSettings getRecipientSettings(@NonNull Context context, @NonNull Cursor cursor, @NonNull String idColumnName) {
long id = CursorUtil.requireLong(cursor, idColumnName);
UUID uuid = UuidUtil.parseOrNull(CursorUtil.requireString(cursor, UUID));
ACI uuid = ACI.parseOrNull(CursorUtil.requireString(cursor, ACI_COLUMN));
String username = CursorUtil.requireString(cursor, USERNAME);
String e164 = CursorUtil.requireString(cursor, PHONE);
String email = CursorUtil.requireString(cursor, EMAIL);
@@ -1840,9 +1840,9 @@ public class RecipientDatabase extends Database {
* database if missing.
*/
public Set<RecipientId> persistProfileKeySet(@NonNull ProfileKeySet profileKeySet) {
Map<UUID, ProfileKey> profileKeys = profileKeySet.getProfileKeys();
Map<UUID, ProfileKey> authoritativeProfileKeys = profileKeySet.getAuthoritativeProfileKeys();
int totalKeys = profileKeys.size() + authoritativeProfileKeys.size();
Map<ACI, ProfileKey> profileKeys = profileKeySet.getProfileKeys();
Map<ACI, ProfileKey> authoritativeProfileKeys = profileKeySet.getAuthoritativeProfileKeys();
int totalKeys = profileKeys.size() + authoritativeProfileKeys.size();
if (totalKeys == 0) {
return Collections.emptySet();
@@ -1853,8 +1853,8 @@ public class RecipientDatabase extends Database {
HashSet<RecipientId> updated = new HashSet<>(totalKeys);
RecipientId selfId = Recipient.self().getId();
for (Map.Entry<UUID, ProfileKey> entry : profileKeys.entrySet()) {
RecipientId recipientId = getOrInsertFromUuid(entry.getKey());
for (Map.Entry<ACI, ProfileKey> entry : profileKeys.entrySet()) {
RecipientId recipientId = getOrInsertFromAci(entry.getKey());
if (setProfileKeyIfAbsent(recipientId, entry.getValue())) {
Log.i(TAG, "Learned new profile key");
@@ -1862,8 +1862,8 @@ public class RecipientDatabase extends Database {
}
}
for (Map.Entry<UUID, ProfileKey> entry : authoritativeProfileKeys.entrySet()) {
RecipientId recipientId = getOrInsertFromUuid(entry.getKey());
for (Map.Entry<ACI, ProfileKey> entry : authoritativeProfileKeys.entrySet()) {
RecipientId recipientId = getOrInsertFromAci(entry.getKey());
if (selfId.equals(recipientId)) {
Log.i(TAG, "Seen authoritative update for self");
@@ -2111,7 +2111,7 @@ public class RecipientDatabase extends Database {
Log.w(TAG, "[setPhoneNumber] Hit a conflict when trying to update " + id + ". Possibly merging.");
RecipientSettings existing = getRecipientSettings(id);
RecipientId newId = getAndPossiblyMerge(existing.getUuid(), e164, true);
RecipientId newId = getAndPossiblyMerge(existing.getAci(), e164, true);
Log.w(TAG, "[setPhoneNumber] Resulting id: " + newId);
db.setTransactionSuccessful();
@@ -2147,7 +2147,7 @@ public class RecipientDatabase extends Database {
try {
RecipientId id = Recipient.self().getId();
RecipientId newId = getAndPossiblyMerge(Recipient.self().requireUuid(), e164, true, true);
RecipientId newId = getAndPossiblyMerge(Recipient.self().requireAci(), e164, true, true);
if (id.equals(newId)) {
Log.i(TAG, "[updateSelfPhone] Phone updated for self");
@@ -2206,19 +2206,19 @@ public class RecipientDatabase extends Database {
/**
* @return True if setting the UUID resulted in changed recipientId, otherwise false.
*/
public boolean markRegistered(@NonNull RecipientId id, @NonNull UUID uuid) {
public boolean markRegistered(@NonNull RecipientId id, @NonNull ACI aci) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
db.beginTransaction();
try {
markRegisteredOrThrow(id, uuid);
markRegisteredOrThrow(id, aci);
db.setTransactionSuccessful();
return false;
} catch (SQLiteConstraintException e) {
Log.w(TAG, "[markRegistered] Hit a conflict when trying to update " + id + ". Possibly merging.");
RecipientSettings existing = getRecipientSettings(id);
RecipientId newId = getAndPossiblyMerge(uuid, existing.getE164(), true);
RecipientId newId = getAndPossiblyMerge(aci, existing.getE164(), true);
Log.w(TAG, "[markRegistered] Merged into " + newId);
db.setTransactionSuccessful();
@@ -2231,10 +2231,10 @@ public class RecipientDatabase extends Database {
/**
* Should only use if you are confident that this shouldn't result in any contact merging.
*/
public void markRegisteredOrThrow(@NonNull RecipientId id, @NonNull UUID uuid) {
public void markRegisteredOrThrow(@NonNull RecipientId id, @NonNull ACI aci) {
ContentValues contentValues = new ContentValues(2);
contentValues.put(REGISTERED, RegisteredState.REGISTERED.getId());
contentValues.put(UUID, uuid.toString().toLowerCase());
contentValues.put(ACI_COLUMN, aci.toString().toLowerCase());
if (update(id, contentValues)) {
setStorageIdIfNotSet(id);
@@ -2252,28 +2252,31 @@ public class RecipientDatabase extends Database {
}
}
public void bulkUpdatedRegisteredStatus(@NonNull Map<RecipientId, String> registered, Collection<RecipientId> unregistered) {
public void bulkUpdatedRegisteredStatus(@NonNull Map<RecipientId, ACI> registered, Collection<RecipientId> unregistered) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
db.beginTransaction();
try {
for (Map.Entry<RecipientId, String> entry : registered.entrySet()) {
for (Map.Entry<RecipientId, ACI> entry : registered.entrySet()) {
RecipientId recipientId = entry.getKey();
ACI aci = entry.getValue();
ContentValues values = new ContentValues(2);
values.put(REGISTERED, RegisteredState.REGISTERED.getId());
if (entry.getValue() != null) {
values.put(UUID, entry.getValue().toLowerCase());
if (aci != null) {
values.put(ACI_COLUMN, aci.toString().toLowerCase());
}
try {
if (update(entry.getKey(), values)) {
setStorageIdIfNotSet(entry.getKey());
if (update(recipientId, values)) {
setStorageIdIfNotSet(recipientId);
}
} catch (SQLiteConstraintException e) {
Log.w(TAG, "[bulkUpdateRegisteredStatus] Hit a conflict when trying to update " + entry.getKey() + ". Possibly merging.");
Log.w(TAG, "[bulkUpdateRegisteredStatus] Hit a conflict when trying to update " + recipientId + ". Possibly merging.");
RecipientSettings existing = getRecipientSettings(entry.getKey());
RecipientId newId = getAndPossiblyMerge(UuidUtil.parseOrThrow(entry.getValue()), existing.getE164(), true);
RecipientId newId = getAndPossiblyMerge(aci, existing.getE164(), true);
Log.w(TAG, "[bulkUpdateRegisteredStatus] Merged into " + newId);
}
}
@@ -2298,27 +2301,27 @@ public class RecipientDatabase extends Database {
*
* @return A mapping of (RecipientId, UUID)
*/
public @NonNull Map<RecipientId, String> bulkProcessCdsResult(@NonNull Map<String, UUID> mapping) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
HashMap<RecipientId, String> uuidMap = new HashMap<>();
public @NonNull Map<RecipientId, ACI> bulkProcessCdsResult(@NonNull Map<String, ACI> mapping) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
HashMap<RecipientId, ACI> aciMap = new HashMap<>();
db.beginTransaction();
try {
for (Map.Entry<String, UUID> entry : mapping.entrySet()) {
for (Map.Entry<String, ACI> entry : mapping.entrySet()) {
String e164 = entry.getKey();
UUID uuid = entry.getValue();
Optional<RecipientId> uuidEntry = uuid != null ? getByUuid(uuid) : Optional.absent();
ACI aci = entry.getValue();
Optional<RecipientId> aciEntry = aci != null ? getByAci(aci) : Optional.absent();
if (uuidEntry.isPresent()) {
boolean idChanged = setPhoneNumber(uuidEntry.get(), e164);
if (aciEntry.isPresent()) {
boolean idChanged = setPhoneNumber(aciEntry.get(), e164);
if (idChanged) {
uuidEntry = getByUuid(Objects.requireNonNull(uuid));
aciEntry = getByAci(Objects.requireNonNull(aci));
}
}
RecipientId id = uuidEntry.isPresent() ? uuidEntry.get() : getOrInsertFromE164(e164);
RecipientId id = aciEntry.isPresent() ? aciEntry.get() : getOrInsertFromE164(e164);
uuidMap.put(id, uuid != null ? uuid.toString() : null);
aciMap.put(id, aci);
}
db.setTransactionSuccessful();
@@ -2326,7 +2329,7 @@ public class RecipientDatabase extends Database {
db.endTransaction();
}
return uuidMap;
return aciMap;
}
public @NonNull List<RecipientId> getUninvitedRecipientsForInsights() {
@@ -2730,7 +2733,7 @@ public class RecipientDatabase extends Database {
.map(b -> b.getNumber().get())
.toList();
List<String> blockedUuid = Stream.of(blocked)
.map(b -> b.getUuid().toString().toLowerCase())
.map(b -> b.getAci().toString().toLowerCase())
.toList();
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
@@ -2750,7 +2753,7 @@ public class RecipientDatabase extends Database {
}
for (String uuid : blockedUuid) {
db.update(TABLE_NAME, setBlocked, UUID + " = ?", new String[] { uuid });
db.update(TABLE_NAME, setBlocked, ACI_COLUMN + " = ?", new String[] { uuid });
}
List<GroupId.V1> groupIdStrings = new ArrayList<>(groupIds.size());
@@ -3106,7 +3109,7 @@ public class RecipientDatabase extends Database {
SessionDatabase sessionDatabase = DatabaseFactory.getSessionDatabase(context);
boolean hasE164Session = sessionDatabase.getAllFor(e164Settings.e164).size() > 0;
boolean hasUuidSession = sessionDatabase.getAllFor(uuidSettings.uuid.toString()).size() > 0;
boolean hasUuidSession = sessionDatabase.getAllFor(uuidSettings.aci.toString()).size() > 0;
if (hasE164Session && hasUuidSession) {
Log.w(TAG, "Had a session for both users. Deleting the E164.", true);
@@ -3114,7 +3117,7 @@ public class RecipientDatabase extends Database {
} else if (hasE164Session && !hasUuidSession) {
Log.w(TAG, "Had a session for E164, but not UUID. Re-assigning to the UUID.", true);
ContentValues values = new ContentValues();
values.put(SessionDatabase.ADDRESS, uuidSettings.uuid.toString());
values.put(SessionDatabase.ADDRESS, uuidSettings.aci.toString());
db.update(SessionDatabase.TABLE_NAME, values, SessionDatabase.ADDRESS + " = ?", SqlUtil.buildArgs(e164Settings.e164));
} else if (!hasE164Session && hasUuidSession) {
Log.w(TAG, "Had a session for UUID, but not E164. No action necessary.", true);
@@ -3260,7 +3263,7 @@ public class RecipientDatabase extends Database {
public static class RecipientSettings {
private final RecipientId id;
private final UUID uuid;
private final ACI aci;
private final String username;
private final String e164;
private final String email;
@@ -3310,7 +3313,7 @@ public class RecipientDatabase extends Database {
private final List<Badge> badges;
RecipientSettings(@NonNull RecipientId id,
@Nullable UUID uuid,
@Nullable ACI uuid,
@Nullable String username,
@Nullable String e164,
@Nullable String email,
@@ -3355,7 +3358,7 @@ public class RecipientDatabase extends Database {
@NonNull List<Badge> badges)
{
this.id = id;
this.uuid = uuid;
this.aci = uuid;
this.username = username;
this.e164 = e164;
this.email = email;
@@ -3409,8 +3412,8 @@ public class RecipientDatabase extends Database {
return id;
}
public @Nullable UUID getUuid() {
return uuid;
public @Nullable ACI getAci() {
return aci;
}
public @Nullable String getUsername() {

View File

@@ -143,8 +143,8 @@ public class SenderKeySharedDatabase extends Database {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
Recipient recipient = Recipient.resolved(recipientId);
if (recipient.hasUuid()) {
db.delete(TABLE_NAME, ADDRESS + " = ?", SqlUtil.buildArgs(recipient.getUuid().get().toString()));
if (recipient.hasAci()) {
db.delete(TABLE_NAME, ADDRESS + " = ?", SqlUtil.buildArgs(recipient.requireAci().toString()));
} else {
Log.w(TAG, "Recipient doesn't have a UUID! " + recipientId);
}

View File

@@ -723,11 +723,11 @@ public class SmsDatabase extends MessageDatabase {
if (!peerEraIdSameAsPrevious && !Util.isEmpty(peekGroupCallEraId)) {
Recipient self = Recipient.self();
boolean markRead = peekJoinedUuids.contains(self.requireUuid()) || self.getId().equals(sender);
boolean markRead = peekJoinedUuids.contains(self.requireAci().uuid()) || self.getId().equals(sender);
byte[] updateDetails = GroupCallUpdateDetails.newBuilder()
.setEraId(Util.emptyIfNull(peekGroupCallEraId))
.setStartedCallUuid(Recipient.resolved(sender).requireUuid().toString())
.setStartedCallUuid(Recipient.resolved(sender).requireAci().toString())
.setStartedCallTimestamp(timestamp)
.addAllInCallUuids(Stream.of(peekJoinedUuids).map(UUID::toString).toList())
.setIsCallFull(isCallFull)
@@ -804,7 +804,7 @@ public class SmsDatabase extends MessageDatabase {
if (!sameEraId && !Util.isEmpty(messageGroupCallEraId)) {
byte[] updateDetails = GroupCallUpdateDetails.newBuilder()
.setEraId(Util.emptyIfNull(messageGroupCallEraId))
.setStartedCallUuid(Recipient.resolved(sender).requireUuid().toString())
.setStartedCallUuid(Recipient.resolved(sender).requireAci().toString())
.setStartedCallTimestamp(timestamp)
.addAllInCallUuids(Collections.emptyList())
.setIsCallFull(false)
@@ -853,7 +853,7 @@ public class SmsDatabase extends MessageDatabase {
}
GroupCallUpdateDetails groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(record.getBody());
boolean containsSelf = peekJoinedUuids.contains(Recipient.self().requireUuid());
boolean containsSelf = peekJoinedUuids.contains(Recipient.self().requireAci().uuid());
sameEraId = groupCallUpdateDetails.getEraId().equals(peekGroupCallEraId) && !Util.isEmpty(peekGroupCallEraId);

View File

@@ -58,6 +58,7 @@ import org.thoughtcrime.securesms.util.SqlUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
import org.whispersystems.signalservice.api.storage.SignalGroupV1Record;
@@ -1446,7 +1447,7 @@ public class ThreadDatabase extends Database {
if (threadRecipient.isPushV2Group()) {
MessageRecord.InviteAddState inviteAddState = record.getGv2AddInviteState();
if (inviteAddState != null) {
RecipientId from = RecipientId.from(inviteAddState.getAddedOrInvitedBy(), null);
RecipientId from = RecipientId.from(ACI.from(inviteAddState.getAddedOrInvitedBy()), null);
if (inviteAddState.isInvited()) {
Log.i(TAG, "GV2 invite message request from " + from);
return Extra.forGroupV2invite(from, individualRecipientId);

View File

@@ -10,26 +10,25 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.api.push.ACI;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.UUID;
/**
* Create a group call update message based on time and joined members.
*/
public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFactory {
private final Context context;
private final List<UUID> joinedMembers;
private final List<ACI> joinedMembers;
private final boolean withTime;
private final GroupCallUpdateDetails groupCallUpdateDetails;
private final UUID selfUuid;
private final ACI selfAci;
public GroupCallUpdateMessageFactory(@NonNull Context context,
@NonNull List<UUID> joinedMembers,
@NonNull List<ACI> joinedMembers,
boolean withTime,
@NonNull GroupCallUpdateDetails groupCallUpdateDetails)
{
@@ -37,11 +36,11 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFa
this.joinedMembers = new ArrayList<>(joinedMembers);
this.withTime = withTime;
this.groupCallUpdateDetails = groupCallUpdateDetails;
this.selfUuid = TextSecurePreferences.getLocalUuid(context);
this.selfAci = TextSecurePreferences.getLocalAci(context);
boolean removed = this.joinedMembers.remove(selfUuid);
boolean removed = this.joinedMembers.remove(selfAci);
if (removed) {
this.joinedMembers.add(selfUuid);
this.joinedMembers.add(selfAci);
}
}
@@ -57,7 +56,7 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFa
if (joinedMembers.get(0).toString().equals(groupCallUpdateDetails.getStartedCallUuid())) {
return withTime ? context.getString(R.string.MessageRecord_s_started_a_group_call_s, describe(joinedMembers.get(0)), time)
: context.getString(R.string.MessageRecord_s_started_a_group_call, describe(joinedMembers.get(0)));
} else if (Objects.equals(joinedMembers.get(0), selfUuid)) {
} else if (Objects.equals(joinedMembers.get(0), selfAci)) {
return withTime ? context.getString(R.string.MessageRecord_you_are_in_the_group_call_s1, time)
: context.getString(R.string.MessageRecord_you_are_in_the_group_call);
} else {
@@ -88,12 +87,12 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFa
}
}
private @NonNull String describe(@NonNull UUID uuid) {
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
private @NonNull String describe(@NonNull ACI aci) {
if (aci.isUnknown()) {
return context.getString(R.string.MessageRecord_unknown);
}
Recipient recipient = Recipient.resolved(RecipientId.from(uuid, null));
Recipient recipient = Recipient.resolved(RecipientId.from(aci, null));
if (recipient.isSelf()) {
return context.getString(R.string.MessageRecord_you);

View File

@@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.util.ExpirationUtil;
import org.thoughtcrime.securesms.util.StringUtil;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.Arrays;
@@ -744,11 +745,12 @@ final class GroupsV2UpdateMessageProducer {
interface DescribeMemberStrategy {
/**
* Map a UUID to a string that describes the group member.
* Map an ACI to a string that describes the group member.
* @param aci
*/
@NonNull
@WorkerThread
String describe(@NonNull UUID uuid);
String describe(@NonNull ACI aci);
}
private interface StringFactory1Arg {
@@ -769,9 +771,9 @@ final class GroupsV2UpdateMessageProducer {
@NonNull StringFactory1Arg stringFactory,
@DrawableRes int iconResource)
{
UUID uuid1 = UuidUtil.fromByteStringOrUnknown(uuid1Bytes);
ACI aci1 = ACI.fromByteStringOrUnknown(uuid1Bytes);
return UpdateDescription.mentioning(Collections.singletonList(uuid1), () -> stringFactory.create(descriptionStrategy.describe(uuid1)), iconResource);
return UpdateDescription.mentioning(Collections.singletonList(aci1), () -> stringFactory.create(descriptionStrategy.describe(aci1)), iconResource);
}
private UpdateDescription updateDescription(@NonNull ByteString uuid1Bytes,
@@ -779,9 +781,9 @@ final class GroupsV2UpdateMessageProducer {
@NonNull StringFactory2Args stringFactory,
@DrawableRes int iconResource)
{
UUID uuid1 = UuidUtil.fromByteStringOrUnknown(uuid1Bytes);
UUID uuid2 = UuidUtil.fromByteStringOrUnknown(uuid2Bytes);
ACI aci1 = ACI.fromByteStringOrUnknown(uuid1Bytes);
ACI aci2 = ACI.fromByteStringOrUnknown(uuid2Bytes);
return UpdateDescription.mentioning(Arrays.asList(uuid1, uuid2), () -> stringFactory.create(descriptionStrategy.describe(uuid1), descriptionStrategy.describe(uuid2)), iconResource);
return UpdateDescription.mentioning(Arrays.asList(aci1, aci2), () -> stringFactory.create(descriptionStrategy.describe(aci1), descriptionStrategy.describe(aci2)), iconResource);
}
}

View File

@@ -54,6 +54,7 @@ import org.thoughtcrime.securesms.util.StringUtil;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Function;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.io.IOException;
@@ -240,7 +241,7 @@ public abstract class MessageRecord extends DisplayRecord {
private static boolean selfCreatedGroup(@NonNull DecryptedGroupChange change) {
return change.getRevision() == 0 &&
change.getEditor().equals(UuidUtil.toByteString(Recipient.self().requireUuid()));
change.getEditor().equals(UuidUtil.toByteString(Recipient.self().requireAci().uuid()));
}
public static @NonNull UpdateDescription getGv2ChangeDescription(@NonNull Context context, @NonNull String body) {
@@ -248,7 +249,7 @@ public abstract class MessageRecord extends DisplayRecord {
ShortStringDescriptionStrategy descriptionStrategy = new ShortStringDescriptionStrategy(context);
byte[] decoded = Base64.decode(body);
DecryptedGroupV2Context decryptedGroupV2Context = DecryptedGroupV2Context.parseFrom(decoded);
GroupsV2UpdateMessageProducer updateMessageProducer = new GroupsV2UpdateMessageProducer(context, descriptionStrategy, Recipient.self().getUuid().get());
GroupsV2UpdateMessageProducer updateMessageProducer = new GroupsV2UpdateMessageProducer(context, descriptionStrategy, Recipient.self().requireAci().uuid());
if (decryptedGroupV2Context.hasChange() && (decryptedGroupV2Context.getGroupState().getRevision() != 0 || decryptedGroupV2Context.hasPreviousGroupState())) {
return UpdateDescription.concatWithNewLines(updateMessageProducer.describeChanges(decryptedGroupV2Context.getPreviousGroupState(), decryptedGroupV2Context.getChange()));
@@ -279,7 +280,7 @@ public abstract class MessageRecord extends DisplayRecord {
}
DecryptedGroup groupState = decryptedGroupV2Context.getGroupState();
boolean invited = DecryptedGroupUtil.findPendingByUuid(groupState.getPendingMembersList(), Recipient.self().requireUuid()).isPresent();
boolean invited = DecryptedGroupUtil.findPendingByUuid(groupState.getPendingMembersList(), Recipient.self().requireAci().uuid()).isPresent();
if (decryptedGroupV2Context.hasChange()) {
UUID changeEditor = UuidUtil.fromByteStringOrNull(decryptedGroupV2Context.getChange().getEditor());
@@ -301,7 +302,7 @@ public abstract class MessageRecord extends DisplayRecord {
@NonNull Function<Recipient, String> stringGenerator,
@DrawableRes int iconResource)
{
return UpdateDescription.mentioning(Collections.singletonList(recipient.getUuid().or(UuidUtil.UNKNOWN_UUID)),
return UpdateDescription.mentioning(Collections.singletonList(recipient.getAci().or(ACI.UNKNOWN)),
() -> stringGenerator.apply(recipient.resolve()),
iconResource);
}
@@ -369,10 +370,11 @@ public abstract class MessageRecord extends DisplayRecord {
public static @NonNull UpdateDescription getGroupCallUpdateDescription(@NonNull Context context, @NonNull String body, boolean withTime) {
GroupCallUpdateDetails groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(body);
List<UUID> joinedMembers = Stream.of(groupCallUpdateDetails.getInCallUuidsList())
.map(UuidUtil::parseOrNull)
.withoutNulls()
.toList();
List<ACI> joinedMembers = Stream.of(groupCallUpdateDetails.getInCallUuidsList())
.map(UuidUtil::parseOrNull)
.withoutNulls()
.map(ACI::from)
.toList();
UpdateDescription.StringFactory stringFactory = new GroupCallUpdateMessageFactory(context, joinedMembers, withTime, groupCallUpdateDetails);
@@ -407,11 +409,11 @@ public abstract class MessageRecord extends DisplayRecord {
}
@Override
public @NonNull String describe(@NonNull UUID uuid) {
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
public @NonNull String describe(@NonNull ACI aci) {
if (aci.isUnknown()) {
return context.getString(R.string.MessageRecord_unknown);
}
return Recipient.resolved(RecipientId.from(uuid, null)).getDisplayName(context);
return Recipient.resolved(RecipientId.from(aci, null)).getDisplayName(context);
}
}

View File

@@ -8,6 +8,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import org.signal.core.util.ThreadUtil;
import org.whispersystems.signalservice.api.push.ACI;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.Collection;
@@ -27,14 +28,14 @@ public final class UpdateDescription {
String create();
}
private final Collection<UUID> mentioned;
private final StringFactory stringFactory;
private final String staticString;
private final int lightIconResource;
private final int lightTint;
private final int darkTint;
private final Collection<ACI> mentioned;
private final StringFactory stringFactory;
private final String staticString;
private final int lightIconResource;
private final int lightTint;
private final int darkTint;
private UpdateDescription(@NonNull Collection<UUID> mentioned,
private UpdateDescription(@NonNull Collection<ACI> mentioned,
@Nullable StringFactory stringFactory,
@Nullable String staticString,
@DrawableRes int iconResource,
@@ -59,11 +60,11 @@ public final class UpdateDescription {
* @param mentioned UUIDs of recipients that are mentioned in the string.
* @param stringFactory The background method for generating the string.
*/
public static UpdateDescription mentioning(@NonNull Collection<UUID> mentioned,
public static UpdateDescription mentioning(@NonNull Collection<ACI> mentioned,
@NonNull StringFactory stringFactory,
@DrawableRes int iconResource)
{
return new UpdateDescription(UuidUtil.filterKnown(mentioned),
return new UpdateDescription(ACI.filterKnown(mentioned),
stringFactory,
null,
iconResource,
@@ -117,7 +118,7 @@ public final class UpdateDescription {
}
@AnyThread
public Collection<UUID> getMentioned() {
public Collection<ACI> getMentioned() {
return mentioned;
}
@@ -148,7 +149,7 @@ public final class UpdateDescription {
);
}
Set<UUID> allMentioned = new HashSet<>();
Set<ACI> allMentioned = new HashSet<>();
for (UpdateDescription updateDescription : updateDescriptions) {
allMentioned.addAll(updateDescription.getMentioned());