Reduce recipient resolves in MessageContentProcessor.

This commit is contained in:
Greyson Parrelli 2021-07-07 13:11:31 -04:00 committed by Alex Hart
parent ae4167ddae
commit 1bb87834d8

View file

@ -197,19 +197,23 @@ public final class MessageContentProcessor {
Optional<Long> optionalSmsMessageId = smsMessageId > 0 ? Optional.of(smsMessageId) : Optional.absent(); Optional<Long> optionalSmsMessageId = smsMessageId > 0 ? Optional.of(smsMessageId) : Optional.absent();
if (messageState == MessageState.DECRYPTED_OK) { if (messageState == MessageState.DECRYPTED_OK) {
handleMessage(content, timestamp, optionalSmsMessageId);
if (content != null) { if (content != null) {
Recipient senderRecipient = Recipient.externalHighTrustPush(context, content.getSender());
handleMessage(content, timestamp, senderRecipient, optionalSmsMessageId);
Optional<List<SignalServiceContent>> earlyContent = ApplicationDependencies.getEarlyMessageCache() Optional<List<SignalServiceContent>> earlyContent = ApplicationDependencies.getEarlyMessageCache()
.retrieve(Recipient.externalPush(context, content.getSender()).getId(), .retrieve(senderRecipient.getId(), content.getTimestamp());
content.getTimestamp());
if (earlyContent.isPresent()) { if (earlyContent.isPresent()) {
log(String.valueOf(content.getTimestamp()), "Found " + earlyContent.get().size() + " dependent item(s) that were retrieved earlier. Processing."); log(String.valueOf(content.getTimestamp()), "Found " + earlyContent.get().size() + " dependent item(s) that were retrieved earlier. Processing.");
for (SignalServiceContent earlyItem : earlyContent.get()) { for (SignalServiceContent earlyItem : earlyContent.get()) {
handleMessage(earlyItem, timestamp, Optional.absent()); handleMessage(earlyItem, timestamp, senderRecipient, Optional.absent());
} }
} }
} else {
warn("null", "Null content. Ignoring message.");
} }
} else if (exceptionMetadata != null) { } else if (exceptionMetadata != null) {
handleExceptionMessage(messageState, exceptionMetadata, timestamp, optionalSmsMessageId); handleExceptionMessage(messageState, exceptionMetadata, timestamp, optionalSmsMessageId);
@ -220,20 +224,19 @@ public final class MessageContentProcessor {
} }
} }
private void handleMessage(@Nullable SignalServiceContent content, long timestamp, @NonNull Optional<Long> smsMessageId) private void handleMessage(@NonNull SignalServiceContent content, long timestamp, @NonNull Recipient senderRecipient, @NonNull Optional<Long> smsMessageId)
throws IOException, GroupChangeBusyException throws IOException, GroupChangeBusyException
{ {
try { try {
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context); Recipient threadRecipient = getMessageDestination(content);
if (content == null || shouldIgnore(content)) { if (shouldIgnore(content, senderRecipient, threadRecipient)) {
log(content != null ? String.valueOf(content.getTimestamp()) : "null", "Ignoring message."); log(content.getTimestamp(), "Ignoring message.");
return; return;
} }
RecipientId senderId = RecipientId.fromHighTrust(content.getSender()); PendingRetryReceiptModel pending = ApplicationDependencies.getPendingRetryReceiptCache().get(senderRecipient.getId(), content.getTimestamp());
PendingRetryReceiptModel pending = ApplicationDependencies.getPendingRetryReceiptCache().get(senderId, content.getTimestamp()); long receivedTime = handlePendingRetry(pending, content, threadRecipient);
long receivedTime = handlePendingRetry(pending, content);
log(String.valueOf(content.getTimestamp()), "Beginning message processing."); log(String.valueOf(content.getTimestamp()), "Beginning message processing.");
@ -242,13 +245,14 @@ public final class MessageContentProcessor {
} }
if (content.getDataMessage().isPresent()) { if (content.getDataMessage().isPresent()) {
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
SignalServiceDataMessage message = content.getDataMessage().get(); SignalServiceDataMessage message = content.getDataMessage().get();
boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent() || message.getPreviews().isPresent() || message.getSticker().isPresent() || message.getMentions().isPresent(); boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent() || message.getPreviews().isPresent() || message.getSticker().isPresent() || message.getMentions().isPresent();
Optional<GroupId> groupId = GroupUtil.idFromGroupContext(message.getGroupContext()); Optional<GroupId> groupId = GroupUtil.idFromGroupContext(message.getGroupContext());
boolean isGv2Message = groupId.isPresent() && groupId.get().isV2(); boolean isGv2Message = groupId.isPresent() && groupId.get().isV2();
if (isGv2Message) { if (isGv2Message) {
if (handleGv2PreProcessing(groupId.orNull().requireV2(), content, content.getDataMessage().get().getGroupContext().get().getGroupV2().get())) { if (handleGv2PreProcessing(groupId.orNull().requireV2(), content, content.getDataMessage().get().getGroupContext().get().getGroupV2().get(), senderRecipient)) {
return; return;
} }
} }
@ -256,41 +260,39 @@ public final class MessageContentProcessor {
MessageId messageId = null; MessageId messageId = null;
if (isInvalidMessage(message)) handleInvalidMessage(content.getSender(), content.getSenderDevice(), groupId, content.getTimestamp(), smsMessageId); if (isInvalidMessage(message)) handleInvalidMessage(content.getSender(), content.getSenderDevice(), groupId, content.getTimestamp(), smsMessageId);
else if (message.isEndSession()) messageId = handleEndSessionMessage(content, smsMessageId); else if (message.isEndSession()) messageId = handleEndSessionMessage(content, smsMessageId, senderRecipient);
else if (message.isGroupV1Update()) handleGroupV1Message(content, message, smsMessageId, groupId.get().requireV1(), receivedTime); else if (message.isGroupV1Update()) handleGroupV1Message(content, message, smsMessageId, groupId.get().requireV1(), senderRecipient, threadRecipient, receivedTime);
else if (message.isExpirationUpdate()) messageId = handleExpirationUpdate(content, message, smsMessageId, groupId, receivedTime); else if (message.isExpirationUpdate()) messageId = handleExpirationUpdate(content, message, smsMessageId, groupId, senderRecipient, threadRecipient, receivedTime);
else if (message.getReaction().isPresent()) messageId = handleReaction(content, message); else if (message.getReaction().isPresent()) messageId = handleReaction(content, message, senderRecipient);
else if (message.getRemoteDelete().isPresent()) messageId = handleRemoteDelete(content, message); else if (message.getRemoteDelete().isPresent()) messageId = handleRemoteDelete(content, message, senderRecipient);
else if (message.getPayment().isPresent()) handlePayment(content, message); else if (message.getPayment().isPresent()) handlePayment(content, message, senderRecipient);
else if (isMediaMessage) messageId = handleMediaMessage(content, message, smsMessageId, receivedTime); else if (isMediaMessage) messageId = handleMediaMessage(content, message, smsMessageId, senderRecipient, threadRecipient, receivedTime);
else if (message.getBody().isPresent()) messageId = handleTextMessage(content, message, smsMessageId, groupId, receivedTime); else if (message.getBody().isPresent()) messageId = handleTextMessage(content, message, smsMessageId, groupId, senderRecipient, threadRecipient, receivedTime);
else if (Build.VERSION.SDK_INT > 19 && message.getGroupCallUpdate().isPresent()) handleGroupCallUpdateMessage(content, message, groupId); else if (Build.VERSION.SDK_INT > 19 && message.getGroupCallUpdate().isPresent()) handleGroupCallUpdateMessage(content, message, groupId, senderRecipient);
if (groupId.isPresent() && groupDatabase.isUnknownGroup(groupId.get())) { if (groupId.isPresent() && groupDatabase.isUnknownGroup(groupId.get())) {
handleUnknownGroupMessage(content, message.getGroupContext().get()); handleUnknownGroupMessage(content, message.getGroupContext().get(), senderRecipient);
} }
if (message.getProfileKey().isPresent()) { if (message.getProfileKey().isPresent()) {
handleProfileKey(content, message.getProfileKey().get()); handleProfileKey(content, message.getProfileKey().get(), senderRecipient);
} }
if (content.isNeedsReceipt() && messageId != null) { if (content.isNeedsReceipt() && messageId != null) {
handleNeedsDeliveryReceipt(content, message, messageId); handleNeedsDeliveryReceipt(content, message, messageId);
} else if (!content.isNeedsReceipt()) { } else if (!content.isNeedsReceipt()) {
Recipient sender = getMessageDestination(content, message); if (RecipientUtil.shouldHaveProfileKey(context, threadRecipient)) {
Log.w(TAG, "Received an unsealed sender message from " + senderRecipient.getId() + ", but they should already have our profile key. Correcting.");
if (RecipientUtil.shouldHaveProfileKey(context, sender)) {
Log.w(TAG, "Received an unsealed sender message from " + sender.getId() + ", but they should already have our profile key. Correcting.");
if (groupId.isPresent() && groupId.get().isV2()) { if (groupId.isPresent() && groupId.get().isV2()) {
Log.i(TAG, "Message was to a GV2 group. Ensuring our group profile keys are up to date."); Log.i(TAG, "Message was to a GV2 group. Ensuring our group profile keys are up to date.");
ApplicationDependencies.getJobManager().startChain(new RefreshAttributesJob(false)) ApplicationDependencies.getJobManager().startChain(new RefreshAttributesJob(false))
.then(GroupV2UpdateSelfProfileKeyJob.withQueueLimits(groupId.get().requireV2())) .then(GroupV2UpdateSelfProfileKeyJob.withQueueLimits(groupId.get().requireV2()))
.enqueue(); .enqueue();
} else if (!sender.isGroup()) { } else if (!threadRecipient.isGroup()) {
Log.i(TAG, "Message was to a 1:1. Ensuring this user has our profile key."); Log.i(TAG, "Message was to a 1:1. Ensuring this user has our profile key.");
ApplicationDependencies.getJobManager().startChain(new RefreshAttributesJob(false)) ApplicationDependencies.getJobManager().startChain(new RefreshAttributesJob(false))
.then(ProfileKeySendJob.create(context, DatabaseFactory.getThreadDatabase(context).getThreadIdFor(sender), true)) .then(ProfileKeySendJob.create(context, DatabaseFactory.getThreadDatabase(context).getThreadIdFor(threadRecipient), true))
.enqueue(); .enqueue();
} }
} }
@ -300,9 +302,9 @@ public final class MessageContentProcessor {
SignalServiceSyncMessage syncMessage = content.getSyncMessage().get(); SignalServiceSyncMessage syncMessage = content.getSyncMessage().get();
if (syncMessage.getSent().isPresent()) handleSynchronizeSentMessage(content, syncMessage.getSent().get()); if (syncMessage.getSent().isPresent()) handleSynchronizeSentMessage(content, syncMessage.getSent().get(), senderRecipient);
else if (syncMessage.getRequest().isPresent()) handleSynchronizeRequestMessage(syncMessage.getRequest().get()); else if (syncMessage.getRequest().isPresent()) handleSynchronizeRequestMessage(syncMessage.getRequest().get());
else if (syncMessage.getRead().isPresent()) handleSynchronizeReadMessage(syncMessage.getRead().get(), content.getTimestamp()); else if (syncMessage.getRead().isPresent()) handleSynchronizeReadMessage(syncMessage.getRead().get(), content.getTimestamp(), senderRecipient);
else if (syncMessage.getViewed().isPresent()) handleSynchronizeViewedMessage(syncMessage.getViewed().get(), content.getTimestamp()); else if (syncMessage.getViewed().isPresent()) handleSynchronizeViewedMessage(syncMessage.getViewed().get(), content.getTimestamp());
else if (syncMessage.getViewOnceOpen().isPresent()) handleSynchronizeViewOnceOpenMessage(syncMessage.getViewOnceOpen().get(), content.getTimestamp()); else if (syncMessage.getViewOnceOpen().isPresent()) handleSynchronizeViewOnceOpenMessage(syncMessage.getViewOnceOpen().get(), content.getTimestamp());
else if (syncMessage.getVerified().isPresent()) handleSynchronizeVerifiedMessage(syncMessage.getVerified().get()); else if (syncMessage.getVerified().isPresent()) handleSynchronizeVerifiedMessage(syncMessage.getVerified().get());
@ -324,29 +326,29 @@ public final class MessageContentProcessor {
return; return;
} }
if (message.getOfferMessage().isPresent()) handleCallOfferMessage(content, message.getOfferMessage().get(), smsMessageId); if (message.getOfferMessage().isPresent()) handleCallOfferMessage(content, message.getOfferMessage().get(), smsMessageId, senderRecipient);
else if (message.getAnswerMessage().isPresent()) handleCallAnswerMessage(content, message.getAnswerMessage().get()); else if (message.getAnswerMessage().isPresent()) handleCallAnswerMessage(content, message.getAnswerMessage().get(), senderRecipient);
else if (message.getIceUpdateMessages().isPresent()) handleCallIceUpdateMessage(content, message.getIceUpdateMessages().get()); else if (message.getIceUpdateMessages().isPresent()) handleCallIceUpdateMessage(content, message.getIceUpdateMessages().get(), senderRecipient);
else if (message.getHangupMessage().isPresent()) handleCallHangupMessage(content, message.getHangupMessage().get(), smsMessageId); else if (message.getHangupMessage().isPresent()) handleCallHangupMessage(content, message.getHangupMessage().get(), smsMessageId, senderRecipient);
else if (message.getBusyMessage().isPresent()) handleCallBusyMessage(content, message.getBusyMessage().get()); else if (message.getBusyMessage().isPresent()) handleCallBusyMessage(content, message.getBusyMessage().get(), senderRecipient);
else if (message.getOpaqueMessage().isPresent()) handleCallOpaqueMessage(content, message.getOpaqueMessage().get()); else if (message.getOpaqueMessage().isPresent()) handleCallOpaqueMessage(content, message.getOpaqueMessage().get(), senderRecipient);
} else if (content.getReceiptMessage().isPresent()) { } else if (content.getReceiptMessage().isPresent()) {
SignalServiceReceiptMessage message = content.getReceiptMessage().get(); SignalServiceReceiptMessage message = content.getReceiptMessage().get();
if (message.isReadReceipt()) handleReadReceipt(content, message); if (message.isReadReceipt()) handleReadReceipt(content, message, senderRecipient);
else if (message.isDeliveryReceipt()) handleDeliveryReceipt(content, message); else if (message.isDeliveryReceipt()) handleDeliveryReceipt(content, message, senderRecipient);
else if (message.isViewedReceipt()) handleViewedReceipt(content, message); else if (message.isViewedReceipt()) handleViewedReceipt(content, message, senderRecipient);
} else if (content.getTypingMessage().isPresent()) { } else if (content.getTypingMessage().isPresent()) {
handleTypingMessage(content, content.getTypingMessage().get()); handleTypingMessage(content, content.getTypingMessage().get(), senderRecipient);
} else if (content.getDecryptionErrorMessage().isPresent()) { } else if (content.getDecryptionErrorMessage().isPresent()) {
handleRetryReceipt(content, content.getDecryptionErrorMessage().get()); handleRetryReceipt(content, content.getDecryptionErrorMessage().get(), senderRecipient);
} else if (content.getSenderKeyDistributionMessage().isPresent()) { } else if (content.getSenderKeyDistributionMessage().isPresent()) {
// Already handled, here in order to prevent unrecognized message log // Already handled, here in order to prevent unrecognized message log
} else { } else {
warn(String.valueOf(content.getTimestamp()), "Got unrecognized message!"); warn(String.valueOf(content.getTimestamp()), "Got unrecognized message!");
} }
resetRecipientToPush(Recipient.externalPush(context, content.getSender())); resetRecipientToPush(senderRecipient);
if (pending != null) { if (pending != null) {
warn(content.getTimestamp(), "Pending retry was processed. Deleting."); warn(content.getTimestamp(), "Pending retry was processed. Deleting.");
@ -360,14 +362,13 @@ public final class MessageContentProcessor {
} }
} }
private long handlePendingRetry(PendingRetryReceiptModel pending, SignalServiceContent content) throws BadGroupIdException { private long handlePendingRetry(@Nullable PendingRetryReceiptModel pending, @NonNull SignalServiceContent content, @NonNull Recipient destination) throws BadGroupIdException {
long receivedTime = System.currentTimeMillis(); long receivedTime = System.currentTimeMillis();
if (pending != null) { if (pending != null) {
warn(content.getTimestamp(), "Incoming message matches a pending retry we were expecting."); warn(content.getTimestamp(), "Incoming message matches a pending retry we were expecting.");
Recipient destination = getMessageDestination(content); Long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(destination.getId());
Long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(destination.getId());
if (threadId != null) { if (threadId != null) {
ThreadDatabase.ConversationMetadata metadata = DatabaseFactory.getThreadDatabase(context).getConversationMetadata(threadId); ThreadDatabase.ConversationMetadata metadata = DatabaseFactory.getThreadDatabase(context).getConversationMetadata(threadId);
@ -387,32 +388,31 @@ public final class MessageContentProcessor {
return receivedTime; return receivedTime;
} }
private void handlePayment(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) { private void handlePayment(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message, @NonNull Recipient senderRecipient) {
if (!message.getPayment().isPresent()) { if (!message.getPayment().isPresent()) {
throw new AssertionError(); throw new AssertionError();
} }
if (!message.getPayment().get().getPaymentNotification().isPresent()) { if (!message.getPayment().get().getPaymentNotification().isPresent()) {
Log.w(TAG, "Ignoring payment message without notification"); warn(content.getTimestamp(), "Ignoring payment message without notification");
return; return;
} }
SignalServiceDataMessage.PaymentNotification paymentNotification = message.getPayment().get().getPaymentNotification().get(); SignalServiceDataMessage.PaymentNotification paymentNotification = message.getPayment().get().getPaymentNotification().get();
PaymentDatabase paymentDatabase = DatabaseFactory.getPaymentDatabase(context); PaymentDatabase paymentDatabase = DatabaseFactory.getPaymentDatabase(context);
UUID uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
Recipient recipient = Recipient.externalHighTrustPush(context, content.getSender()); String queue = "Payment_" + PushProcessMessageJob.getQueueName(senderRecipient.getId());
String queue = "Payment_" + PushProcessMessageJob.getQueueName(recipient.getId());
try { try {
paymentDatabase.createIncomingPayment(uuid, paymentDatabase.createIncomingPayment(uuid,
recipient.getId(), senderRecipient.getId(),
message.getTimestamp(), message.getTimestamp(),
paymentNotification.getNote(), paymentNotification.getNote(),
Money.MobileCoin.ZERO, Money.MobileCoin.ZERO,
Money.MobileCoin.ZERO, Money.MobileCoin.ZERO,
paymentNotification.getReceipt()); paymentNotification.getReceipt());
} catch (PaymentDatabase.PublicKeyConflictException e) { } catch (PaymentDatabase.PublicKeyConflictException e) {
Log.w(TAG, "Ignoring payment with public key already in database"); warn(content.getTimestamp(), "Ignoring payment with public key already in database");
return; return;
} }
@ -425,7 +425,7 @@ public final class MessageContentProcessor {
/** /**
* @return True if the content should be ignored, otherwise false. * @return True if the content should be ignored, otherwise false.
*/ */
private boolean handleGv2PreProcessing(GroupId.V2 groupId, SignalServiceContent content, SignalServiceGroupV2 groupV2) private boolean handleGv2PreProcessing(@NonNull GroupId.V2 groupId, @NonNull SignalServiceContent content, @NonNull SignalServiceGroupV2 groupV2, @NonNull Recipient senderRecipient)
throws IOException, GroupChangeBusyException throws IOException, GroupChangeBusyException
{ {
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context); GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
@ -440,8 +440,7 @@ public final class MessageContentProcessor {
return true; return true;
} }
Recipient sender = Recipient.externalPush(context, content.getSender()); if (!groupDatabase.isCurrentMember(groupId, senderRecipient.getId())) {
if (!groupDatabase.isCurrentMember(groupId, sender.getId())) {
log(String.valueOf(content.getTimestamp()), "Ignoring GV2 message from member not in group " + groupId); log(String.valueOf(content.getTimestamp()), "Ignoring GV2 message from member not in group " + groupId);
return true; return true;
} }
@ -516,7 +515,7 @@ public final class MessageContentProcessor {
case CORRUPT_MESSAGE: case CORRUPT_MESSAGE:
case NO_SESSION: case NO_SESSION:
warn(String.valueOf(timestamp), "Discovered old enqueued bad encrypted message. Scheduling reset."); warn(String.valueOf(timestamp), "Discovered old enqueued bad encrypted message. Scheduling reset.");
ApplicationDependencies.getJobManager().add(new AutomaticSessionResetJob(Recipient.external(context, e.sender).getId(), e.senderDevice, timestamp)); ApplicationDependencies.getJobManager().add(new AutomaticSessionResetJob(sender.getId(), e.senderDevice, timestamp));
break; break;
default: default:
@ -526,7 +525,8 @@ public final class MessageContentProcessor {
private void handleCallOfferMessage(@NonNull SignalServiceContent content, private void handleCallOfferMessage(@NonNull SignalServiceContent content,
@NonNull OfferMessage message, @NonNull OfferMessage message,
@NonNull Optional<Long> smsMessageId) @NonNull Optional<Long> smsMessageId,
@NonNull Recipient senderRecipient)
{ {
log(String.valueOf(content.getTimestamp()), "handleCallOfferMessage..."); log(String.valueOf(content.getTimestamp()), "handleCallOfferMessage...");
@ -534,9 +534,8 @@ public final class MessageContentProcessor {
MessageDatabase database = DatabaseFactory.getSmsDatabase(context); MessageDatabase database = DatabaseFactory.getSmsDatabase(context);
database.markAsMissedCall(smsMessageId.get(), message.getType() == OfferMessage.Type.VIDEO_CALL); database.markAsMissedCall(smsMessageId.get(), message.getType() == OfferMessage.Type.VIDEO_CALL);
} else { } else {
Recipient recipient = Recipient.externalHighTrustPush(context, content.getSender()); RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
RemotePeer remotePeer = new RemotePeer(recipient.getId()); byte[] remoteIdentityKey = DatabaseFactory.getIdentityDatabase(context).getIdentity(senderRecipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull();
byte[] remoteIdentityKey = DatabaseFactory.getIdentityDatabase(context).getIdentity(recipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull();
ApplicationDependencies.getSignalCallManager() ApplicationDependencies.getSignalCallManager()
.receivedOffer(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice()), .receivedOffer(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice()),
@ -549,12 +548,12 @@ public final class MessageContentProcessor {
} }
private void handleCallAnswerMessage(@NonNull SignalServiceContent content, private void handleCallAnswerMessage(@NonNull SignalServiceContent content,
@NonNull AnswerMessage message) @NonNull AnswerMessage message,
@NonNull Recipient senderRecipient)
{ {
log(String.valueOf(content), "handleCallAnswerMessage..."); log(String.valueOf(content), "handleCallAnswerMessage...");
Recipient recipient = Recipient.externalHighTrustPush(context, content.getSender()); RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
RemotePeer remotePeer = new RemotePeer(recipient.getId()); byte[] remoteIdentityKey = DatabaseFactory.getIdentityDatabase(context).getIdentity(senderRecipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull();
byte[] remoteIdentityKey = DatabaseFactory.getIdentityDatabase(context).getIdentity(recipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull();
ApplicationDependencies.getSignalCallManager() ApplicationDependencies.getSignalCallManager()
.receivedAnswer(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice()), .receivedAnswer(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice()),
@ -563,7 +562,8 @@ public final class MessageContentProcessor {
} }
private void handleCallIceUpdateMessage(@NonNull SignalServiceContent content, private void handleCallIceUpdateMessage(@NonNull SignalServiceContent content,
@NonNull List<IceUpdateMessage> messages) @NonNull List<IceUpdateMessage> messages,
@NonNull Recipient senderRecipient)
{ {
log(String.valueOf(content), "handleCallIceUpdateMessage... " + messages.size()); log(String.valueOf(content), "handleCallIceUpdateMessage... " + messages.size());
@ -575,7 +575,7 @@ public final class MessageContentProcessor {
callId = iceMessage.getId(); callId = iceMessage.getId();
} }
RemotePeer remotePeer = new RemotePeer(Recipient.externalHighTrustPush(context, content.getSender()).getId()); RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
ApplicationDependencies.getSignalCallManager() ApplicationDependencies.getSignalCallManager()
.receivedIceCandidates(new WebRtcData.CallMetadata(remotePeer, new CallId(callId), content.getSenderDevice()), .receivedIceCandidates(new WebRtcData.CallMetadata(remotePeer, new CallId(callId), content.getSenderDevice()),
@ -584,13 +584,14 @@ public final class MessageContentProcessor {
private void handleCallHangupMessage(@NonNull SignalServiceContent content, private void handleCallHangupMessage(@NonNull SignalServiceContent content,
@NonNull HangupMessage message, @NonNull HangupMessage message,
@NonNull Optional<Long> smsMessageId) @NonNull Optional<Long> smsMessageId,
@NonNull Recipient senderRecipient)
{ {
log(String.valueOf(content), "handleCallHangupMessage"); log(String.valueOf(content), "handleCallHangupMessage");
if (smsMessageId.isPresent()) { if (smsMessageId.isPresent()) {
DatabaseFactory.getSmsDatabase(context).markAsMissedCall(smsMessageId.get(), false); DatabaseFactory.getSmsDatabase(context).markAsMissedCall(smsMessageId.get(), false);
} else { } else {
RemotePeer remotePeer = new RemotePeer(Recipient.externalHighTrustPush(context, content.getSender()).getId()); RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
ApplicationDependencies.getSignalCallManager() ApplicationDependencies.getSignalCallManager()
.receivedCallHangup(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice()), .receivedCallHangup(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice()),
@ -599,18 +600,20 @@ public final class MessageContentProcessor {
} }
private void handleCallBusyMessage(@NonNull SignalServiceContent content, private void handleCallBusyMessage(@NonNull SignalServiceContent content,
@NonNull BusyMessage message) @NonNull BusyMessage message,
@NonNull Recipient senderRecipient)
{ {
log(String.valueOf(content.getTimestamp()), "handleCallBusyMessage"); log(String.valueOf(content.getTimestamp()), "handleCallBusyMessage");
RemotePeer remotePeer = new RemotePeer(Recipient.externalHighTrustPush(context, content.getSender()).getId()); RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
ApplicationDependencies.getSignalCallManager() ApplicationDependencies.getSignalCallManager()
.receivedCallBusy(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice())); .receivedCallBusy(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice()));
} }
private void handleCallOpaqueMessage(@NonNull SignalServiceContent content, private void handleCallOpaqueMessage(@NonNull SignalServiceContent content,
@NonNull OpaqueMessage message) @NonNull OpaqueMessage message,
@NonNull Recipient senderRecipient)
{ {
log(String.valueOf(content.getTimestamp()), "handleCallOpaqueMessage"); log(String.valueOf(content.getTimestamp()), "handleCallOpaqueMessage");
@ -620,7 +623,7 @@ public final class MessageContentProcessor {
} }
ApplicationDependencies.getSignalCallManager() ApplicationDependencies.getSignalCallManager()
.receivedOpaqueMessage(new WebRtcData.OpaqueMessageMetadata(Recipient.externalHighTrustPush(context, content.getSender()).requireUuid(), .receivedOpaqueMessage(new WebRtcData.OpaqueMessageMetadata(senderRecipient.requireUuid(),
message.getOpaque(), message.getOpaque(),
content.getSenderDevice(), content.getSenderDevice(),
messageAgeSeconds)); messageAgeSeconds));
@ -628,7 +631,8 @@ public final class MessageContentProcessor {
private void handleGroupCallUpdateMessage(@NonNull SignalServiceContent content, private void handleGroupCallUpdateMessage(@NonNull SignalServiceContent content,
@NonNull SignalServiceDataMessage message, @NonNull SignalServiceDataMessage message,
@NonNull Optional<GroupId> groupId) @NonNull Optional<GroupId> groupId,
@NonNull Recipient senderRecipient)
{ {
if (!groupId.isPresent() || !groupId.get().isV2()) { if (!groupId.isPresent() || !groupId.get().isV2()) {
Log.w(TAG, "Invalid group for group call update message"); Log.w(TAG, "Invalid group for group call update message");
@ -638,18 +642,19 @@ public final class MessageContentProcessor {
RecipientId groupRecipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromPossiblyMigratedGroupId(groupId.get()); RecipientId groupRecipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromPossiblyMigratedGroupId(groupId.get());
DatabaseFactory.getSmsDatabase(context).insertOrUpdateGroupCall(groupRecipientId, DatabaseFactory.getSmsDatabase(context).insertOrUpdateGroupCall(groupRecipientId,
RecipientId.from(content.getSender()), senderRecipient.getId(),
content.getServerReceivedTimestamp(), content.getServerReceivedTimestamp(),
message.getGroupCallUpdate().get().getEraId()); message.getGroupCallUpdate().get().getEraId());
GroupCallPeekJob.enqueue(groupRecipientId); GroupCallPeekJob.enqueue(groupRecipientId);
} }
private @Nullable MessageId handleEndSessionMessage(@NonNull SignalServiceContent content, private @Nullable MessageId handleEndSessionMessage(@NonNull SignalServiceContent content,
@NonNull Optional<Long> smsMessageId) @NonNull Optional<Long> smsMessageId,
@NonNull Recipient senderRecipient)
{ {
MessageDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context); MessageDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(Recipient.externalHighTrustPush(context, content.getSender()).getId(), IncomingTextMessage incomingTextMessage = new IncomingTextMessage(senderRecipient.getId(),
content.getSenderDevice(), content.getSenderDevice(),
content.getTimestamp(), content.getTimestamp(),
content.getServerReceivedTimestamp(), content.getServerReceivedTimestamp(),
@ -713,13 +718,15 @@ public final class MessageContentProcessor {
@NonNull SignalServiceDataMessage message, @NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId, @NonNull Optional<Long> smsMessageId,
@NonNull GroupId.V1 groupId, @NonNull GroupId.V1 groupId,
@NonNull Recipient senderRecipient,
@NonNull Recipient threadRecipient,
long receivedTime) long receivedTime)
throws StorageFailedException, BadGroupIdException throws StorageFailedException, BadGroupIdException
{ {
GroupV1MessageProcessor.process(context, content, message, false); GroupV1MessageProcessor.process(context, content, message, false);
if (message.getExpiresInSeconds() != 0 && message.getExpiresInSeconds() != getMessageDestination(content, message).getExpireMessages()) { if (message.getExpiresInSeconds() != 0 && message.getExpiresInSeconds() != threadRecipient.getExpireMessages()) {
handleExpirationUpdate(content, message, Optional.absent(), Optional.of(groupId), receivedTime); handleExpirationUpdate(content, message, Optional.absent(), Optional.of(groupId), senderRecipient, threadRecipient, receivedTime);
} }
if (smsMessageId.isPresent()) { if (smsMessageId.isPresent()) {
@ -728,13 +735,14 @@ public final class MessageContentProcessor {
} }
private void handleUnknownGroupMessage(@NonNull SignalServiceContent content, private void handleUnknownGroupMessage(@NonNull SignalServiceContent content,
@NonNull SignalServiceGroupContext group) @NonNull SignalServiceGroupContext group,
@NonNull Recipient senderRecipient)
throws BadGroupIdException throws BadGroupIdException
{ {
if (group.getGroupV1().isPresent()) { if (group.getGroupV1().isPresent()) {
SignalServiceGroup groupV1 = group.getGroupV1().get(); SignalServiceGroup groupV1 = group.getGroupV1().get();
if (groupV1.getType() != SignalServiceGroup.Type.REQUEST_INFO) { if (groupV1.getType() != SignalServiceGroup.Type.REQUEST_INFO) {
ApplicationDependencies.getJobManager().add(new RequestGroupInfoJob(Recipient.externalHighTrustPush(context, content.getSender()).getId(), GroupId.v1(groupV1.getGroupId()))); ApplicationDependencies.getJobManager().add(new RequestGroupInfoJob(senderRecipient.getId(), GroupId.v1(groupV1.getGroupId())));
} else { } else {
warn(content.getTimestamp(), "Received a REQUEST_INFO message for a group we don't know about. Ignoring."); warn(content.getTimestamp(), "Received a REQUEST_INFO message for a group we don't know about. Ignoring.");
} }
@ -750,8 +758,10 @@ public final class MessageContentProcessor {
@NonNull SignalServiceDataMessage message, @NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId, @NonNull Optional<Long> smsMessageId,
@NonNull Optional<GroupId> groupId, @NonNull Optional<GroupId> groupId,
@NonNull Recipient senderRecipient,
@NonNull Recipient threadRecipient,
long receivedTime) long receivedTime)
throws StorageFailedException, BadGroupIdException throws StorageFailedException
{ {
if (groupId.isPresent() && groupId.get().isV2()) { if (groupId.isPresent() && groupId.get().isV2()) {
warn(String.valueOf(content.getTimestamp()), "Expiration update received for GV2. Ignoring."); warn(String.valueOf(content.getTimestamp()), "Expiration update received for GV2. Ignoring.");
@ -760,17 +770,15 @@ public final class MessageContentProcessor {
int expiresInSeconds = message.getExpiresInSeconds(); int expiresInSeconds = message.getExpiresInSeconds();
Optional<SignalServiceGroupContext> groupContext = message.getGroupContext(); Optional<SignalServiceGroupContext> groupContext = message.getGroupContext();
Recipient recipient = getMessageDestination(content, groupContext);
if (recipient.getExpireMessages() == expiresInSeconds) { if (threadRecipient.getExpireMessages() == expiresInSeconds) {
log(String.valueOf(content.getTimestamp()), "No change in message expiry for group. Ignoring."); log(String.valueOf(content.getTimestamp()), "No change in message expiry for group. Ignoring.");
return null; return null;
} }
try { try {
MessageDatabase database = DatabaseFactory.getMmsDatabase(context); MessageDatabase database = DatabaseFactory.getMmsDatabase(context);
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender()); IncomingMediaMessage mediaMessage = new IncomingMediaMessage(senderRecipient.getId(),
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(sender.getId(),
content.getTimestamp(), content.getTimestamp(),
content.getServerReceivedTimestamp(), content.getServerReceivedTimestamp(),
receivedTime, receivedTime,
@ -791,7 +799,7 @@ public final class MessageContentProcessor {
Optional<InsertResult> insertResult = database.insertSecureDecryptedMessageInbox(mediaMessage, -1); Optional<InsertResult> insertResult = database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(recipient.getId(), expiresInSeconds); DatabaseFactory.getRecipientDatabase(context).setExpireMessages(threadRecipient.getId(), expiresInSeconds);
if (smsMessageId.isPresent()) { if (smsMessageId.isPresent()) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get()); DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
@ -807,7 +815,7 @@ public final class MessageContentProcessor {
return null; return null;
} }
private @Nullable MessageId handleReaction(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) { private @Nullable MessageId handleReaction(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message, @NonNull Recipient senderRecipient) {
SignalServiceDataMessage.Reaction reaction = message.getReaction().get(); SignalServiceDataMessage.Reaction reaction = message.getReaction().get();
if (!EmojiUtil.isEmoji(reaction.getEmoji())) { if (!EmojiUtil.isEmoji(reaction.getEmoji())) {
@ -815,7 +823,6 @@ public final class MessageContentProcessor {
return null; return null;
} }
Recipient reactionAuthor = Recipient.externalHighTrustPush(context, content.getSender());
Recipient targetAuthor = Recipient.externalPush(context, reaction.getTargetAuthor()); Recipient targetAuthor = Recipient.externalPush(context, reaction.getTargetAuthor());
MessageRecord targetMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(reaction.getTargetSentTimestamp(), targetAuthor.getId()); MessageRecord targetMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(reaction.getTargetSentTimestamp(), targetAuthor.getId());
@ -839,12 +846,12 @@ public final class MessageContentProcessor {
Recipient threadRecipient = targetThread.getRecipient().resolve(); Recipient threadRecipient = targetThread.getRecipient().resolve();
if (threadRecipient.isGroup() && !threadRecipient.getParticipants().contains(reactionAuthor)) { if (threadRecipient.isGroup() && !threadRecipient.getParticipants().contains(senderRecipient)) {
warn(String.valueOf(content.getTimestamp()), "[handleReaction] Reaction author is not in the group! timestamp: " + reaction.getTargetSentTimestamp() + " author: " + targetAuthor.getId()); warn(String.valueOf(content.getTimestamp()), "[handleReaction] Reaction author is not in the group! timestamp: " + reaction.getTargetSentTimestamp() + " author: " + targetAuthor.getId());
return null; return null;
} }
if (!threadRecipient.isGroup() && !reactionAuthor.equals(threadRecipient) && !reactionAuthor.isSelf()) { if (!threadRecipient.isGroup() && !senderRecipient.equals(threadRecipient) && !senderRecipient.isSelf()) {
warn(String.valueOf(content.getTimestamp()), "[handleReaction] Reaction author is not a part of the 1:1 thread! timestamp: " + reaction.getTargetSentTimestamp() + " author: " + targetAuthor.getId()); warn(String.valueOf(content.getTimestamp()), "[handleReaction] Reaction author is not a part of the 1:1 thread! timestamp: " + reaction.getTargetSentTimestamp() + " author: " + targetAuthor.getId());
return null; return null;
} }
@ -852,10 +859,10 @@ public final class MessageContentProcessor {
MessageDatabase db = targetMessage.isMms() ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context); MessageDatabase db = targetMessage.isMms() ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context);
if (reaction.isRemove()) { if (reaction.isRemove()) {
db.deleteReaction(targetMessage.getId(), reactionAuthor.getId()); db.deleteReaction(targetMessage.getId(), senderRecipient.getId());
ApplicationDependencies.getMessageNotifier().updateNotification(context); ApplicationDependencies.getMessageNotifier().updateNotification(context);
} else { } else {
ReactionRecord reactionRecord = new ReactionRecord(reaction.getEmoji(), reactionAuthor.getId(), message.getTimestamp(), System.currentTimeMillis()); ReactionRecord reactionRecord = new ReactionRecord(reaction.getEmoji(), senderRecipient.getId(), message.getTimestamp(), System.currentTimeMillis());
db.addReaction(targetMessage.getId(), reactionRecord); db.addReaction(targetMessage.getId(), reactionRecord);
ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false); ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false);
} }
@ -863,24 +870,23 @@ public final class MessageContentProcessor {
return new MessageId(targetMessage.getId(), targetMessage.isMms()); return new MessageId(targetMessage.getId(), targetMessage.isMms());
} }
private @Nullable MessageId handleRemoteDelete(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) { private @Nullable MessageId handleRemoteDelete(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message, @NonNull Recipient senderRecipient) {
SignalServiceDataMessage.RemoteDelete delete = message.getRemoteDelete().get(); SignalServiceDataMessage.RemoteDelete delete = message.getRemoteDelete().get();
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender()); MessageRecord targetMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(delete.getTargetSentTimestamp(), senderRecipient.getId());
MessageRecord targetMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(delete.getTargetSentTimestamp(), sender.getId());
if (targetMessage != null && RemoteDeleteUtil.isValidReceive(targetMessage, sender, content.getServerReceivedTimestamp())) { if (targetMessage != null && RemoteDeleteUtil.isValidReceive(targetMessage, senderRecipient, content.getServerReceivedTimestamp())) {
MessageDatabase db = targetMessage.isMms() ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context); MessageDatabase db = targetMessage.isMms() ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context);
db.markAsRemoteDelete(targetMessage.getId()); db.markAsRemoteDelete(targetMessage.getId());
ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false); ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false);
return new MessageId(targetMessage.getId(), targetMessage.isMms()); return new MessageId(targetMessage.getId(), targetMessage.isMms());
} else if (targetMessage == null) { } else if (targetMessage == null) {
warn(String.valueOf(content.getTimestamp()), "[handleRemoteDelete] Could not find matching message! timestamp: " + delete.getTargetSentTimestamp() + " author: " + sender.getId()); warn(String.valueOf(content.getTimestamp()), "[handleRemoteDelete] Could not find matching message! timestamp: " + delete.getTargetSentTimestamp() + " author: " + senderRecipient.getId());
ApplicationDependencies.getEarlyMessageCache().store(sender.getId(), delete.getTargetSentTimestamp(), content); ApplicationDependencies.getEarlyMessageCache().store(senderRecipient.getId(), delete.getTargetSentTimestamp(), content);
return null; return null;
} else { } else {
warn(String.valueOf(content.getTimestamp()), String.format(Locale.ENGLISH, "[handleRemoteDelete] Invalid remote delete! deleteTime: %d, targetTime: %d, deleteAuthor: %s, targetAuthor: %s", warn(String.valueOf(content.getTimestamp()), String.format(Locale.ENGLISH, "[handleRemoteDelete] Invalid remote delete! deleteTime: %d, targetTime: %d, deleteAuthor: %s, targetAuthor: %s",
content.getServerReceivedTimestamp(), targetMessage.getServerTimestamp(), sender.getId(), targetMessage.getRecipient().getId())); content.getServerReceivedTimestamp(), targetMessage.getServerTimestamp(), senderRecipient.getId(), targetMessage.getRecipient().getId()));
return null; return null;
} }
} }
@ -952,7 +958,7 @@ public final class MessageContentProcessor {
throws BadGroupIdException throws BadGroupIdException
{ {
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context); RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context); ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
Recipient recipient; Recipient recipient;
@ -1025,7 +1031,8 @@ public final class MessageContentProcessor {
} }
private void handleSynchronizeSentMessage(@NonNull SignalServiceContent content, private void handleSynchronizeSentMessage(@NonNull SignalServiceContent content,
@NonNull SentTranscriptMessage message) @NonNull SentTranscriptMessage message,
@NonNull Recipient senderRecipient)
throws StorageFailedException, BadGroupIdException, IOException, GroupChangeBusyException throws StorageFailedException, BadGroupIdException, IOException, GroupChangeBusyException
{ {
log(String.valueOf(content.getTimestamp()), "Processing sent transcript for message with ID " + message.getTimestamp()); log(String.valueOf(content.getTimestamp()), "Processing sent transcript for message with ID " + message.getTimestamp());
@ -1035,7 +1042,7 @@ public final class MessageContentProcessor {
if (message.getMessage().isGroupV2Message()) { if (message.getMessage().isGroupV2Message()) {
GroupId.V2 groupId = GroupId.v2(message.getMessage().getGroupContext().get().getGroupV2().get().getMasterKey()); GroupId.V2 groupId = GroupId.v2(message.getMessage().getGroupContext().get().getGroupV2().get().getMasterKey());
if (handleGv2PreProcessing(groupId, content, message.getMessage().getGroupContext().get().getGroupV2().get())) { if (handleGv2PreProcessing(groupId, content, message.getMessage().getGroupContext().get().getGroupV2().get(), senderRecipient)) {
return; return;
} }
} }
@ -1053,16 +1060,16 @@ public final class MessageContentProcessor {
handleSynchronizeSentGv2Update(content, message); handleSynchronizeSentGv2Update(content, message);
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(getSyncMessageDestination(message)); threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(getSyncMessageDestination(message));
} else if (Build.VERSION.SDK_INT > 19 && message.getMessage().getGroupCallUpdate().isPresent()) { } else if (Build.VERSION.SDK_INT > 19 && message.getMessage().getGroupCallUpdate().isPresent()) {
handleGroupCallUpdateMessage(content, message.getMessage(), GroupUtil.idFromGroupContext(message.getMessage().getGroupContext())); handleGroupCallUpdateMessage(content, message.getMessage(), GroupUtil.idFromGroupContext(message.getMessage().getGroupContext()), senderRecipient);
} else if (message.getMessage().isEmptyGroupV2Message()) { } else if (message.getMessage().isEmptyGroupV2Message()) {
warn(content.getTimestamp(), "Empty GV2 message! Doing nothing."); warn(content.getTimestamp(), "Empty GV2 message! Doing nothing.");
} else if (message.getMessage().isExpirationUpdate()) { } else if (message.getMessage().isExpirationUpdate()) {
threadId = handleSynchronizeSentExpirationUpdate(message); threadId = handleSynchronizeSentExpirationUpdate(message);
} else if (message.getMessage().getReaction().isPresent()) { } else if (message.getMessage().getReaction().isPresent()) {
handleReaction(content, message.getMessage()); handleReaction(content, message.getMessage(), senderRecipient);
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(getSyncMessageDestination(message)); threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(getSyncMessageDestination(message));
} else if (message.getMessage().getRemoteDelete().isPresent()) { } else if (message.getMessage().getRemoteDelete().isPresent()) {
handleRemoteDelete(content, message.getMessage()); handleRemoteDelete(content, message.getMessage(), senderRecipient);
} else if (message.getMessage().getAttachments().isPresent() || message.getMessage().getQuote().isPresent() || message.getMessage().getPreviews().isPresent() || message.getMessage().getSticker().isPresent() || message.getMessage().isViewOnce() || message.getMessage().getMentions().isPresent()) { } else if (message.getMessage().getAttachments().isPresent() || message.getMessage().getQuote().isPresent() || message.getMessage().getPreviews().isPresent() || message.getMessage().getSticker().isPresent() || message.getMessage().isViewOnce() || message.getMessage().getMentions().isPresent()) {
threadId = handleSynchronizeSentMediaMessage(message); threadId = handleSynchronizeSentMediaMessage(message);
} else { } else {
@ -1070,7 +1077,7 @@ public final class MessageContentProcessor {
} }
if (message.getMessage().getGroupContext().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.idFromGroupContext(message.getMessage().getGroupContext().get()))) { if (message.getMessage().getGroupContext().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.idFromGroupContext(message.getMessage().getGroupContext().get()))) {
handleUnknownGroupMessage(content, message.getMessage().getGroupContext().get()); handleUnknownGroupMessage(content, message.getMessage().getGroupContext().get(), senderRecipient);
} }
if (message.getMessage().getProfileKey().isPresent()) { if (message.getMessage().getProfileKey().isPresent()) {
@ -1136,14 +1143,14 @@ public final class MessageContentProcessor {
} }
} }
private void handleSynchronizeReadMessage(@NonNull List<ReadMessage> readMessages, long envelopeTimestamp) private void handleSynchronizeReadMessage(@NonNull List<ReadMessage> readMessages, long envelopeTimestamp, @NonNull Recipient senderRecipient)
{ {
Map<Long, Long> threadToLatestRead = new HashMap<>(); Map<Long, Long> threadToLatestRead = new HashMap<>();
for (ReadMessage readMessage : readMessages) { for (ReadMessage readMessage : readMessages) {
List<Pair<Long, Long>> expiringText = DatabaseFactory.getSmsDatabase(context).setTimestampRead(new SyncMessageId(Recipient.externalPush(context, readMessage.getSender()).getId(), readMessage.getTimestamp()), List<Pair<Long, Long>> expiringText = DatabaseFactory.getSmsDatabase(context).setTimestampRead(new SyncMessageId(senderRecipient.getId(), readMessage.getTimestamp()),
envelopeTimestamp, envelopeTimestamp,
threadToLatestRead); threadToLatestRead);
List<Pair<Long, Long>> expiringMedia = DatabaseFactory.getMmsDatabase(context).setTimestampRead(new SyncMessageId(Recipient.externalPush(context, readMessage.getSender()).getId(), readMessage.getTimestamp()), List<Pair<Long, Long>> expiringMedia = DatabaseFactory.getMmsDatabase(context).setTimestampRead(new SyncMessageId(senderRecipient.getId(), readMessage.getTimestamp()),
envelopeTimestamp, envelopeTimestamp,
threadToLatestRead); threadToLatestRead);
@ -1210,10 +1217,12 @@ public final class MessageContentProcessor {
private @Nullable MessageId handleMediaMessage(@NonNull SignalServiceContent content, private @Nullable MessageId handleMediaMessage(@NonNull SignalServiceContent content,
@NonNull SignalServiceDataMessage message, @NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId, @NonNull Optional<Long> smsMessageId,
@NonNull Recipient senderRecipient,
@NonNull Recipient threadRecipient,
long receivedTime) long receivedTime)
throws StorageFailedException, BadGroupIdException throws StorageFailedException
{ {
notifyTypingStoppedFromIncomingMessage(getMessageDestination(content, message), content.getSender(), content.getSenderDevice()); notifyTypingStoppedFromIncomingMessage(senderRecipient, threadRecipient, content.getSenderDevice());
Optional<InsertResult> insertResult; Optional<InsertResult> insertResult;
@ -1227,7 +1236,7 @@ public final class MessageContentProcessor {
Optional<List<Mention>> mentions = getMentions(message.getMentions()); Optional<List<Mention>> mentions = getMentions(message.getMentions());
Optional<Attachment> sticker = getStickerAttachment(message.getSticker()); Optional<Attachment> sticker = getStickerAttachment(message.getSticker());
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(RecipientId.fromHighTrust(content.getSender()), IncomingMediaMessage mediaMessage = new IncomingMediaMessage(senderRecipient.getId(),
message.getTimestamp(), message.getTimestamp(),
content.getServerReceivedTimestamp(), content.getServerReceivedTimestamp(),
receivedTime, receivedTime,
@ -1414,18 +1423,18 @@ public final class MessageContentProcessor {
} }
private void updateGroupReceiptStatus(@NonNull SentTranscriptMessage message, long messageId, @NonNull GroupId groupString) { private void updateGroupReceiptStatus(@NonNull SentTranscriptMessage message, long messageId, @NonNull GroupId groupString) {
GroupReceiptDatabase receiptDatabase = DatabaseFactory.getGroupReceiptDatabase(context); GroupReceiptDatabase receiptDatabase = DatabaseFactory.getGroupReceiptDatabase(context);
List<Recipient> messageRecipients = Stream.of(message.getRecipients()).map(address -> Recipient.externalPush(context, address)).toList(); List<RecipientId> messageRecipientIds = Stream.of(message.getRecipients()).map(RecipientId::from).toList();
List<Recipient> members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupString, GroupDatabase.MemberSet.FULL_MEMBERS_EXCLUDING_SELF); List<Recipient> members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupString, GroupDatabase.MemberSet.FULL_MEMBERS_EXCLUDING_SELF);
Map<RecipientId, Integer> localReceipts = Stream.of(receiptDatabase.getGroupReceiptInfo(messageId)) Map<RecipientId, Integer> localReceipts = Stream.of(receiptDatabase.getGroupReceiptInfo(messageId))
.collect(Collectors.toMap(GroupReceiptInfo::getRecipientId, GroupReceiptInfo::getStatus)); .collect(Collectors.toMap(GroupReceiptInfo::getRecipientId, GroupReceiptInfo::getStatus));
for (Recipient messageRecipient : messageRecipients) { for (RecipientId messageRecipientId : messageRecipientIds) {
//noinspection ConstantConditions //noinspection ConstantConditions
if (localReceipts.containsKey(messageRecipient.getId()) && localReceipts.get(messageRecipient.getId()) < GroupReceiptDatabase.STATUS_UNDELIVERED) { if (localReceipts.containsKey(messageRecipientId) && localReceipts.get(messageRecipientId) < GroupReceiptDatabase.STATUS_UNDELIVERED) {
receiptDatabase.update(messageRecipient.getId(), messageId, GroupReceiptDatabase.STATUS_UNDELIVERED, message.getTimestamp()); receiptDatabase.update(messageRecipientId, messageId, GroupReceiptDatabase.STATUS_UNDELIVERED, message.getTimestamp());
} else if (!localReceipts.containsKey(messageRecipient.getId())) { } else if (!localReceipts.containsKey(messageRecipientId)) {
receiptDatabase.insert(Collections.singletonList(messageRecipient.getId()), messageId, GroupReceiptDatabase.STATUS_UNDELIVERED, message.getTimestamp()); receiptDatabase.insert(Collections.singletonList(messageRecipientId), messageId, GroupReceiptDatabase.STATUS_UNDELIVERED, message.getTimestamp());
} }
} }
@ -1439,15 +1448,16 @@ public final class MessageContentProcessor {
@NonNull SignalServiceDataMessage message, @NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId, @NonNull Optional<Long> smsMessageId,
@NonNull Optional<GroupId> groupId, @NonNull Optional<GroupId> groupId,
@NonNull Recipient senderRecipient,
@NonNull Recipient threadRecipient,
long receivedTime) long receivedTime)
throws StorageFailedException, BadGroupIdException throws StorageFailedException
{ {
MessageDatabase database = DatabaseFactory.getSmsDatabase(context); MessageDatabase database = DatabaseFactory.getSmsDatabase(context);
String body = message.getBody().isPresent() ? message.getBody().get() : ""; String body = message.getBody().isPresent() ? message.getBody().get() : "";
Recipient recipient = getMessageDestination(content, message);
if (message.getExpiresInSeconds() != recipient.getExpireMessages()) { if (message.getExpiresInSeconds() != threadRecipient.getExpireMessages()) {
handleExpirationUpdate(content, message, Optional.absent(), groupId, receivedTime); handleExpirationUpdate(content, message, Optional.absent(), groupId, senderRecipient, threadRecipient, receivedTime);
} }
Optional<InsertResult> insertResult; Optional<InsertResult> insertResult;
@ -1455,9 +1465,9 @@ public final class MessageContentProcessor {
if (smsMessageId.isPresent() && !message.getGroupContext().isPresent()) { if (smsMessageId.isPresent() && !message.getGroupContext().isPresent()) {
insertResult = Optional.of(database.updateBundleMessageBody(smsMessageId.get(), body)); insertResult = Optional.of(database.updateBundleMessageBody(smsMessageId.get(), body));
} else { } else {
notifyTypingStoppedFromIncomingMessage(recipient, content.getSender(), content.getSenderDevice()); notifyTypingStoppedFromIncomingMessage(senderRecipient, threadRecipient, content.getSenderDevice());
IncomingTextMessage textMessage = new IncomingTextMessage(RecipientId.fromHighTrust(content.getSender()), IncomingTextMessage textMessage = new IncomingTextMessage(senderRecipient.getId(),
content.getSenderDevice(), content.getSenderDevice(),
message.getTimestamp(), message.getTimestamp(),
content.getServerReceivedTimestamp(), content.getServerReceivedTimestamp(),
@ -1635,15 +1645,15 @@ public final class MessageContentProcessor {
} }
private void handleProfileKey(@NonNull SignalServiceContent content, private void handleProfileKey(@NonNull SignalServiceContent content,
@NonNull byte[] messageProfileKeyBytes) @NonNull byte[] messageProfileKeyBytes,
@NonNull Recipient senderRecipient)
{ {
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context); RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
Recipient recipient = Recipient.externalHighTrustPush(context, content.getSender()); ProfileKey messageProfileKey = ProfileKeyUtil.profileKeyOrNull(messageProfileKeyBytes);
ProfileKey messageProfileKey = ProfileKeyUtil.profileKeyOrNull(messageProfileKeyBytes);
if (messageProfileKey != null) { if (messageProfileKey != null) {
if (database.setProfileKey(recipient.getId(), messageProfileKey)) { if (database.setProfileKey(senderRecipient.getId(), messageProfileKey)) {
ApplicationDependencies.getJobManager().add(RetrieveProfileJob.forRecipient(recipient.getId())); ApplicationDependencies.getJobManager().add(RetrieveProfileJob.forRecipient(senderRecipient.getId()));
} }
} else { } else {
warn(String.valueOf(content.getTimestamp()), "Ignored invalid profile key seen in message"); warn(String.valueOf(content.getTimestamp()), "Ignored invalid profile key seen in message");
@ -1664,84 +1674,83 @@ public final class MessageContentProcessor {
} }
private void handleViewedReceipt(@NonNull SignalServiceContent content, private void handleViewedReceipt(@NonNull SignalServiceContent content,
@NonNull SignalServiceReceiptMessage message) @NonNull SignalServiceReceiptMessage message,
@NonNull Recipient senderRecipient)
{ {
if (!TextSecurePreferences.isReadReceiptsEnabled(context)) { if (!TextSecurePreferences.isReadReceiptsEnabled(context)) {
log("Ignoring viewed receipts for IDs: " + Util.join(message.getTimestamps(), ", ")); log("Ignoring viewed receipts for IDs: " + Util.join(message.getTimestamps(), ", "));
return; return;
} }
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender()); log(TAG, "Processing viewed receipts. Sender: " + senderRecipient.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
log(TAG, "Processing viewed receipts. Sender: " + sender.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
List<SyncMessageId> ids = Stream.of(message.getTimestamps()) List<SyncMessageId> ids = Stream.of(message.getTimestamps())
.map(t -> new SyncMessageId(sender.getId(), t)) .map(t -> new SyncMessageId(senderRecipient.getId(), t))
.toList(); .toList();
Collection<SyncMessageId> unhandled = DatabaseFactory.getMmsSmsDatabase(context) Collection<SyncMessageId> unhandled = DatabaseFactory.getMmsSmsDatabase(context)
.incrementViewedReceiptCounts(ids, content.getTimestamp()); .incrementViewedReceiptCounts(ids, content.getTimestamp());
for (SyncMessageId id : unhandled) { for (SyncMessageId id : unhandled) {
warn(String.valueOf(content.getTimestamp()), "[handleViewedReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + " author: " + sender.getId()); warn(String.valueOf(content.getTimestamp()), "[handleViewedReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + " author: " + senderRecipient.getId());
ApplicationDependencies.getEarlyMessageCache().store(sender.getId(), id.getTimetamp(), content); ApplicationDependencies.getEarlyMessageCache().store(senderRecipient.getId(), id.getTimetamp(), content);
} }
} }
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
private void handleDeliveryReceipt(@NonNull SignalServiceContent content, private void handleDeliveryReceipt(@NonNull SignalServiceContent content,
@NonNull SignalServiceReceiptMessage message) @NonNull SignalServiceReceiptMessage message,
@NonNull Recipient senderRecipient)
{ {
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender()); log(TAG, "Processing delivery receipts. Sender: " + senderRecipient.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
log(TAG, "Processing delivery receipts. Sender: " + sender.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
List<SyncMessageId> ids = Stream.of(message.getTimestamps()) List<SyncMessageId> ids = Stream.of(message.getTimestamps())
.map(t -> new SyncMessageId(sender.getId(), t)) .map(t -> new SyncMessageId(senderRecipient.getId(), t))
.toList(); .toList();
DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCounts(ids, System.currentTimeMillis()); DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCounts(ids, System.currentTimeMillis());
DatabaseFactory.getMessageLogDatabase(context).deleteEntriesForRecipient(message.getTimestamps(), sender.getId(), content.getSenderDevice()); DatabaseFactory.getMessageLogDatabase(context).deleteEntriesForRecipient(message.getTimestamps(), senderRecipient.getId(), content.getSenderDevice());
} }
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
private void handleReadReceipt(@NonNull SignalServiceContent content, private void handleReadReceipt(@NonNull SignalServiceContent content,
@NonNull SignalServiceReceiptMessage message) @NonNull SignalServiceReceiptMessage message,
@NonNull Recipient senderRecipient)
{ {
if (!TextSecurePreferences.isReadReceiptsEnabled(context)) { if (!TextSecurePreferences.isReadReceiptsEnabled(context)) {
log("Ignoring read receipts for IDs: " + Util.join(message.getTimestamps(), ", ")); log("Ignoring read receipts for IDs: " + Util.join(message.getTimestamps(), ", "));
return; return;
} }
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender()); log(TAG, "Processing read receipts. Sender: " + senderRecipient.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
log(TAG, "Processing read receipts. Sender: " + sender.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
List<SyncMessageId> ids = Stream.of(message.getTimestamps()) List<SyncMessageId> ids = Stream.of(message.getTimestamps())
.map(t -> new SyncMessageId(sender.getId(), t)) .map(t -> new SyncMessageId(senderRecipient.getId(), t))
.toList(); .toList();
Collection<SyncMessageId> unhandled = DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCounts(ids, content.getTimestamp()); Collection<SyncMessageId> unhandled = DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCounts(ids, content.getTimestamp());
for (SyncMessageId id : unhandled) { for (SyncMessageId id : unhandled) {
warn(String.valueOf(content.getTimestamp()), "[handleReadReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + " author: " + sender.getId()); warn(String.valueOf(content.getTimestamp()), "[handleReadReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + " author: " + senderRecipient.getId());
ApplicationDependencies.getEarlyMessageCache().store(sender.getId(), id.getTimetamp(), content); ApplicationDependencies.getEarlyMessageCache().store(senderRecipient.getId(), id.getTimetamp(), content);
} }
} }
private void handleTypingMessage(@NonNull SignalServiceContent content, private void handleTypingMessage(@NonNull SignalServiceContent content,
@NonNull SignalServiceTypingMessage typingMessage) @NonNull SignalServiceTypingMessage typingMessage,
@NonNull Recipient senderRecipient)
throws BadGroupIdException throws BadGroupIdException
{ {
if (!TextSecurePreferences.isTypingIndicatorsEnabled(context)) { if (!TextSecurePreferences.isTypingIndicatorsEnabled(context)) {
return; return;
} }
Recipient author = Recipient.externalHighTrustPush(context, content.getSender());
long threadId; long threadId;
if (typingMessage.getGroupId().isPresent()) { if (typingMessage.getGroupId().isPresent()) {
GroupId.Push groupId = GroupId.push(typingMessage.getGroupId().get()); GroupId.Push groupId = GroupId.push(typingMessage.getGroupId().get());
if (!DatabaseFactory.getGroupDatabase(context).isCurrentMember(groupId, author.getId())) { if (!DatabaseFactory.getGroupDatabase(context).isCurrentMember(groupId, senderRecipient.getId())) {
warn(String.valueOf(content.getTimestamp()), "Seen typing indicator for non-member"); warn(String.valueOf(content.getTimestamp()), "Seen typing indicator for non-member");
return; return;
} }
@ -1750,7 +1759,7 @@ public final class MessageContentProcessor {
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient); threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
} else { } else {
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(author); threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(senderRecipient);
} }
if (threadId <= 0) { if (threadId <= 0) {
@ -1760,35 +1769,34 @@ public final class MessageContentProcessor {
if (typingMessage.isTypingStarted()) { if (typingMessage.isTypingStarted()) {
Log.d(TAG, "Typing started on thread " + threadId); Log.d(TAG, "Typing started on thread " + threadId);
ApplicationDependencies.getTypingStatusRepository().onTypingStarted(context,threadId, author, content.getSenderDevice()); ApplicationDependencies.getTypingStatusRepository().onTypingStarted(context,threadId, senderRecipient, content.getSenderDevice());
} else { } else {
Log.d(TAG, "Typing stopped on thread " + threadId); Log.d(TAG, "Typing stopped on thread " + threadId);
ApplicationDependencies.getTypingStatusRepository().onTypingStopped(context, threadId, author, content.getSenderDevice(), false); ApplicationDependencies.getTypingStatusRepository().onTypingStopped(context, threadId, senderRecipient, content.getSenderDevice(), false);
} }
} }
private void handleRetryReceipt(@NonNull SignalServiceContent content, @NonNull DecryptionErrorMessage decryptionErrorMessage) { private void handleRetryReceipt(@NonNull SignalServiceContent content, @NonNull DecryptionErrorMessage decryptionErrorMessage, @NonNull Recipient senderRecipient) {
if (!FeatureFlags.senderKey()) { if (!FeatureFlags.senderKey()) {
warn(String.valueOf(content.getTimestamp()), "[RetryReceipt] Sender key not enabled, skipping retry receipt."); warn(String.valueOf(content.getTimestamp()), "[RetryReceipt] Sender key not enabled, skipping retry receipt.");
return; return;
} }
Recipient requester = Recipient.externalHighTrustPush(context, content.getSender()); long sentTimestamp = decryptionErrorMessage.getTimestamp();
long sentTimestamp = decryptionErrorMessage.getTimestamp();
warn(content.getTimestamp(), "[RetryReceipt] Received a retry receipt from " + requester.getId() + ", device " + decryptionErrorMessage.getDeviceId() + " for message with timestamp " + sentTimestamp + "."); warn(content.getTimestamp(), "[RetryReceipt] Received a retry receipt from " + senderRecipient.getId() + ", device " + decryptionErrorMessage.getDeviceId() + " for message with timestamp " + sentTimestamp + ".");
if (!requester.hasUuid()) { if (!senderRecipient.hasUuid()) {
warn(content.getTimestamp(), "[RetryReceipt] Requester " + requester.getId() + " somehow has no UUID! timestamp: " + sentTimestamp); warn(content.getTimestamp(), "[RetryReceipt] Requester " + senderRecipient.getId() + " somehow has no UUID! timestamp: " + sentTimestamp);
return; return;
} }
MessageLogEntry messageLogEntry = DatabaseFactory.getMessageLogDatabase(context).getLogEntry(requester.getId(), content.getSenderDevice(), sentTimestamp); MessageLogEntry messageLogEntry = DatabaseFactory.getMessageLogDatabase(context).getLogEntry(senderRecipient.getId(), content.getSenderDevice(), sentTimestamp);
if (decryptionErrorMessage.getRatchetKey().isPresent()) { if (decryptionErrorMessage.getRatchetKey().isPresent()) {
handleIndividualRetryReceipt(requester, messageLogEntry, content, decryptionErrorMessage); handleIndividualRetryReceipt(senderRecipient, messageLogEntry, content, decryptionErrorMessage);
} else { } else {
handleSenderKeyRetryReceipt(requester, messageLogEntry, content, decryptionErrorMessage); handleSenderKeyRetryReceipt(senderRecipient, messageLogEntry, content, decryptionErrorMessage);
} }
} }
@ -2088,20 +2096,6 @@ public final class MessageContentProcessor {
return getGroupRecipient(message != null ? message.getGroupContext() : Optional.absent()).or(() -> Recipient.externalHighTrustPush(context, content.getSender())); return getGroupRecipient(message != null ? message.getGroupContext() : Optional.absent()).or(() -> Recipient.externalHighTrustPush(context, content.getSender()));
} }
private Recipient getMessageDestination(@NonNull SignalServiceContent content,
@NonNull SignalServiceDataMessage message)
throws BadGroupIdException
{
return getGroupRecipient(message.getGroupContext()).or(() -> Recipient.externalHighTrustPush(context, content.getSender()));
}
private Recipient getMessageDestination(@NonNull SignalServiceContent content,
@NonNull Optional<SignalServiceGroupContext> groupContext)
throws BadGroupIdException
{
return getGroupRecipient(groupContext).or(() -> Recipient.externalPush(context, content.getSender()));
}
private Optional<Recipient> getGroupRecipient(Optional<SignalServiceGroupContext> message) private Optional<Recipient> getGroupRecipient(Optional<SignalServiceGroupContext> message)
throws BadGroupIdException throws BadGroupIdException
{ {
@ -2111,29 +2105,20 @@ public final class MessageContentProcessor {
return Optional.absent(); return Optional.absent();
} }
private void notifyTypingStoppedFromIncomingMessage(@NonNull Recipient conversationRecipient, @NonNull SignalServiceAddress sender, int device) { private void notifyTypingStoppedFromIncomingMessage(@NonNull Recipient senderRecipient, @NonNull Recipient conversationRecipient, int device) {
Recipient author = Recipient.externalPush(context, sender); long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(conversationRecipient);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(conversationRecipient);
if (threadId > 0 && TextSecurePreferences.isTypingIndicatorsEnabled(context)) { if (threadId > 0 && TextSecurePreferences.isTypingIndicatorsEnabled(context)) {
Log.d(TAG, "Typing stopped on thread " + threadId + " due to an incoming message."); Log.d(TAG, "Typing stopped on thread " + threadId + " due to an incoming message.");
ApplicationDependencies.getTypingStatusRepository().onTypingStopped(context, threadId, author, device, true); ApplicationDependencies.getTypingStatusRepository().onTypingStopped(context, threadId, senderRecipient, device, true);
} }
} }
private boolean shouldIgnore(@Nullable SignalServiceContent content) private boolean shouldIgnore(@NonNull SignalServiceContent content, @NonNull Recipient sender, @NonNull Recipient conversation)
throws BadGroupIdException throws BadGroupIdException
{ {
if (content == null) {
warn("Got a message with null content.");
return true;
}
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
if (content.getDataMessage().isPresent()) { if (content.getDataMessage().isPresent()) {
SignalServiceDataMessage message = content.getDataMessage().get(); SignalServiceDataMessage message = content.getDataMessage().get();
Recipient conversation = getMessageDestination(content, message);
if (conversation.isGroup() && conversation.isBlocked()) { if (conversation.isGroup() && conversation.isBlocked()) {
return true; return true;