Move from ACI to a generic ServiceId.

This commit is contained in:
Greyson Parrelli
2022-02-17 15:55:54 -05:00
parent 9f1deda220
commit 7ca2420287
110 changed files with 841 additions and 824 deletions

View File

@@ -7,8 +7,6 @@ import android.database.Cursor;
import androidx.annotation.AnyThread;
import androidx.annotation.NonNull;
import net.zetetic.database.sqlcipher.SQLiteDatabase;
import org.signal.core.util.ThreadUtil;
import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.Log;
@@ -153,7 +151,7 @@ public final class LiveRecipientCache {
String localE164 = SignalStore.account().getE164();
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) {
selfId = recipientDatabase.getByE164(localE164).orNull();
} else {
@@ -235,6 +233,6 @@ public final class LiveRecipientCache {
}
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());
}
}

View File

@@ -49,6 +49,7 @@ import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.libsignal.util.guava.Preconditions;
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.SignalServiceAddress;
import org.whispersystems.signalservice.api.util.UuidUtil;
@@ -78,7 +79,7 @@ public class Recipient {
private final RecipientId id;
private final boolean resolving;
private final ACI aci;
private final ServiceId serviceId;
private final PNI pni;
private final String username;
private final String e164;
@@ -166,8 +167,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 ACI aci, @NonNull String username) {
Recipient recipient = externalPush(context, aci, null, false);
public static @NonNull Recipient externalUsername(@NonNull ServiceId serviceId, @NonNull String username) {
Recipient recipient = externalPush(serviceId, null, false);
SignalDatabase.recipients().setUsername(recipient.getId(), username);
return recipient;
}
@@ -175,11 +176,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, ACI, String, boolean)}
* {@link #externalPush(ServiceId, String, boolean)}
*/
@WorkerThread
public static @NonNull Recipient externalPush(@NonNull Context context, @NonNull SignalServiceAddress signalServiceAddress) {
return externalPush(context, signalServiceAddress.getAci(), signalServiceAddress.getNumber().orNull(), false);
public static @NonNull Recipient externalPush(@NonNull SignalServiceAddress signalServiceAddress) {
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.
*/
@WorkerThread
public static @NonNull Recipient externalGV1Member(@NonNull Context context, @NonNull SignalServiceAddress address) {
public static @NonNull Recipient externalGV1Member(@NonNull SignalServiceAddress address) {
if (address.getNumber().isPresent()) {
return externalPush(context, null, address.getNumber().get(), false);
return externalPush(null, address.getNumber().get(), false);
} else {
return externalPush(context, address.getAci(), null, false);
return externalPush(address.getServiceId(), null, false);
}
}
@@ -207,7 +208,7 @@ public class Recipient {
*/
@WorkerThread
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).
*/
@WorkerThread
public static @NonNull Recipient externalPush(@NonNull Context context, @Nullable ACI aci, @Nullable String e164, boolean highTrust) {
if (ACI.UNKNOWN.equals(aci)) {
public static @NonNull Recipient externalPush(@Nullable ServiceId serviceId, @Nullable String e164, boolean highTrust) {
if (ServiceId.UNKNOWN.equals(serviceId)) {
throw new AssertionError();
}
RecipientDatabase db = SignalDatabase.recipients();
RecipientId recipientId = db.getAndPossiblyMerge(aci, e164, highTrust);
RecipientId recipientId = db.getAndPossiblyMerge(serviceId, e164, highTrust);
Recipient resolved = resolved(recipientId);
@@ -237,9 +238,9 @@ public class Recipient {
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.");
db.markRegistered(recipientId, aci);
db.markRegistered(recipientId, serviceId);
} 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());
}
@@ -305,7 +306,7 @@ public class Recipient {
* or serialized groupId.
*
* 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.
*/
@WorkerThread
@@ -317,7 +318,7 @@ public class Recipient {
if (UuidUtil.isUuid(identifier)) {
ACI uuid = ACI.parseOrThrow(identifier);
id = db.getOrInsertFromAci(uuid);
id = db.getOrInsertFromServiceId(uuid);
} else if (GroupId.isEncodedGroup(identifier)) {
id = db.getOrInsertFromGroupId(GroupId.parseOrThrow(identifier));
} else if (NumberUtil.isValidEmail(identifier)) {
@@ -337,7 +338,7 @@ public class Recipient {
Recipient(@NonNull RecipientId id) {
this.id = id;
this.resolving = true;
this.aci = null;
this.serviceId = null;
this.pni = null;
this.username = null;
this.e164 = null;
@@ -392,9 +393,9 @@ public class Recipient {
public Recipient(@NonNull RecipientId id, @NonNull RecipientDetails details, boolean resolved) {
this.id = id;
this.resolving = !resolved;
this.aci = details.aci;
this.pni = details.pni;
this.resolving = !resolved;
this.serviceId = details.serviceId;
this.pni = details.pni;
this.username = details.username;
this.e164 = details.e164;
this.email = details.email;
@@ -614,8 +615,8 @@ public class Recipient {
return StringUtil.isolateBidi(name);
}
public @NonNull Optional<ACI> getAci() {
return Optional.fromNullable(aci);
public @NonNull Optional<ServiceId> getServiceId() {
return Optional.fromNullable(serviceId);
}
public @NonNull Optional<PNI> getPni() {
@@ -646,16 +647,6 @@ public class Recipient {
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() {
PNI resolved = resolving ? resolve().pni : pni;
@@ -706,16 +697,12 @@ public class Recipient {
return getE164().isPresent();
}
public boolean hasAci() {
return getAci().isPresent();
public boolean hasServiceId() {
return getServiceId().isPresent();
}
public boolean hasPni() {
return getPni().isPresent();
}
public boolean isAciOnly() {
return hasAci() && !hasSmsAddress();
public boolean isServiceIdOnly() {
return hasServiceId() && !hasSmsAddress();
}
public @NonNull GroupId requireGroupId() {
@@ -728,36 +715,31 @@ public class Recipient {
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
* available, will return an E164 number.
* The {@link ServiceId} of the user if available, otherwise throw.
*/
public @NonNull String requireServiceId() {
Recipient resolved = resolving ? resolve() : this;
public @NonNull ServiceId requireServiceId() {
ServiceId resolved = resolving ? resolve().serviceId : serviceId;
if (resolved.getAci().isPresent()) {
return resolved.requireAci().toString();
} else {
return getE164().get();
if (resolved == null) {
throw new MissingAddressError(id);
}
return resolved;
}
/**
* @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() {
Recipient resolved = resolving ? resolve() : this;
if (resolved.isGroup()) {
return resolved.requireGroupId().toString();
} else if (resolved.getAci().isPresent()) {
return resolved.requireAci().toString();
} else if (resolved.getServiceId().isPresent()) {
return resolved.requireServiceId().toString();
}
return requireSmsAddress();
@@ -1214,7 +1196,7 @@ public class Recipient {
profileSharing == other.profileSharing &&
lastProfileFetch == other.lastProfileFetch &&
forceSmsSelection == other.forceSmsSelection &&
Objects.equals(aci, other.aci) &&
Objects.equals(serviceId, other.serviceId) &&
Objects.equals(username, other.username) &&
Objects.equals(e164, other.e164) &&
Objects.equals(email, other.email) &&

View File

@@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
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.ServiceId;
import java.util.Collections;
import java.util.LinkedList;
@@ -32,7 +33,7 @@ import java.util.List;
public class RecipientDetails {
final ACI aci;
final ServiceId serviceId;
final PNI pni;
final String username;
final String e164;
@@ -99,7 +100,7 @@ public class RecipientDetails {
this.systemContactPhoto = Util.uri(record.getSystemContactPhotoUri());
this.customLabel = record.getSystemPhoneLabel();
this.contactUri = Util.uri(record.getSystemContactUri());
this.aci = record.getAci();
this.serviceId = record.getServiceId();
this.pni = record.getPni();
this.username = record.getUsername();
this.e164 = record.getE164();
@@ -156,9 +157,9 @@ public class RecipientDetails {
this.groupAvatarId = null;
this.systemContactPhoto = null;
this.customLabel = null;
this.contactUri = null;
this.aci = null;
this.pni = null;
this.contactUri = null;
this.serviceId = null;
this.pni = null;
this.username = null;
this.e164 = null;
this.email = null;
@@ -210,7 +211,7 @@ public class RecipientDetails {
public static @NonNull RecipientDetails forIndividual(@NonNull Context context, @NonNull RecipientRecord settings) {
boolean systemContact = !settings.getSystemProfileName().isEmpty();
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());
RegisteredState registeredState = settings.getRegistered();

View File

@@ -15,13 +15,13 @@ 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.ServiceId;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
public class RecipientId implements Parcelable, Comparable<RecipientId> {
@@ -55,7 +55,7 @@ public class RecipientId implements Parcelable, Comparable<RecipientId> {
@AnyThread
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
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
@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);
}
@AnyThread
@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);
if (recipientId == null) {
Recipient recipient = Recipient.externalPush(ApplicationDependencies.getApplication(), aci, e164, highTrust);
Recipient recipient = Recipient.externalPush(aci, e164, highTrust);
RecipientIdCache.INSTANCE.put(recipient);
recipientId = recipient.getId();
}

View File

@@ -5,11 +5,10 @@ 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 org.whispersystems.signalservice.api.push.ServiceId;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
/**
* 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) {
RecipientId recipientId = recipient.getId();
Optional<String> e164 = recipient.getE164();
Optional<ACI> aci = recipient.getAci();
RecipientId recipientId = recipient.getId();
Optional<String> e164 = recipient.getE164();
Optional<ServiceId> serviceId = recipient.getServiceId();
if (e164.isPresent()) {
ids.put(e164.get(), recipientId);
}
if (aci.isPresent()) {
ids.put(aci.get(), recipientId);
if (serviceId.isPresent()) {
ids.put(serviceId.get(), recipientId);
}
}
synchronized @Nullable RecipientId get(@Nullable ACI aci, @Nullable String e164) {
if (aci != null && e164 != null) {
RecipientId recipientIdByAci = ids.get(aci);
synchronized @Nullable RecipientId get(@Nullable ServiceId serviceId, @Nullable String e164) {
if (serviceId != null && e164 != null) {
RecipientId recipientIdByAci = ids.get(serviceId);
if (recipientIdByAci == null) return null;
RecipientId recipientIdByE164 = ids.get(e164);
@@ -58,13 +57,13 @@ final class RecipientIdCache {
if (recipientIdByAci.equals(recipientIdByE164)) {
return recipientIdByAci;
} else {
ids.remove(aci);
ids.remove(serviceId);
ids.remove(e164);
Log.w(TAG, "Seen invalid RecipientIdCacheState");
return null;
}
} else if (aci != null) {
return ids.get(aci);
} else if (serviceId != null) {
return ids.get(serviceId);
} else if (e164 != null) {
return ids.get(e164);
}

View File

@@ -49,11 +49,11 @@ public class RecipientUtil {
{
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!");
}
if (!recipient.getAci().isPresent()) {
if (!recipient.getServiceId().isPresent()) {
Log.i(TAG, recipient.getId() + " is missing a UUID...");
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);
}
if (recipient.hasAci()) {
return new SignalServiceAddress(recipient.requireAci(), Optional.fromNullable(recipient.resolve().getE164().orNull()));
if (recipient.hasServiceId()) {
return new SignalServiceAddress(recipient.requireServiceId(), Optional.fromNullable(recipient.resolve().getE164().orNull()));
} else {
throw new NotFoundException(recipient.getId() + " is not registered!");
}
@@ -81,7 +81,7 @@ public class RecipientUtil {
return Stream.of(recipients)
.map(Recipient::resolve)
.map(r -> new SignalServiceAddress(r.requireAci(), r.getE164().orNull()))
.map(r -> new SignalServiceAddress(r.requireServiceId(), r.getE164().orNull()))
.toList();
}
@@ -93,7 +93,7 @@ public class RecipientUtil {
{
List<Recipient> recipientsWithoutUuids = Stream.of(recipients)
.map(Recipient::resolve)
.filterNot(Recipient::hasAci)
.filterNot(Recipient::hasServiceId)
.toList();
if (recipientsWithoutUuids.size() > 0) {
@@ -178,7 +178,7 @@ public class RecipientUtil {
ApplicationDependencies.getJobManager().add(new MultiDeviceBlockedUpdateJob());
StorageSyncHelper.scheduleSyncForDataChange();
if (recipient.hasServiceIdentifier()) {
if (recipient.hasServiceId()) {
ApplicationDependencies.getJobManager().add(MultiDeviceMessageRequestResponseJob.forAccept(recipient.getId()));
}
}