Reduce Recipient usage in some jobs.

This commit is contained in:
Greyson Parrelli 2026-06-06 20:11:50 -04:00 committed by Cody Henthorne
parent 15e7b30fa1
commit b4cf59f9c2
20 changed files with 190 additions and 132 deletions

View File

@ -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<RecipientId, Optional<UnidentifiedAccess>> getAccessMapFor(@NonNull List<Recipient> recipients, boolean isForStory) {
List<Optional<UnidentifiedAccess>> 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) {

View File

@ -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));

View File

@ -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
}

View File

@ -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)
}

View File

@ -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;
}

View File

@ -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<ServiceId> 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();
}

View File

@ -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<ReadMessage> 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 {

View File

@ -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));
}

View File

@ -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<ViewedMessage> 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));
}
}

View File

@ -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));

View File

@ -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()
}
}

View File

@ -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);
}

View File

@ -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> 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);

View File

@ -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<SignalProtocolAddress> 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);

View File

@ -181,7 +181,7 @@ class RetrieveRemoteAnnouncementsJob private constructor(private val force: Bool
private fun updateReleaseNotes(announcements: List<ReleaseNote>) {
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

View File

@ -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);

View File

@ -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);

View File

@ -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<byte[]> group = groupId.map(GroupId::getDecodedId);
Log.i(TAG, "Sending retry receipt for " + errorMessage.getTimestamp() + " to " + recipientId + ", device: " + errorMessage.getDeviceId());

View File

@ -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);

View File

@ -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<SignalServiceAddress> toSignalServiceAddressesFromResolved(@NonNull Context context, @NonNull List<Recipient> recipients)
throws IOException
{