mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-22 01:40:07 +01:00
Strongly type UUIDs as ACIs.
This commit is contained in:
@@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.util.LRUCache;
|
||||
import org.thoughtcrime.securesms.util.Stopwatch;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.concurrent.FilteredExecutor;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -160,11 +161,11 @@ public final class LiveRecipientCache {
|
||||
}
|
||||
|
||||
if (selfId == null) {
|
||||
UUID localUuid = TextSecurePreferences.getLocalUuid(context);
|
||||
ACI localAci = TextSecurePreferences.getLocalAci(context);
|
||||
String localE164 = TextSecurePreferences.getLocalNumber(context);
|
||||
|
||||
if (localUuid != null) {
|
||||
selfId = recipientDatabase.getByUuid(localUuid).or(recipientDatabase.getByE164(localE164)).orNull();
|
||||
if (localAci != null) {
|
||||
selfId = recipientDatabase.getByAci(localAci).or(recipientDatabase.getByE164(localE164)).orNull();
|
||||
} else if (localE164 != null) {
|
||||
selfId = recipientDatabase.getByE164(localE164).orNull();
|
||||
} else {
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.MentionSetting;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.RecipientExtras;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
@@ -77,7 +78,7 @@ public class Recipient {
|
||||
|
||||
private final RecipientId id;
|
||||
private final boolean resolving;
|
||||
private final UUID uuid;
|
||||
private final ACI aci;
|
||||
private final String username;
|
||||
private final String e164;
|
||||
private final String email;
|
||||
@@ -163,8 +164,8 @@ public class Recipient {
|
||||
* Returns a fully-populated {@link Recipient} and associates it with the provided username.
|
||||
*/
|
||||
@WorkerThread
|
||||
public static @NonNull Recipient externalUsername(@NonNull Context context, @NonNull UUID uuid, @NonNull String username) {
|
||||
Recipient recipient = externalPush(context, uuid, null, false);
|
||||
public static @NonNull Recipient externalUsername(@NonNull Context context, @NonNull ACI aci, @NonNull String username) {
|
||||
Recipient recipient = externalPush(context, aci, null, false);
|
||||
DatabaseFactory.getRecipientDatabase(context).setUsername(recipient.getId(), username);
|
||||
return recipient;
|
||||
}
|
||||
@@ -172,11 +173,11 @@ public class Recipient {
|
||||
/**
|
||||
* Returns a fully-populated {@link Recipient} based off of a {@link SignalServiceAddress},
|
||||
* creating one in the database if necessary. Convenience overload of
|
||||
* {@link #externalPush(Context, UUID, String, boolean)}
|
||||
* {@link #externalPush(Context, ACI, String, boolean)}
|
||||
*/
|
||||
@WorkerThread
|
||||
public static @NonNull Recipient externalPush(@NonNull Context context, @NonNull SignalServiceAddress signalServiceAddress) {
|
||||
return externalPush(context, signalServiceAddress.getUuid(), signalServiceAddress.getNumber().orNull(), false);
|
||||
return externalPush(context, signalServiceAddress.getAci(), signalServiceAddress.getNumber().orNull(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +190,7 @@ public class Recipient {
|
||||
if (address.getNumber().isPresent()) {
|
||||
return externalPush(context, null, address.getNumber().get(), false);
|
||||
} else {
|
||||
return externalPush(context, address.getUuid(), null, false);
|
||||
return externalPush(context, address.getAci(), null, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +205,7 @@ public class Recipient {
|
||||
*/
|
||||
@WorkerThread
|
||||
public static @NonNull Recipient externalHighTrustPush(@NonNull Context context, @NonNull SignalServiceAddress signalServiceAddress) {
|
||||
return externalPush(context, signalServiceAddress.getUuid(), signalServiceAddress.getNumber().orNull(), true);
|
||||
return externalPush(context, signalServiceAddress.getAci(), signalServiceAddress.getNumber().orNull(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,19 +221,19 @@ public class Recipient {
|
||||
* that can be trusted as accurate (like an envelope).
|
||||
*/
|
||||
@WorkerThread
|
||||
public static @NonNull Recipient externalPush(@NonNull Context context, @Nullable UUID uuid, @Nullable String e164, boolean highTrust) {
|
||||
if (UuidUtil.UNKNOWN_UUID.equals(uuid)) {
|
||||
public static @NonNull Recipient externalPush(@NonNull Context context, @Nullable ACI aci, @Nullable String e164, boolean highTrust) {
|
||||
if (UuidUtil.UNKNOWN_UUID.equals(aci)) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
RecipientDatabase db = DatabaseFactory.getRecipientDatabase(context);
|
||||
RecipientId recipientId = db.getAndPossiblyMerge(uuid, e164, highTrust);
|
||||
RecipientId recipientId = db.getAndPossiblyMerge(aci, e164, highTrust);
|
||||
|
||||
Recipient resolved = resolved(recipientId);
|
||||
|
||||
if (highTrust && !resolved.isRegistered() && uuid != null) {
|
||||
if (highTrust && !resolved.isRegistered() && aci != null) {
|
||||
Log.w(TAG, "External high-trust push was locally marked unregistered. Marking as registered.");
|
||||
db.markRegistered(recipientId, uuid);
|
||||
db.markRegistered(recipientId, aci);
|
||||
} else if (highTrust && !resolved.isRegistered()) {
|
||||
Log.w(TAG, "External high-trust push was locally marked unregistered, but we don't have a UUID, so we can't do anything.", new Throwable());
|
||||
}
|
||||
@@ -298,7 +299,7 @@ public class Recipient {
|
||||
* or serialized groupId.
|
||||
*
|
||||
* If the identifier is a UUID of a Signal user, prefer using
|
||||
* {@link #externalPush(Context, UUID, String, boolean)} or its overload, as this will let us associate
|
||||
* {@link #externalPush(Context, ACI, String, boolean)} or its overload, as this will let us associate
|
||||
* the phone number with the recipient.
|
||||
*/
|
||||
@WorkerThread
|
||||
@@ -309,8 +310,8 @@ public class Recipient {
|
||||
RecipientId id = null;
|
||||
|
||||
if (UuidUtil.isUuid(identifier)) {
|
||||
UUID uuid = UuidUtil.parseOrThrow(identifier);
|
||||
id = db.getOrInsertFromUuid(uuid);
|
||||
ACI uuid = ACI.parseOrThrow(identifier);
|
||||
id = db.getOrInsertFromAci(uuid);
|
||||
} else if (GroupId.isEncodedGroup(identifier)) {
|
||||
id = db.getOrInsertFromGroupId(GroupId.parseOrThrow(identifier));
|
||||
} else if (NumberUtil.isValidEmail(identifier)) {
|
||||
@@ -329,9 +330,9 @@ public class Recipient {
|
||||
|
||||
Recipient(@NonNull RecipientId id) {
|
||||
this.id = id;
|
||||
this.resolving = true;
|
||||
this.uuid = null;
|
||||
this.username = null;
|
||||
this.resolving = true;
|
||||
this.aci = null;
|
||||
this.username = null;
|
||||
this.e164 = null;
|
||||
this.email = null;
|
||||
this.groupId = null;
|
||||
@@ -384,7 +385,7 @@ public class Recipient {
|
||||
public Recipient(@NonNull RecipientId id, @NonNull RecipientDetails details, boolean resolved) {
|
||||
this.id = id;
|
||||
this.resolving = !resolved;
|
||||
this.uuid = details.uuid;
|
||||
this.aci = details.aci;
|
||||
this.username = details.username;
|
||||
this.e164 = details.e164;
|
||||
this.email = details.email;
|
||||
@@ -603,8 +604,8 @@ public class Recipient {
|
||||
return StringUtil.isolateBidi(name);
|
||||
}
|
||||
|
||||
public @NonNull Optional<UUID> getUuid() {
|
||||
return Optional.fromNullable(uuid);
|
||||
public @NonNull Optional<ACI> getAci() {
|
||||
return Optional.fromNullable(aci);
|
||||
}
|
||||
|
||||
public @NonNull Optional<String> getUsername() {
|
||||
@@ -631,8 +632,8 @@ public class Recipient {
|
||||
return Optional.fromNullable(e164).or(Optional.fromNullable(email));
|
||||
}
|
||||
|
||||
public @NonNull UUID requireUuid() {
|
||||
UUID resolved = resolving ? resolve().uuid : uuid;
|
||||
public @NonNull ACI requireAci() {
|
||||
ACI resolved = resolving ? resolve().aci : aci;
|
||||
|
||||
if (resolved == null) {
|
||||
throw new MissingAddressError(id);
|
||||
@@ -682,12 +683,12 @@ public class Recipient {
|
||||
return getE164().isPresent();
|
||||
}
|
||||
|
||||
public boolean hasUuid() {
|
||||
return getUuid().isPresent();
|
||||
public boolean hasAci() {
|
||||
return getAci().isPresent();
|
||||
}
|
||||
|
||||
public boolean isUuidOnly() {
|
||||
return hasUuid() && !hasSmsAddress();
|
||||
public boolean isAciOnly() {
|
||||
return hasAci() && !hasSmsAddress();
|
||||
}
|
||||
|
||||
public @NonNull GroupId requireGroupId() {
|
||||
@@ -701,18 +702,18 @@ public class Recipient {
|
||||
}
|
||||
|
||||
public boolean hasServiceIdentifier() {
|
||||
return uuid != null || e164 != null;
|
||||
return aci != null || e164 != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A string identifier able to be used with the Signal service. Prefers UUID, and if not
|
||||
* @return A string identifier able to be used with the Signal service. Prefers ACI, and if not
|
||||
* available, will return an E164 number.
|
||||
*/
|
||||
public @NonNull String requireServiceId() {
|
||||
Recipient resolved = resolving ? resolve() : this;
|
||||
|
||||
if (resolved.getUuid().isPresent()) {
|
||||
return resolved.getUuid().get().toString();
|
||||
if (resolved.getAci().isPresent()) {
|
||||
return resolved.requireAci().toString();
|
||||
} else {
|
||||
return getE164().get();
|
||||
}
|
||||
@@ -721,15 +722,15 @@ public class Recipient {
|
||||
/**
|
||||
* @return A single string to represent the recipient, in order of precedence:
|
||||
*
|
||||
* Group ID > UUID > Phone > Email
|
||||
* Group ID > ACI > Phone > Email
|
||||
*/
|
||||
public @NonNull String requireStringId() {
|
||||
Recipient resolved = resolving ? resolve() : this;
|
||||
|
||||
if (resolved.isGroup()) {
|
||||
return resolved.requireGroupId().toString();
|
||||
} else if (resolved.getUuid().isPresent()) {
|
||||
return resolved.getUuid().get().toString();
|
||||
} else if (resolved.getAci().isPresent()) {
|
||||
return resolved.requireAci().toString();
|
||||
}
|
||||
|
||||
return requireSmsAddress();
|
||||
@@ -1183,7 +1184,7 @@ public class Recipient {
|
||||
lastProfileFetch == other.lastProfileFetch &&
|
||||
forceSmsSelection == other.forceSmsSelection &&
|
||||
Objects.equals(id, other.id) &&
|
||||
Objects.equals(uuid, other.uuid) &&
|
||||
Objects.equals(aci, other.aci) &&
|
||||
Objects.equals(username, other.username) &&
|
||||
Objects.equals(e164, other.e164) &&
|
||||
Objects.equals(email, other.email) &&
|
||||
|
||||
@@ -22,15 +22,15 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class RecipientDetails {
|
||||
|
||||
final UUID uuid;
|
||||
final ACI aci;
|
||||
final String username;
|
||||
final String e164;
|
||||
final String email;
|
||||
@@ -94,7 +94,7 @@ public class RecipientDetails {
|
||||
this.systemContactPhoto = Util.uri(settings.getSystemContactPhotoUri());
|
||||
this.customLabel = settings.getSystemPhoneLabel();
|
||||
this.contactUri = Util.uri(settings.getSystemContactUri());
|
||||
this.uuid = settings.getUuid();
|
||||
this.aci = settings.getAci();
|
||||
this.username = settings.getUsername();
|
||||
this.e164 = settings.getE164();
|
||||
this.email = settings.getEmail();
|
||||
@@ -149,9 +149,9 @@ public class RecipientDetails {
|
||||
this.groupAvatarId = null;
|
||||
this.systemContactPhoto = null;
|
||||
this.customLabel = null;
|
||||
this.contactUri = null;
|
||||
this.uuid = null;
|
||||
this.username = null;
|
||||
this.contactUri = null;
|
||||
this.aci = null;
|
||||
this.username = null;
|
||||
this.e164 = null;
|
||||
this.email = null;
|
||||
this.groupId = null;
|
||||
@@ -201,7 +201,7 @@ public class RecipientDetails {
|
||||
public static @NonNull RecipientDetails forIndividual(@NonNull Context context, @NonNull RecipientSettings settings) {
|
||||
boolean systemContact = !settings.getSystemProfileName().isEmpty();
|
||||
boolean isSelf = (settings.getE164() != null && settings.getE164().equals(TextSecurePreferences.getLocalNumber(context))) ||
|
||||
(settings.getUuid() != null && settings.getUuid().equals(TextSecurePreferences.getLocalUuid(context)));
|
||||
(settings.getAci() != null && settings.getAci().equals(TextSecurePreferences.getLocalAci(context)));
|
||||
|
||||
RegisteredState registeredState = settings.getRegistered();
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.annimon.stream.Stream;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.util.DelimiterUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
@@ -54,7 +55,7 @@ public class RecipientId implements Parcelable, Comparable<RecipientId> {
|
||||
|
||||
@AnyThread
|
||||
public static @NonNull RecipientId from(@NonNull SignalServiceAddress address) {
|
||||
return from(address.getUuid(), address.getNumber().orNull(), false);
|
||||
return from(address.getAci(), address.getNumber().orNull(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +66,7 @@ public class RecipientId implements Parcelable, Comparable<RecipientId> {
|
||||
@AnyThread
|
||||
public static @NonNull RecipientId fromExternalPush(@NonNull String identifier) {
|
||||
if (UuidUtil.isUuid(identifier)) {
|
||||
return from(UuidUtil.parseOrThrow(identifier), null);
|
||||
return from(ACI.parseOrThrow(identifier), null);
|
||||
} else {
|
||||
return from(null, identifier);
|
||||
}
|
||||
@@ -77,7 +78,7 @@ public class RecipientId implements Parcelable, Comparable<RecipientId> {
|
||||
*/
|
||||
@AnyThread
|
||||
public static @NonNull RecipientId fromHighTrust(@NonNull SignalServiceAddress address) {
|
||||
return from(address.getUuid(), address.getNumber().orNull(), true);
|
||||
return from(address.getAci(), address.getNumber().orNull(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,17 +86,17 @@ public class RecipientId implements Parcelable, Comparable<RecipientId> {
|
||||
*/
|
||||
@AnyThread
|
||||
@SuppressLint("WrongThread")
|
||||
public static @NonNull RecipientId from(@Nullable UUID uuid, @Nullable String e164) {
|
||||
return from(uuid, e164, false);
|
||||
public static @NonNull RecipientId from(@Nullable ACI aci, @Nullable String e164) {
|
||||
return from(aci, e164, false);
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@SuppressLint("WrongThread")
|
||||
private static @NonNull RecipientId from(@Nullable UUID uuid, @Nullable String e164, boolean highTrust) {
|
||||
RecipientId recipientId = RecipientIdCache.INSTANCE.get(uuid, e164);
|
||||
private static @NonNull RecipientId from(@Nullable ACI aci, @Nullable String e164, boolean highTrust) {
|
||||
RecipientId recipientId = RecipientIdCache.INSTANCE.get(aci, e164);
|
||||
|
||||
if (recipientId == null) {
|
||||
Recipient recipient = Recipient.externalPush(ApplicationDependencies.getApplication(), uuid, e164, highTrust);
|
||||
Recipient recipient = Recipient.externalPush(ApplicationDependencies.getApplication(), aci, e164, highTrust);
|
||||
RecipientIdCache.INSTANCE.put(recipient);
|
||||
recipientId = recipient.getId();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.push.ACI;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@@ -35,35 +36,35 @@ final class RecipientIdCache {
|
||||
synchronized void put(@NonNull Recipient recipient) {
|
||||
RecipientId recipientId = recipient.getId();
|
||||
Optional<String> e164 = recipient.getE164();
|
||||
Optional<UUID> uuid = recipient.getUuid();
|
||||
Optional<ACI> aci = recipient.getAci();
|
||||
|
||||
if (e164.isPresent()) {
|
||||
ids.put(e164.get(), recipientId);
|
||||
}
|
||||
|
||||
if (uuid.isPresent()) {
|
||||
ids.put(uuid.get(), recipientId);
|
||||
if (aci.isPresent()) {
|
||||
ids.put(aci.get(), recipientId);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized @Nullable RecipientId get(@Nullable UUID uuid, @Nullable String e164) {
|
||||
if (uuid != null && e164 != null) {
|
||||
RecipientId recipientIdByUuid = ids.get(uuid);
|
||||
if (recipientIdByUuid == null) return null;
|
||||
synchronized @Nullable RecipientId get(@Nullable ACI aci, @Nullable String e164) {
|
||||
if (aci != null && e164 != null) {
|
||||
RecipientId recipientIdByAci = ids.get(aci);
|
||||
if (recipientIdByAci == null) return null;
|
||||
|
||||
RecipientId recipientIdByE164 = ids.get(e164);
|
||||
if (recipientIdByE164 == null) return null;
|
||||
|
||||
if (recipientIdByUuid.equals(recipientIdByE164)) {
|
||||
return recipientIdByUuid;
|
||||
if (recipientIdByAci.equals(recipientIdByE164)) {
|
||||
return recipientIdByAci;
|
||||
} else {
|
||||
ids.remove(uuid);
|
||||
ids.remove(aci);
|
||||
ids.remove(e164);
|
||||
Log.w(TAG, "Seen invalid RecipientIdCacheState");
|
||||
return null;
|
||||
}
|
||||
} else if (uuid != null) {
|
||||
return ids.get(uuid);
|
||||
} else if (aci != null) {
|
||||
return ids.get(aci);
|
||||
} else if (e164 != null) {
|
||||
return ids.get(e164);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class RecipientUtil {
|
||||
|
||||
@@ -50,11 +49,11 @@ public class RecipientUtil {
|
||||
{
|
||||
recipient = recipient.resolve();
|
||||
|
||||
if (!recipient.getUuid().isPresent() && !recipient.getE164().isPresent()) {
|
||||
if (!recipient.getAci().isPresent() && !recipient.getE164().isPresent()) {
|
||||
throw new AssertionError(recipient.getId() + " - No UUID or phone number!");
|
||||
}
|
||||
|
||||
if (!recipient.getUuid().isPresent()) {
|
||||
if (!recipient.getAci().isPresent()) {
|
||||
Log.i(TAG, recipient.getId() + " is missing a UUID...");
|
||||
RegisteredState state = DirectoryHelper.refreshDirectoryFor(context, recipient, false);
|
||||
|
||||
@@ -62,8 +61,8 @@ public class RecipientUtil {
|
||||
Log.i(TAG, "Successfully performed a UUID fetch for " + recipient.getId() + ". Registered: " + state);
|
||||
}
|
||||
|
||||
if (recipient.hasUuid()) {
|
||||
return new SignalServiceAddress(recipient.requireUuid(), Optional.fromNullable(recipient.resolve().getE164().orNull()));
|
||||
if (recipient.hasAci()) {
|
||||
return new SignalServiceAddress(recipient.requireAci(), Optional.fromNullable(recipient.resolve().getE164().orNull()));
|
||||
} else {
|
||||
throw new NotFoundException(recipient.getId() + " is not registered!");
|
||||
}
|
||||
@@ -82,7 +81,7 @@ public class RecipientUtil {
|
||||
|
||||
return Stream.of(recipients)
|
||||
.map(Recipient::resolve)
|
||||
.map(r -> new SignalServiceAddress(r.requireUuid(), r.getE164().orNull()))
|
||||
.map(r -> new SignalServiceAddress(r.requireAci(), r.getE164().orNull()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@@ -94,7 +93,7 @@ public class RecipientUtil {
|
||||
{
|
||||
List<Recipient> recipientsWithoutUuids = Stream.of(recipients)
|
||||
.map(Recipient::resolve)
|
||||
.filterNot(Recipient::hasUuid)
|
||||
.filterNot(Recipient::hasAci)
|
||||
.toList();
|
||||
|
||||
if (recipientsWithoutUuids.size() > 0) {
|
||||
|
||||
Reference in New Issue
Block a user