diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/SealedSenderAccessUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/SealedSenderAccessUtil.java index cbad331e3d..00eb18c5d6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/SealedSenderAccessUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/SealedSenderAccessUtil.java @@ -15,6 +15,8 @@ import org.signal.libsignal.protocol.InvalidKeyException; import org.signal.libsignal.protocol.ecc.ECPublicKey; import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.thoughtcrime.securesms.BuildConfig; +import org.thoughtcrime.securesms.database.RecipientTable.SealedSenderAccessMode; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.keyvalue.CertificateType; import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.recipients.Recipient; @@ -56,6 +58,20 @@ public class SealedSenderAccessUtil { return SealedSenderAccess.forIndividualWithGroupFallback(getAccessFor(recipient, true), getSealedSenderCertificate(), createGroupSendToken); } + @WorkerThread + public static @Nullable SealedSenderAccess getSealedSenderAccessFor(@NonNull RecipientRecord record) { + return getSealedSenderAccessFor(record, true); + } + + @WorkerThread + public static @Nullable SealedSenderAccess getSealedSenderAccessFor(@NonNull RecipientRecord record, boolean log) { + return SealedSenderAccess.forIndividual(getAccessFor(record, log)); + } + + public static @Nullable SealedSenderAccess getSealedSenderAccessFor(@NonNull RecipientRecord record, @Nullable SealedSenderAccess.CreateGroupSendToken createGroupSendToken) { + return SealedSenderAccess.forIndividualWithGroupFallback(getAccessFor(record, true), getSealedSenderCertificate(), createGroupSendToken); + } + @WorkerThread private static @Nullable UnidentifiedAccess getAccessFor(@NonNull Recipient recipient, boolean log) { return getAccessFor(Collections.singletonList(recipient), false, log) @@ -63,6 +79,39 @@ public class SealedSenderAccessUtil { .orElse(null); } + @WorkerThread + private static @Nullable UnidentifiedAccess getAccessFor(@NonNull RecipientRecord record, boolean log) { + byte[] ourUnidentifiedAccessCertificate = SignalStore.certificate().getUnidentifiedAccessCertificate(getUnidentifiedAccessCertificateType()); + + UnidentifiedAccess unidentifiedAccess = null; + if (ourUnidentifiedAccessCertificate != null) { + try { + unidentifiedAccess = getTargetUnidentifiedAccess(record.getProfileKey(), getEffectiveSealedSenderAccessMode(record), ourUnidentifiedAccessCertificate, false); + } catch (InvalidCertificateException e) { + Log.w(TAG, "Invalid unidentified access certificate!", e); + } + } else { + Log.w(TAG, "Missing our unidentified access certificate!"); + } + + if (log) { + Log.i(TAG, "Unidentified: " + (unidentifiedAccess != null ? 1 : 0) + ", Other: " + (unidentifiedAccess != null ? 0 : 1)); + } + + return unidentifiedAccess; + } + + /** + * Mirrors {@link Recipient#getSealedSenderAccessMode()}: a recipient addressed only by PNI cannot receive sealed sender. + */ + private static @NonNull SealedSenderAccessMode getEffectiveSealedSenderAccessMode(@NonNull RecipientRecord record) { + if (record.getAci() == null && record.getPni() != null) { + return SealedSenderAccessMode.DISABLED; + } else { + return record.getSealedSenderAccessMode(); + } + } + @WorkerThread public static Map> getAccessMapFor(@NonNull List recipients, boolean isForStory) { List> accessList = getAccessFor(recipients, isForStory, true); @@ -88,7 +137,8 @@ public class SealedSenderAccessUtil { UnidentifiedAccess unidentifiedAccess = null; if (ourUnidentifiedAccessCertificate != null) { try { - unidentifiedAccess = getTargetUnidentifiedAccess(recipient, ourUnidentifiedAccessCertificate, isForStory); + Recipient resolved = recipient.resolve(); + unidentifiedAccess = getTargetUnidentifiedAccess(resolved.getProfileKey(), resolved.getSealedSenderAccessMode(), ourUnidentifiedAccessCertificate, isForStory); } catch (InvalidCertificateException e) { Log.w(TAG, "Invalid unidentified access certificate!", e); } @@ -135,12 +185,12 @@ public class SealedSenderAccessUtil { .getUnidentifiedAccessCertificate(getUnidentifiedAccessCertificateType()); } - private static @Nullable UnidentifiedAccess getTargetUnidentifiedAccess(@NonNull Recipient recipient, @NonNull byte[] certificate, boolean isForStory) throws InvalidCertificateException { - ProfileKey theirProfileKey = ProfileKeyUtil.profileKeyOrNull(recipient.resolve().getProfileKey()); + private static @Nullable UnidentifiedAccess getTargetUnidentifiedAccess(@Nullable byte[] theirProfileKeyBytes, @NonNull SealedSenderAccessMode accessMode, @NonNull byte[] certificate, boolean isForStory) throws InvalidCertificateException { + ProfileKey theirProfileKey = ProfileKeyUtil.profileKeyOrNull(theirProfileKeyBytes); byte[] accessKey; - switch (recipient.resolve().getSealedSenderAccessMode()) { + switch (accessMode) { case UNKNOWN: if (theirProfileKey == null) { if (isForStory) { @@ -166,7 +216,7 @@ public class SealedSenderAccessUtil { accessKey = UNRESTRICTED_KEY; break; default: - throw new AssertionError("Unknown mode: " + recipient.getSealedSenderAccessMode().getMode()); + throw new AssertionError("Unknown mode: " + accessMode.getMode()); } if (accessKey == null && isForStory) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/AutomaticSessionResetJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/AutomaticSessionResetJob.java index 211afb27ce..37816635b7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/AutomaticSessionResetJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/AutomaticSessionResetJob.java @@ -6,7 +6,9 @@ import androidx.annotation.Nullable; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.crypto.SealedSenderAccessUtil; import org.thoughtcrime.securesms.database.MessageTable; +import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; import org.thoughtcrime.securesms.database.SignalDatabase; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.database.model.databaseprotos.DeviceLastResetTime; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.jobmanager.Job; @@ -14,7 +16,6 @@ import org.thoughtcrime.securesms.jobmanager.JsonJobData; import org.thoughtcrime.securesms.jobmanager.impl.DecryptionsDrainedConstraint; import org.thoughtcrime.securesms.jobmanager.impl.SealedSenderConstraint; import org.thoughtcrime.securesms.notifications.v2.ConversationId; -import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.util.RemoteConfig; @@ -129,15 +130,15 @@ public class AutomaticSessionResetJob extends BaseJob { } private void sendNullMessage() throws IOException { - Recipient recipient = Recipient.resolved(recipientId); + RecipientRecord recipient = SignalDatabase.recipients().getRecord(recipientId); - if (recipient.isUnregistered()) { + if (recipient.getRegistered() == RegisteredState.NOT_REGISTERED) { Log.w(TAG, recipient.getId() + " not registered!"); return; } SignalServiceMessageSender messageSender = AppDependencies.getSignalServiceMessageSender(); - SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient); + SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(recipient); try { messageSender.sendNullMessage(address, SealedSenderAccessUtil.getSealedSenderAccessFor(recipient)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/CallLinkPeekJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/CallLinkPeekJob.kt index 44617e9754..6a7e319095 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/CallLinkPeekJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/CallLinkPeekJob.kt @@ -6,11 +6,11 @@ package org.thoughtcrime.securesms.jobs import org.signal.core.util.logging.Log +import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.dependencies.AppDependencies import org.thoughtcrime.securesms.jobmanager.Job import org.thoughtcrime.securesms.jobmanager.JsonJobData import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint -import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import java.util.concurrent.TimeUnit @@ -45,8 +45,8 @@ internal class CallLinkPeekJob private constructor( ) override fun onRun() { - val recipient = Recipient.resolved(callLinkRecipientId) - if (!recipient.isCallLink) { + val recipient = SignalDatabase.recipients.getRecord(callLinkRecipientId) + if (recipient.callLinkRoomId == null) { Log.w(TAG, "Recipient was not a call link. Ignoring.") return } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/CreateReleaseChannelJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/CreateReleaseChannelJob.kt index a2ac1f0863..667852f981 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/CreateReleaseChannelJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/CreateReleaseChannelJob.kt @@ -12,7 +12,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.profiles.AvatarHelper import org.thoughtcrime.securesms.profiles.ProfileName import org.thoughtcrime.securesms.providers.BlobProvider -import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.transport.RetryLaterException import java.util.concurrent.CountDownLatch @@ -52,14 +51,20 @@ class CreateReleaseChannelJob private constructor(parameters: Parameters) : Base if (SignalStore.releaseChannel.releaseChannelRecipientId != null) { val existingId = SignalStore.releaseChannel.releaseChannelRecipientId!! - val recipient = Recipient.resolved(existingId) + val recipient = SignalDatabase.recipients.getRecord(existingId) - if (recipient.hasServiceId || recipient.hasE164 || recipient.isGroup || recipient.isDistributionList || recipient.isCallLink) { - Log.w(TAG, "Release channel recipient $existingId is not a valid release channel recipient (hasServiceId: ${recipient.hasServiceId}, hasE164: ${recipient.hasE164}, isGroup: ${recipient.isGroup}, isDistributionList: ${recipient.isDistributionList}, isCallLink: ${recipient.isCallLink}). Clearing and recreating.") + val hasServiceId = recipient.serviceId != null + val hasE164 = recipient.e164 != null + val isGroup = recipient.groupId != null + val isDistributionList = recipient.distributionListId != null + val isCallLink = recipient.callLinkRoomId != null + + if (hasServiceId || hasE164 || isGroup || isDistributionList || isCallLink) { + Log.w(TAG, "Release channel recipient $existingId is not a valid release channel recipient (hasServiceId: $hasServiceId, hasE164: $hasE164, isGroup: $isGroup, isDistributionList: $isDistributionList, isCallLink: $isCallLink). Clearing and recreating.") SignalStore.releaseChannel.clearReleaseChannelRecipientId() } else { Log.i(TAG, "Already created Release Channel recipient $existingId") - if (recipient.profileAvatar.isNullOrEmpty() || !SignalStore.releaseChannel.hasUpdatedAvatar) { + if (recipient.signalProfileAvatar.isNullOrEmpty() || !SignalStore.releaseChannel.hasUpdatedAvatar) { SignalStore.releaseChannel.hasUpdatedAvatar = true setAvatar(recipient.id) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceMessageRequestResponseJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceMessageRequestResponseJob.java index 9e4304d888..3531d6b853 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceMessageRequestResponseJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceMessageRequestResponseJob.java @@ -5,6 +5,9 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.signal.core.util.logging.Log; +import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; +import org.thoughtcrime.securesms.database.SignalDatabase; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JsonJobData; @@ -14,7 +17,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.net.NotPushRegisteredException; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; @@ -106,19 +108,19 @@ public class MultiDeviceMessageRequestResponseJob extends BaseJob { } SignalServiceMessageSender messageSender = AppDependencies.getSignalServiceMessageSender(); - Recipient recipient = Recipient.resolved(threadRecipient); + RecipientRecord recipient = SignalDatabase.recipients().getRecord(threadRecipient); - if (!recipient.isGroup() && !recipient.getHasServiceId()) { + if (recipient.getGroupId() == null && recipient.getServiceId() == null) { Log.i(TAG, "Queued for non-group recipient without ServiceId"); return; } MessageRequestResponseMessage response; - if (recipient.isGroup()) { - response = MessageRequestResponseMessage.forGroup(recipient.getGroupId().get().getDecodedId(), localToRemoteType(type)); - } else if (recipient.isMaybeRegistered()) { - response = MessageRequestResponseMessage.forIndividual(RecipientUtil.getOrFetchServiceId(context, recipient), localToRemoteType(type)); + if (recipient.getGroupId() != null) { + response = MessageRequestResponseMessage.forGroup(recipient.getGroupId().getDecodedId(), localToRemoteType(type)); + } else if (recipient.getRegistered() != RegisteredState.NOT_REGISTERED) { + response = MessageRequestResponseMessage.forIndividual(recipient.getServiceId(), localToRemoteType(type)); } else { response = null; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceOutgoingPaymentSyncJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceOutgoingPaymentSyncJob.java index d6170aafe3..e403c2cacf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceOutgoingPaymentSyncJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceOutgoingPaymentSyncJob.java @@ -15,7 +15,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.net.NotPushRegisteredException; import org.thoughtcrime.securesms.payments.proto.PaymentMetaData; import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.whispersystems.signalservice.api.messages.multidevice.OutgoingPaymentMessage; import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.signal.core.models.ServiceId; @@ -94,7 +93,7 @@ public final class MultiDeviceOutgoingPaymentSyncJob extends BaseJob { Optional uuid; if (!defrag && payment.getPayee().hasRecipientId()) { - uuid = Optional.of(RecipientUtil.getOrFetchServiceId(context, Recipient.resolved(payment.getPayee().requireRecipientId()))); + uuid = Optional.ofNullable(SignalDatabase.recipients().getRecord(payment.getPayee().requireRecipientId()).getServiceId()); } else { uuid = Optional.empty(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java index 2aa09d495e..22f35046f7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java @@ -10,6 +10,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.signal.core.util.ListUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.database.MessageTable.SyncMessageId; +import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; +import org.thoughtcrime.securesms.database.SignalDatabase; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JobManager; @@ -20,7 +23,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.net.NotPushRegisteredException; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.signal.core.util.JsonUtils; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; @@ -117,9 +119,9 @@ public class MultiDeviceReadUpdateJob extends BaseJob { List readMessages = new LinkedList<>(); for (SerializableSyncMessageId messageId : messageIds) { - Recipient recipient = Recipient.resolved(RecipientId.from(messageId.recipientId)); - if (!recipient.isGroup() && !recipient.isDistributionList() && recipient.isMaybeRegistered() && (recipient.getHasServiceId() || recipient.getHasE164())) { - ServiceId senderAci = RecipientUtil.getOrFetchServiceId(context, recipient); + RecipientRecord recipient = SignalDatabase.recipients().getRecord(RecipientId.from(messageId.recipientId)); + if (recipient.getGroupId() == null && recipient.getDistributionListId() == null && recipient.getRegistered() != RegisteredState.NOT_REGISTERED && (recipient.getServiceId() != null || recipient.getE164() != null)) { + ServiceId senderAci = recipient.getServiceId(); if (senderAci instanceof ServiceId.ACI) { readMessages.add(new ReadMessage((ServiceId.ACI) senderAci, messageId.timestamp)); } else { diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewOnceOpenJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewOnceOpenJob.java index 81da522fa8..104b294eed 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewOnceOpenJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewOnceOpenJob.java @@ -7,6 +7,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.database.MessageTable.SyncMessageId; +import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; +import org.thoughtcrime.securesms.database.SignalDatabase; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JsonJobData; @@ -16,7 +19,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.net.NotPushRegisteredException; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.signal.core.util.JsonUtils; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.signalservice.api.SignalServiceMessageSender; @@ -85,14 +87,14 @@ public class MultiDeviceViewOnceOpenJob extends BaseJob { } SignalServiceMessageSender messageSender = AppDependencies.getSignalServiceMessageSender(); - Recipient recipient = Recipient.resolved(RecipientId.from(messageId.recipientId)); + RecipientRecord recipient = SignalDatabase.recipients().getRecord(RecipientId.from(messageId.recipientId)); - if (recipient.isUnregistered()) { + if (recipient.getRegistered() == RegisteredState.NOT_REGISTERED || recipient.getServiceId() == null) { Log.w(TAG, recipient.getId() + " not registered!"); return; } - ViewOnceOpenMessage openMessage = new ViewOnceOpenMessage(RecipientUtil.getOrFetchServiceId(context, recipient), messageId.timestamp); + ViewOnceOpenMessage openMessage = new ViewOnceOpenMessage(recipient.getServiceId(), messageId.timestamp); messageSender.sendSyncMessage(SignalServiceSyncMessage.forViewOnceOpen(openMessage)); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewedUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewedUpdateJob.java index f021e11352..02b1756016 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewedUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceViewedUpdateJob.java @@ -10,6 +10,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.signal.core.util.ListUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.database.MessageTable.SyncMessageId; +import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; +import org.thoughtcrime.securesms.database.SignalDatabase; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JobManager; @@ -20,7 +23,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.net.NotPushRegisteredException; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.signal.core.util.JsonUtils; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.signalservice.api.SignalServiceMessageSender; @@ -117,9 +119,9 @@ public class MultiDeviceViewedUpdateJob extends BaseJob { List viewedMessages = new LinkedList<>(); for (SerializableSyncMessageId messageId : messageIds) { - Recipient recipient = Recipient.resolved(RecipientId.from(messageId.recipientId)); - if (!recipient.isGroup() && recipient.isMaybeRegistered()) { - viewedMessages.add(new ViewedMessage(RecipientUtil.getOrFetchServiceId(context, recipient), messageId.timestamp)); + RecipientRecord recipient = SignalDatabase.recipients().getRecord(RecipientId.from(messageId.recipientId)); + if (recipient.getGroupId() == null && recipient.getRegistered() != RegisteredState.NOT_REGISTERED && recipient.getServiceId() != null) { + viewedMessages.add(new ViewedMessage(recipient.getServiceId(), messageId.timestamp)); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/NullMessageSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/NullMessageSendJob.java index 2f7564e42f..f643f67bff 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/NullMessageSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/NullMessageSendJob.java @@ -5,12 +5,14 @@ import androidx.annotation.Nullable; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.crypto.SealedSenderAccessUtil; +import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; +import org.thoughtcrime.securesms.database.SignalDatabase; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JsonJobData; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.thoughtcrime.securesms.jobmanager.impl.SealedSenderConstraint; -import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.whispersystems.signalservice.api.SignalServiceMessageSender; @@ -61,19 +63,19 @@ public class NullMessageSendJob extends BaseJob { @Override protected void onRun() throws Exception { - Recipient recipient = Recipient.resolved(recipientId); + RecipientRecord recipient = SignalDatabase.recipients().getRecord(recipientId); - if (recipient.isGroup()) { + if (recipient.getGroupId() != null) { Log.w(TAG, "Groups are not supported!"); return; } - if (recipient.isUnregistered()) { + if (recipient.getRegistered() == RegisteredState.NOT_REGISTERED) { Log.w(TAG, recipient.getId() + " not registered!"); } SignalServiceMessageSender messageSender = AppDependencies.getSignalServiceMessageSender(); - SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient); + SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(recipient); try { messageSender.sendNullMessage(address, SealedSenderAccessUtil.getSealedSenderAccessFor(recipient)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.kt index 505b40c7b2..cda92a1761 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.kt @@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.contactshare.ContactModelMapper import org.thoughtcrime.securesms.crypto.ProfileKeyUtil import org.thoughtcrime.securesms.database.MessageTable import org.thoughtcrime.securesms.database.NoSuchMessageException +import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.database.SignalDatabase.Companion.messages import org.thoughtcrime.securesms.database.SignalDatabase.Companion.stickers @@ -44,9 +45,7 @@ import org.thoughtcrime.securesms.net.NotPushRegisteredException import org.thoughtcrime.securesms.notifications.v2.ConversationId.Companion.forConversation import org.thoughtcrime.securesms.notifications.v2.ConversationId.Companion.fromThreadAndReply import org.thoughtcrime.securesms.recipients.Recipient -import org.thoughtcrime.securesms.recipients.Recipient.Companion.resolved import org.thoughtcrime.securesms.recipients.Recipient.Companion.self -import org.thoughtcrime.securesms.recipients.RecipientUtil import org.thoughtcrime.securesms.transport.RetryLaterException import org.thoughtcrime.securesms.transport.UndeliverableMessageException import org.thoughtcrime.securesms.util.MediaUtil @@ -362,25 +361,18 @@ abstract class PushSendJob protected constructor(parameters: Parameters) : BaseJ ) } - val quoteAuthorRecipient = resolved(quoteAuthor) + val quoteAuthorRecord = SignalDatabase.recipients.getRecord(quoteAuthor) + val author: ServiceId? = if (quoteAuthorRecord.registered != RegisteredState.NOT_REGISTERED) { + quoteAuthorRecord.serviceId + } else { + quoteAuthorRecord.aci + } - if (quoteAuthorRecipient.isMaybeRegistered) { - return Optional.of( + return if (author != null) { + Optional.of( SignalServiceDataMessage.Quote( id = quoteId, - author = RecipientUtil.getOrFetchServiceId(context, quoteAuthorRecipient), - text = quoteBody, - attachments = quoteAttachments, - mentions = quoteMentions, - type = quoteType.dataMessageType, - bodyRanges = bodyRanges - ) - ) - } else if (quoteAuthorRecipient.hasServiceId) { - return Optional.of( - SignalServiceDataMessage.Quote( - id = quoteId, - author = quoteAuthorRecipient.requireAci(), + author = author, text = quoteBody, attachments = quoteAttachments, mentions = quoteMentions, @@ -389,7 +381,7 @@ abstract class PushSendJob protected constructor(parameters: Parameters) : BaseJ ) ) } else { - return Optional.empty() + Optional.empty() } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ReactionSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/ReactionSendJob.java index 0c8e4e0949..67680ebcf5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ReactionSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ReactionSendJob.java @@ -230,7 +230,7 @@ public class ReactionSendJob extends BaseJob { { SignalServiceDataMessage.Builder dataMessageBuilder = SignalServiceDataMessage.newBuilder() .withTimestamp(System.currentTimeMillis()) - .withReaction(buildReaction(context, reaction, remove, targetAuthor, targetSentTimestamp)); + .withReaction(buildReaction(reaction, remove, targetAuthor, targetSentTimestamp)); if (conversationRecipient.isGroup()) { GroupUtil.setDataMessageGroupContext(context, dataMessageBuilder, conversationRecipient.requireGroupId().requirePush()); @@ -265,16 +265,14 @@ public class ReactionSendJob extends BaseJob { return groupResult.completed; } - private static SignalServiceDataMessage.Reaction buildReaction(@NonNull Context context, - @NonNull ReactionRecord reaction, + private static SignalServiceDataMessage.Reaction buildReaction(@NonNull ReactionRecord reaction, boolean remove, @NonNull Recipient targetAuthor, long targetSentTimestamp) - throws IOException { return new SignalServiceDataMessage.Reaction(reaction.getEmoji(), remove, - RecipientUtil.getOrFetchServiceId(context, targetAuthor), + targetAuthor.requireServiceId(), targetSentTimestamp); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ReportSpamJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/ReportSpamJob.java index 37a3877c28..ca2afa9176 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ReportSpamJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ReportSpamJob.java @@ -7,6 +7,7 @@ import org.signal.core.util.Base64; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.database.MessageTable.ReportSpamData; import org.thoughtcrime.securesms.database.SignalDatabase; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JsonJobData; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; @@ -21,7 +22,6 @@ import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedExcept import java.io.IOException; import java.util.List; -import java.util.Optional; import java.util.concurrent.TimeUnit; /** @@ -95,11 +95,11 @@ public class ReportSpamJob extends BaseJob { int count = 0; for (ReportSpamData data : reportSpamData) { - RecipientId recipientId = data.getRecipientId(); - Recipient recipient = Recipient.resolved(recipientId); - Optional serviceId = recipient.getServiceId(); + RecipientId recipientId = data.getRecipientId(); + RecipientRecord recipient = SignalDatabase.recipients().getRecord(recipientId); + ServiceId serviceId = recipient.getServiceId(); - if (serviceId.isPresent() && !serviceId.get().isUnknown()) { + if (serviceId != null && !serviceId.isUnknown()) { String reportingTokenEncoded = null; byte[] reportingTokenBytes = SignalDatabase.recipients().getReportingToken(recipientId); @@ -107,7 +107,7 @@ public class ReportSpamJob extends BaseJob { reportingTokenEncoded = Base64.encodeWithPadding(reportingTokenBytes); } - NetworkResultUtil.toBasicLegacy(SignalNetwork.message().reportSpam(serviceId.get(), data.getServerGuid(), reportingTokenEncoded)); + NetworkResultUtil.toBasicLegacy(SignalNetwork.message().reportSpam(serviceId, data.getServerGuid(), reportingTokenEncoded)); count++; } else { Log.w(TAG, "Unable to report spam without an ACI for " + recipientId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ResendMessageJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/ResendMessageJob.java index 83b69e38ae..06646efb9e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ResendMessageJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ResendMessageJob.java @@ -8,9 +8,11 @@ import org.signal.core.util.logging.Log; import org.signal.libsignal.protocol.SignalProtocolAddress; import org.signal.libsignal.protocol.message.SenderKeyDistributionMessage; import org.thoughtcrime.securesms.crypto.SealedSenderAccessUtil; +import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.model.DistributionListRecord; import org.thoughtcrime.securesms.database.model.GroupRecord; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.jobmanager.Job; @@ -18,7 +20,6 @@ import org.thoughtcrime.securesms.jobmanager.JsonJobData; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.thoughtcrime.securesms.jobmanager.impl.SealedSenderConstraint; import org.thoughtcrime.securesms.keyvalue.SignalStore; -import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.whispersystems.signalservice.api.SignalServiceMessageSender; @@ -136,14 +137,14 @@ public class ResendMessageJob extends BaseJob { Log.i(TAG, "[" + sentTimestamp + " ] Resending message to " + recipientId + " (urgent: " + urgent + ", contentHint: " + contentHint.name() + ", groupId: " + groupId + ", distributionId: " + distributionId + ")"); SignalServiceMessageSender messageSender = AppDependencies.getSignalServiceMessageSender(); - Recipient recipient = Recipient.resolved(recipientId); + RecipientRecord recipient = SignalDatabase.recipients().getRecord(recipientId); - if (recipient.isUnregistered()) { + if (recipient.getRegistered() == RegisteredState.NOT_REGISTERED) { Log.w(TAG, recipient.getId() + " is unregistered!"); return; } - SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient); + SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(recipient); Content contentToSend = content; SealedSenderAccess.CreateGroupSendToken createGroupSendToken = null; @@ -189,9 +190,9 @@ public class ResendMessageJob extends BaseJob { } catch (IllegalStateException e) { Log.w(TAG, "Failed to resend content. Archiving session and trying again.", e); AppDependencies.getProtocolStore().aci().sessions().archiveSessions(recipientId, SignalServiceAddress.DEFAULT_DEVICE_ID); - AppDependencies.getProtocolStore().aci().sessions().archiveSiblingSessions(recipient.requireServiceId().toProtocolAddress(SignalServiceAddress.DEFAULT_DEVICE_ID)); + AppDependencies.getProtocolStore().aci().sessions().archiveSiblingSessions(recipient.getServiceId().toProtocolAddress(SignalServiceAddress.DEFAULT_DEVICE_ID)); AppDependencies.getProtocolStore().pni().sessions().archiveSessions(recipientId, SignalServiceAddress.DEFAULT_DEVICE_ID); - AppDependencies.getProtocolStore().pni().sessions().archiveSiblingSessions(recipient.requireServiceId().toProtocolAddress(SignalServiceAddress.DEFAULT_DEVICE_ID)); + AppDependencies.getProtocolStore().pni().sessions().archiveSiblingSessions(recipient.getServiceId().toProtocolAddress(SignalServiceAddress.DEFAULT_DEVICE_ID)); SignalDatabase.senderKeyShared().deleteAllFor(recipientId); result = messageSender.resendContent(address, access, sentTimestamp, contentToSend, contentHint, Optional.ofNullable(groupId).map(GroupId::getDecodedId), urgent); @@ -201,7 +202,7 @@ public class ResendMessageJob extends BaseJob { List addresses = result.getSuccess() .getDevices() .stream() - .map(device -> recipient.requireServiceId().toProtocolAddress(device)) + .map(device -> recipient.getServiceId().toProtocolAddress(device)) .collect(Collectors.toList()); AppDependencies.getProtocolStore().aci().markSenderKeySharedWith(distributionId, addresses); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveRemoteAnnouncementsJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveRemoteAnnouncementsJob.kt index 557ffd8743..71e9859be9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveRemoteAnnouncementsJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveRemoteAnnouncementsJob.kt @@ -181,7 +181,7 @@ class RetrieveRemoteAnnouncementsJob private constructor(private val force: Bool private fun updateReleaseNotes(announcements: List) { val values = SignalStore.releaseChannel - if (Recipient.resolved(values.releaseChannelRecipientId!!).isBlocked) { + if (SignalDatabase.recipients.getRecord(values.releaseChannelRecipientId!!).isBlocked) { Log.i(TAG, "Release channel is blocked, do not bother with updates") values.highestVersionNoteReceived = announcements.mapNotNull { it.androidMinVersion?.toIntOrNull() }.maxOrNull() ?: values.highestVersionNoteReceived return diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java index 32521be90d..dbb9c48f31 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java @@ -8,8 +8,10 @@ import org.signal.core.util.logging.Log; import org.signal.libsignal.zkgroup.groupsend.GroupSendFullToken; import org.signal.network.exceptions.PushNetworkException; import org.thoughtcrime.securesms.crypto.SealedSenderAccessUtil; +import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.model.MessageId; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JsonJobData; @@ -103,24 +105,24 @@ public class SendDeliveryReceiptJob extends BaseJob { } SignalServiceMessageSender messageSender = AppDependencies.getSignalServiceMessageSender(); - Recipient recipient = Recipient.resolved(recipientId); + RecipientRecord recipient = SignalDatabase.recipients().getRecord(recipientId); - if (recipient.isSelf()) { + if (recipient.getId().equals(Recipient.self().getId())) { Log.i(TAG, "Not sending to self, abort"); return; } - if (recipient.isUnregistered()) { + if (recipient.getRegistered() == RegisteredState.NOT_REGISTERED) { Log.w(TAG, recipient.getId() + " is unregistered!"); return; } - if (!recipient.getHasServiceId() && !recipient.getHasE164()) { + if (recipient.getServiceId() == null && recipient.getE164() == null) { Log.w(TAG, "No serviceId or e164!"); return; } - SignalServiceAddress remoteAddress = RecipientUtil.toSignalServiceAddress(context, recipient); + SignalServiceAddress remoteAddress = RecipientUtil.toSignalServiceAddress(recipient); SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.DELIVERY, Collections.singletonList(messageSentTimestamp), timestamp); @@ -128,7 +130,7 @@ public class SendDeliveryReceiptJob extends BaseJob { SendMessageResult result = ReceiptSender.sendWithSessionRepair(recipientId, () -> messageSender.sendReceipt(remoteAddress, SealedSenderAccessUtil.getSealedSenderAccessFor(recipient, this::getGroupSendFullToken), receiptMessage, - recipient.getNeedsPniSignature())); + recipient.needsPniSignature())); if (result != null && messageId != null) { SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageId, false); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java index 2869b97fef..f49e53e332 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java @@ -9,8 +9,10 @@ import org.signal.core.util.ListUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.crypto.SealedSenderAccessUtil; import org.thoughtcrime.securesms.database.MessageTable.MarkedMessageInfo; +import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.model.MessageId; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JobManager; @@ -156,9 +158,9 @@ public class SendReadReceiptJob extends BaseJob { return; } - Recipient recipient = Recipient.resolved(recipientId); + RecipientRecord recipient = SignalDatabase.recipients().getRecord(recipientId); - if (recipient.isSelf()) { + if (recipient.getId().equals(Recipient.self().getId())) { Log.i(TAG, "Not sending to self, aborting."); } @@ -167,35 +169,35 @@ public class SendReadReceiptJob extends BaseJob { return; } - if (recipient.isGroup()) { + if (recipient.getGroupId() != null) { Log.w(TAG, "Refusing to send receipts to group"); return; } - if (recipient.isDistributionList()) { + if (recipient.getDistributionListId() != null) { Log.w(TAG, "Refusing to send receipts to distribution list"); return; } - if (recipient.isUnregistered()) { + if (recipient.getRegistered() == RegisteredState.NOT_REGISTERED) { Log.w(TAG, recipient.getId() + " not registered!"); return; } - if (!recipient.getHasServiceId() && !recipient.getHasE164()) { + if (recipient.getServiceId() == null && recipient.getE164() == null) { Log.w(TAG, "No serviceId or e164!"); return; } SignalServiceMessageSender messageSender = AppDependencies.getSignalServiceMessageSender(); - SignalServiceAddress remoteAddress = RecipientUtil.toSignalServiceAddress(context, recipient); + SignalServiceAddress remoteAddress = RecipientUtil.toSignalServiceAddress(recipient); SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.READ, messageSentTimestamps, timestamp); SendMessageResult result = ReceiptSender.sendWithSessionRepair(recipientId, () -> messageSender.sendReceipt(remoteAddress, SealedSenderAccessUtil.getSealedSenderAccessFor(recipient, () -> SignalDatabase.groups().getGroupSendFullToken(threadId, recipientId)), receiptMessage, - recipient.getNeedsPniSignature())); + recipient.needsPniSignature())); if (result != null && Util.hasItems(messageIds)) { SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds, false); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendRetryReceiptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendRetryReceiptJob.java index 9a6e03774b..0d4604a0ff 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendRetryReceiptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendRetryReceiptJob.java @@ -8,13 +8,15 @@ import org.signal.libsignal.protocol.InvalidKeyException; import org.signal.libsignal.protocol.InvalidMessageException; import org.signal.libsignal.protocol.message.DecryptionErrorMessage; import org.thoughtcrime.securesms.crypto.SealedSenderAccessUtil; +import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; +import org.thoughtcrime.securesms.database.SignalDatabase; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JsonJobData; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.thoughtcrime.securesms.jobmanager.impl.SealedSenderConstraint; -import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.whispersystems.signalservice.api.push.SignalServiceAddress; @@ -82,14 +84,14 @@ public final class SendRetryReceiptJob extends BaseJob { @Override protected void onRun() throws Exception { - Recipient recipient = Recipient.resolved(recipientId); + RecipientRecord recipient = SignalDatabase.recipients().getRecord(recipientId); - if (recipient.isUnregistered()) { + if (recipient.getRegistered() == RegisteredState.NOT_REGISTERED) { Log.w(TAG, recipient.getId() + " not registered!"); return; } - SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient); + SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(recipient); Optional group = groupId.map(GroupId::getDecodedId); Log.i(TAG, "Sending retry receipt for " + errorMessage.getTimestamp() + " to " + recipientId + ", device: " + errorMessage.getDeviceId()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendViewedReceiptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendViewedReceiptJob.java index f84f3652d9..49004b8035 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SendViewedReceiptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SendViewedReceiptJob.java @@ -10,8 +10,10 @@ import org.signal.core.util.ListUtil; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.crypto.SealedSenderAccessUtil; import org.thoughtcrime.securesms.database.MessageTable.MarkedMessageInfo; +import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.model.MessageId; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.database.model.StoryType; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.jobmanager.Job; @@ -176,9 +178,9 @@ public class SendViewedReceiptJob extends BaseJob { return; } - Recipient recipient = Recipient.resolved(recipientId); + RecipientRecord recipient = SignalDatabase.recipients().getRecord(recipientId); - if (recipient.isSelf()) { + if (recipient.getId().equals(Recipient.self().getId())) { Log.i(TAG, "Not sending view receipt to self."); return; } @@ -188,23 +190,23 @@ public class SendViewedReceiptJob extends BaseJob { return; } - if (recipient.isGroup()) { + if (recipient.getGroupId() != null) { Log.w(TAG, "Refusing to send receipts to group"); return; } - if (recipient.isUnregistered()) { + if (recipient.getRegistered() == RegisteredState.NOT_REGISTERED) { Log.w(TAG, recipient.getId() + " not registered!"); return; } - if (recipient.isReleaseNotes()) { + if (recipient.getId().equals(SignalStore.releaseChannel().getReleaseChannelRecipientId())) { Log.w(TAG, "Refusing to send receipts to release channel"); return; } SignalServiceMessageSender messageSender = AppDependencies.getSignalServiceMessageSender(); - SignalServiceAddress remoteAddress = RecipientUtil.toSignalServiceAddress(context, recipient); + SignalServiceAddress remoteAddress = RecipientUtil.toSignalServiceAddress(recipient); SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.VIEWED, messageSentTimestamps, timestamp); @@ -213,7 +215,7 @@ public class SendViewedReceiptJob extends BaseJob { SealedSenderAccessUtil.getSealedSenderAccessFor(recipient, () -> SignalDatabase.groups().getGroupSendFullToken(threadId, recipientId)), receiptMessage, - recipient.getNeedsPniSignature())); + recipient.needsPniSignature())); if (result != null && Util.hasItems(foundMessageIds)) { SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, foundMessageIds, false); diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java index 81ae8e357f..62936d2481 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java @@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.database.RecipientTable.RegisteredState; import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.ThreadTable; import org.thoughtcrime.securesms.database.model.GroupRecord; +import org.thoughtcrime.securesms.database.model.RecipientRecord; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupChangeException; @@ -43,19 +44,8 @@ public class RecipientUtil { private static final String TAG = Log.tag(RecipientUtil.class); /** - * This method will do it's best to get a {@link ServiceId} for the provided recipient. This includes performing - * a possible network request if no ServiceId is available. If the request to get a ServiceId fails or the user is - * not registered, an IOException is thrown. - */ - @WorkerThread - public static @NonNull ServiceId getOrFetchServiceId(@NonNull Context context, @NonNull Recipient recipient) throws IOException { - return toSignalServiceAddress(context, recipient).getServiceId(); - } - - /** - * This method will do it's best to craft a fully-populated {@link SignalServiceAddress} based on - * the provided recipient. This includes performing a possible network request if no UUID is - * available. If the request to get a UUID fails or the user is not registered, an IOException is thrown. + * Crafts a fully-populated {@link SignalServiceAddress} based on the provided recipient. If the recipient + * has no serviceId then they are not a valid send target and a {@link NotFoundException} is thrown. */ @WorkerThread public static @NonNull SignalServiceAddress toSignalServiceAddress(@NonNull Context context, @NonNull Recipient recipient) @@ -63,25 +53,29 @@ public class RecipientUtil { { recipient = recipient.resolve(); - if (!recipient.getServiceId().isPresent() && !recipient.getE164().isPresent()) { - throw new AssertionError(recipient.getId() + " - No UUID or phone number!"); - } - - if (!recipient.getServiceId().isPresent()) { - Log.i(TAG, recipient.getId() + " is missing a UUID..."); - RegisteredState state = ContactDiscovery.refresh(context, recipient, false); - - recipient = Recipient.resolved(recipient.getId()); - Log.i(TAG, "Successfully performed a UUID fetch for " + recipient.getId() + ". Registered: " + state); - } - if (recipient.getHasServiceId()) { - return new SignalServiceAddress(recipient.requireServiceId(), Optional.ofNullable(recipient.resolve().getE164().orElse(null))); + return new SignalServiceAddress(recipient.requireServiceId(), recipient.getE164()); } else { throw new NotFoundException(recipient.getId() + " is not registered!"); } } + /** + * Crafts a fully-populated {@link SignalServiceAddress} based on the provided record. If the record has + * no serviceId then they are not a valid send target and a {@link NotFoundException} is thrown. + */ + public static @NonNull SignalServiceAddress toSignalServiceAddress(@NonNull RecipientRecord record) + throws IOException + { + ServiceId serviceId = record.getServiceId(); + + if (serviceId != null) { + return new SignalServiceAddress(serviceId, Optional.ofNullable(record.getE164())); + } else { + throw new NotFoundException(record.getId() + " is not registered!"); + } + } + public static @NonNull List toSignalServiceAddressesFromResolved(@NonNull Context context, @NonNull List recipients) throws IOException {