Reduce recipient resolves in MessageContentProcessor.
This commit is contained in:
parent
ae4167ddae
commit
1bb87834d8
1 changed files with 183 additions and 198 deletions
|
@ -197,19 +197,23 @@ public final class MessageContentProcessor {
|
|||
Optional<Long> optionalSmsMessageId = smsMessageId > 0 ? Optional.of(smsMessageId) : Optional.absent();
|
||||
|
||||
if (messageState == MessageState.DECRYPTED_OK) {
|
||||
handleMessage(content, timestamp, optionalSmsMessageId);
|
||||
|
||||
if (content != null) {
|
||||
Recipient senderRecipient = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
|
||||
handleMessage(content, timestamp, senderRecipient, optionalSmsMessageId);
|
||||
|
||||
Optional<List<SignalServiceContent>> earlyContent = ApplicationDependencies.getEarlyMessageCache()
|
||||
.retrieve(Recipient.externalPush(context, content.getSender()).getId(),
|
||||
content.getTimestamp());
|
||||
.retrieve(senderRecipient.getId(), content.getTimestamp());
|
||||
if (earlyContent.isPresent()) {
|
||||
log(String.valueOf(content.getTimestamp()), "Found " + earlyContent.get().size() + " dependent item(s) that were retrieved earlier. Processing.");
|
||||
|
||||
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) {
|
||||
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
|
||||
{
|
||||
try {
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
Recipient threadRecipient = getMessageDestination(content);
|
||||
|
||||
if (content == null || shouldIgnore(content)) {
|
||||
log(content != null ? String.valueOf(content.getTimestamp()) : "null", "Ignoring message.");
|
||||
if (shouldIgnore(content, senderRecipient, threadRecipient)) {
|
||||
log(content.getTimestamp(), "Ignoring message.");
|
||||
return;
|
||||
}
|
||||
|
||||
RecipientId senderId = RecipientId.fromHighTrust(content.getSender());
|
||||
PendingRetryReceiptModel pending = ApplicationDependencies.getPendingRetryReceiptCache().get(senderId, content.getTimestamp());
|
||||
long receivedTime = handlePendingRetry(pending, content);
|
||||
PendingRetryReceiptModel pending = ApplicationDependencies.getPendingRetryReceiptCache().get(senderRecipient.getId(), content.getTimestamp());
|
||||
long receivedTime = handlePendingRetry(pending, content, threadRecipient);
|
||||
|
||||
log(String.valueOf(content.getTimestamp()), "Beginning message processing.");
|
||||
|
||||
|
@ -242,13 +245,14 @@ public final class MessageContentProcessor {
|
|||
}
|
||||
|
||||
if (content.getDataMessage().isPresent()) {
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
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();
|
||||
Optional<GroupId> groupId = GroupUtil.idFromGroupContext(message.getGroupContext());
|
||||
boolean isGv2Message = groupId.isPresent() && groupId.get().isV2();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -256,41 +260,39 @@ public final class MessageContentProcessor {
|
|||
MessageId messageId = null;
|
||||
|
||||
if (isInvalidMessage(message)) handleInvalidMessage(content.getSender(), content.getSenderDevice(), groupId, content.getTimestamp(), smsMessageId);
|
||||
else if (message.isEndSession()) messageId = handleEndSessionMessage(content, smsMessageId);
|
||||
else if (message.isGroupV1Update()) handleGroupV1Message(content, message, smsMessageId, groupId.get().requireV1(), receivedTime);
|
||||
else if (message.isExpirationUpdate()) messageId = handleExpirationUpdate(content, message, smsMessageId, groupId, receivedTime);
|
||||
else if (message.getReaction().isPresent()) messageId = handleReaction(content, message);
|
||||
else if (message.getRemoteDelete().isPresent()) messageId = handleRemoteDelete(content, message);
|
||||
else if (message.getPayment().isPresent()) handlePayment(content, message);
|
||||
else if (isMediaMessage) messageId = handleMediaMessage(content, message, smsMessageId, receivedTime);
|
||||
else if (message.getBody().isPresent()) messageId = handleTextMessage(content, message, smsMessageId, groupId, receivedTime);
|
||||
else if (Build.VERSION.SDK_INT > 19 && message.getGroupCallUpdate().isPresent()) handleGroupCallUpdateMessage(content, message, groupId);
|
||||
else if (message.isEndSession()) messageId = handleEndSessionMessage(content, smsMessageId, senderRecipient);
|
||||
else if (message.isGroupV1Update()) handleGroupV1Message(content, message, smsMessageId, groupId.get().requireV1(), senderRecipient, threadRecipient, receivedTime);
|
||||
else if (message.isExpirationUpdate()) messageId = handleExpirationUpdate(content, message, smsMessageId, groupId, senderRecipient, threadRecipient, receivedTime);
|
||||
else if (message.getReaction().isPresent()) messageId = handleReaction(content, message, senderRecipient);
|
||||
else if (message.getRemoteDelete().isPresent()) messageId = handleRemoteDelete(content, message, senderRecipient);
|
||||
else if (message.getPayment().isPresent()) handlePayment(content, message, senderRecipient);
|
||||
else if (isMediaMessage) messageId = handleMediaMessage(content, message, smsMessageId, senderRecipient, threadRecipient, 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, senderRecipient);
|
||||
|
||||
if (groupId.isPresent() && groupDatabase.isUnknownGroup(groupId.get())) {
|
||||
handleUnknownGroupMessage(content, message.getGroupContext().get());
|
||||
handleUnknownGroupMessage(content, message.getGroupContext().get(), senderRecipient);
|
||||
}
|
||||
|
||||
if (message.getProfileKey().isPresent()) {
|
||||
handleProfileKey(content, message.getProfileKey().get());
|
||||
handleProfileKey(content, message.getProfileKey().get(), senderRecipient);
|
||||
}
|
||||
|
||||
if (content.isNeedsReceipt() && messageId != null) {
|
||||
handleNeedsDeliveryReceipt(content, message, messageId);
|
||||
} else if (!content.isNeedsReceipt()) {
|
||||
Recipient sender = getMessageDestination(content, message);
|
||||
|
||||
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 (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 (groupId.isPresent() && groupId.get().isV2()) {
|
||||
Log.i(TAG, "Message was to a GV2 group. Ensuring our group profile keys are up to date.");
|
||||
ApplicationDependencies.getJobManager().startChain(new RefreshAttributesJob(false))
|
||||
.then(GroupV2UpdateSelfProfileKeyJob.withQueueLimits(groupId.get().requireV2()))
|
||||
.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.");
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -300,9 +302,9 @@ public final class MessageContentProcessor {
|
|||
|
||||
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.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.getViewOnceOpen().isPresent()) handleSynchronizeViewOnceOpenMessage(syncMessage.getViewOnceOpen().get(), content.getTimestamp());
|
||||
else if (syncMessage.getVerified().isPresent()) handleSynchronizeVerifiedMessage(syncMessage.getVerified().get());
|
||||
|
@ -324,29 +326,29 @@ public final class MessageContentProcessor {
|
|||
return;
|
||||
}
|
||||
|
||||
if (message.getOfferMessage().isPresent()) handleCallOfferMessage(content, message.getOfferMessage().get(), smsMessageId);
|
||||
else if (message.getAnswerMessage().isPresent()) handleCallAnswerMessage(content, message.getAnswerMessage().get());
|
||||
else if (message.getIceUpdateMessages().isPresent()) handleCallIceUpdateMessage(content, message.getIceUpdateMessages().get());
|
||||
else if (message.getHangupMessage().isPresent()) handleCallHangupMessage(content, message.getHangupMessage().get(), smsMessageId);
|
||||
else if (message.getBusyMessage().isPresent()) handleCallBusyMessage(content, message.getBusyMessage().get());
|
||||
else if (message.getOpaqueMessage().isPresent()) handleCallOpaqueMessage(content, message.getOpaqueMessage().get());
|
||||
if (message.getOfferMessage().isPresent()) handleCallOfferMessage(content, message.getOfferMessage().get(), smsMessageId, senderRecipient);
|
||||
else if (message.getAnswerMessage().isPresent()) handleCallAnswerMessage(content, message.getAnswerMessage().get(), senderRecipient);
|
||||
else if (message.getIceUpdateMessages().isPresent()) handleCallIceUpdateMessage(content, message.getIceUpdateMessages().get(), senderRecipient);
|
||||
else if (message.getHangupMessage().isPresent()) handleCallHangupMessage(content, message.getHangupMessage().get(), smsMessageId, senderRecipient);
|
||||
else if (message.getBusyMessage().isPresent()) handleCallBusyMessage(content, message.getBusyMessage().get(), senderRecipient);
|
||||
else if (message.getOpaqueMessage().isPresent()) handleCallOpaqueMessage(content, message.getOpaqueMessage().get(), senderRecipient);
|
||||
} else if (content.getReceiptMessage().isPresent()) {
|
||||
SignalServiceReceiptMessage message = content.getReceiptMessage().get();
|
||||
|
||||
if (message.isReadReceipt()) handleReadReceipt(content, message);
|
||||
else if (message.isDeliveryReceipt()) handleDeliveryReceipt(content, message);
|
||||
else if (message.isViewedReceipt()) handleViewedReceipt(content, message);
|
||||
if (message.isReadReceipt()) handleReadReceipt(content, message, senderRecipient);
|
||||
else if (message.isDeliveryReceipt()) handleDeliveryReceipt(content, message, senderRecipient);
|
||||
else if (message.isViewedReceipt()) handleViewedReceipt(content, message, senderRecipient);
|
||||
} else if (content.getTypingMessage().isPresent()) {
|
||||
handleTypingMessage(content, content.getTypingMessage().get());
|
||||
handleTypingMessage(content, content.getTypingMessage().get(), senderRecipient);
|
||||
} else if (content.getDecryptionErrorMessage().isPresent()) {
|
||||
handleRetryReceipt(content, content.getDecryptionErrorMessage().get());
|
||||
handleRetryReceipt(content, content.getDecryptionErrorMessage().get(), senderRecipient);
|
||||
} else if (content.getSenderKeyDistributionMessage().isPresent()) {
|
||||
// Already handled, here in order to prevent unrecognized message log
|
||||
} else {
|
||||
warn(String.valueOf(content.getTimestamp()), "Got unrecognized message!");
|
||||
}
|
||||
|
||||
resetRecipientToPush(Recipient.externalPush(context, content.getSender()));
|
||||
resetRecipientToPush(senderRecipient);
|
||||
|
||||
if (pending != null) {
|
||||
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();
|
||||
|
||||
if (pending != null) {
|
||||
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) {
|
||||
ThreadDatabase.ConversationMetadata metadata = DatabaseFactory.getThreadDatabase(context).getConversationMetadata(threadId);
|
||||
|
@ -387,32 +388,31 @@ public final class MessageContentProcessor {
|
|||
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()) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
if (!message.getPayment().get().getPaymentNotification().isPresent()) {
|
||||
Log.w(TAG, "Ignoring payment message without notification");
|
||||
warn(content.getTimestamp(), "Ignoring payment message without notification");
|
||||
return;
|
||||
}
|
||||
|
||||
SignalServiceDataMessage.PaymentNotification paymentNotification = message.getPayment().get().getPaymentNotification().get();
|
||||
PaymentDatabase paymentDatabase = DatabaseFactory.getPaymentDatabase(context);
|
||||
UUID uuid = UUID.randomUUID();
|
||||
Recipient recipient = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
String queue = "Payment_" + PushProcessMessageJob.getQueueName(recipient.getId());
|
||||
String queue = "Payment_" + PushProcessMessageJob.getQueueName(senderRecipient.getId());
|
||||
|
||||
try {
|
||||
paymentDatabase.createIncomingPayment(uuid,
|
||||
recipient.getId(),
|
||||
senderRecipient.getId(),
|
||||
message.getTimestamp(),
|
||||
paymentNotification.getNote(),
|
||||
Money.MobileCoin.ZERO,
|
||||
Money.MobileCoin.ZERO,
|
||||
paymentNotification.getReceipt());
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
@ -425,7 +425,7 @@ public final class MessageContentProcessor {
|
|||
/**
|
||||
* @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
|
||||
{
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
|
@ -440,8 +440,7 @@ public final class MessageContentProcessor {
|
|||
return true;
|
||||
}
|
||||
|
||||
Recipient sender = Recipient.externalPush(context, content.getSender());
|
||||
if (!groupDatabase.isCurrentMember(groupId, sender.getId())) {
|
||||
if (!groupDatabase.isCurrentMember(groupId, senderRecipient.getId())) {
|
||||
log(String.valueOf(content.getTimestamp()), "Ignoring GV2 message from member not in group " + groupId);
|
||||
return true;
|
||||
}
|
||||
|
@ -516,7 +515,7 @@ public final class MessageContentProcessor {
|
|||
case CORRUPT_MESSAGE:
|
||||
case NO_SESSION:
|
||||
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;
|
||||
|
||||
default:
|
||||
|
@ -526,7 +525,8 @@ public final class MessageContentProcessor {
|
|||
|
||||
private void handleCallOfferMessage(@NonNull SignalServiceContent content,
|
||||
@NonNull OfferMessage message,
|
||||
@NonNull Optional<Long> smsMessageId)
|
||||
@NonNull Optional<Long> smsMessageId,
|
||||
@NonNull Recipient senderRecipient)
|
||||
{
|
||||
log(String.valueOf(content.getTimestamp()), "handleCallOfferMessage...");
|
||||
|
||||
|
@ -534,9 +534,8 @@ public final class MessageContentProcessor {
|
|||
MessageDatabase database = DatabaseFactory.getSmsDatabase(context);
|
||||
database.markAsMissedCall(smsMessageId.get(), message.getType() == OfferMessage.Type.VIDEO_CALL);
|
||||
} else {
|
||||
Recipient recipient = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
RemotePeer remotePeer = new RemotePeer(recipient.getId());
|
||||
byte[] remoteIdentityKey = DatabaseFactory.getIdentityDatabase(context).getIdentity(recipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull();
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
|
||||
byte[] remoteIdentityKey = DatabaseFactory.getIdentityDatabase(context).getIdentity(senderRecipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull();
|
||||
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.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,
|
||||
@NonNull AnswerMessage message)
|
||||
@NonNull AnswerMessage message,
|
||||
@NonNull Recipient senderRecipient)
|
||||
{
|
||||
log(String.valueOf(content), "handleCallAnswerMessage...");
|
||||
Recipient recipient = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
RemotePeer remotePeer = new RemotePeer(recipient.getId());
|
||||
byte[] remoteIdentityKey = DatabaseFactory.getIdentityDatabase(context).getIdentity(recipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull();
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
|
||||
byte[] remoteIdentityKey = DatabaseFactory.getIdentityDatabase(context).getIdentity(senderRecipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull();
|
||||
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.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,
|
||||
@NonNull List<IceUpdateMessage> messages)
|
||||
@NonNull List<IceUpdateMessage> messages,
|
||||
@NonNull Recipient senderRecipient)
|
||||
{
|
||||
log(String.valueOf(content), "handleCallIceUpdateMessage... " + messages.size());
|
||||
|
||||
|
@ -575,7 +575,7 @@ public final class MessageContentProcessor {
|
|||
callId = iceMessage.getId();
|
||||
}
|
||||
|
||||
RemotePeer remotePeer = new RemotePeer(Recipient.externalHighTrustPush(context, content.getSender()).getId());
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
|
||||
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.receivedIceCandidates(new WebRtcData.CallMetadata(remotePeer, new CallId(callId), content.getSenderDevice()),
|
||||
|
@ -584,13 +584,14 @@ public final class MessageContentProcessor {
|
|||
|
||||
private void handleCallHangupMessage(@NonNull SignalServiceContent content,
|
||||
@NonNull HangupMessage message,
|
||||
@NonNull Optional<Long> smsMessageId)
|
||||
@NonNull Optional<Long> smsMessageId,
|
||||
@NonNull Recipient senderRecipient)
|
||||
{
|
||||
log(String.valueOf(content), "handleCallHangupMessage");
|
||||
if (smsMessageId.isPresent()) {
|
||||
DatabaseFactory.getSmsDatabase(context).markAsMissedCall(smsMessageId.get(), false);
|
||||
} else {
|
||||
RemotePeer remotePeer = new RemotePeer(Recipient.externalHighTrustPush(context, content.getSender()).getId());
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
|
||||
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.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,
|
||||
@NonNull BusyMessage message)
|
||||
@NonNull BusyMessage message,
|
||||
@NonNull Recipient senderRecipient)
|
||||
{
|
||||
log(String.valueOf(content.getTimestamp()), "handleCallBusyMessage");
|
||||
|
||||
RemotePeer remotePeer = new RemotePeer(Recipient.externalHighTrustPush(context, content.getSender()).getId());
|
||||
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId());
|
||||
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.receivedCallBusy(new WebRtcData.CallMetadata(remotePeer, new CallId(message.getId()), content.getSenderDevice()));
|
||||
}
|
||||
|
||||
private void handleCallOpaqueMessage(@NonNull SignalServiceContent content,
|
||||
@NonNull OpaqueMessage message)
|
||||
@NonNull OpaqueMessage message,
|
||||
@NonNull Recipient senderRecipient)
|
||||
{
|
||||
log(String.valueOf(content.getTimestamp()), "handleCallOpaqueMessage");
|
||||
|
||||
|
@ -620,7 +623,7 @@ public final class MessageContentProcessor {
|
|||
}
|
||||
|
||||
ApplicationDependencies.getSignalCallManager()
|
||||
.receivedOpaqueMessage(new WebRtcData.OpaqueMessageMetadata(Recipient.externalHighTrustPush(context, content.getSender()).requireUuid(),
|
||||
.receivedOpaqueMessage(new WebRtcData.OpaqueMessageMetadata(senderRecipient.requireUuid(),
|
||||
message.getOpaque(),
|
||||
content.getSenderDevice(),
|
||||
messageAgeSeconds));
|
||||
|
@ -628,7 +631,8 @@ public final class MessageContentProcessor {
|
|||
|
||||
private void handleGroupCallUpdateMessage(@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceDataMessage message,
|
||||
@NonNull Optional<GroupId> groupId)
|
||||
@NonNull Optional<GroupId> groupId,
|
||||
@NonNull Recipient senderRecipient)
|
||||
{
|
||||
if (!groupId.isPresent() || !groupId.get().isV2()) {
|
||||
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());
|
||||
|
||||
DatabaseFactory.getSmsDatabase(context).insertOrUpdateGroupCall(groupRecipientId,
|
||||
RecipientId.from(content.getSender()),
|
||||
content.getServerReceivedTimestamp(),
|
||||
message.getGroupCallUpdate().get().getEraId());
|
||||
senderRecipient.getId(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
message.getGroupCallUpdate().get().getEraId());
|
||||
|
||||
GroupCallPeekJob.enqueue(groupRecipientId);
|
||||
}
|
||||
|
||||
private @Nullable MessageId handleEndSessionMessage(@NonNull SignalServiceContent content,
|
||||
@NonNull Optional<Long> smsMessageId)
|
||||
@NonNull Optional<Long> smsMessageId,
|
||||
@NonNull Recipient senderRecipient)
|
||||
{
|
||||
MessageDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(Recipient.externalHighTrustPush(context, content.getSender()).getId(),
|
||||
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(senderRecipient.getId(),
|
||||
content.getSenderDevice(),
|
||||
content.getTimestamp(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
|
@ -713,13 +718,15 @@ public final class MessageContentProcessor {
|
|||
@NonNull SignalServiceDataMessage message,
|
||||
@NonNull Optional<Long> smsMessageId,
|
||||
@NonNull GroupId.V1 groupId,
|
||||
@NonNull Recipient senderRecipient,
|
||||
@NonNull Recipient threadRecipient,
|
||||
long receivedTime)
|
||||
throws StorageFailedException, BadGroupIdException
|
||||
{
|
||||
GroupV1MessageProcessor.process(context, content, message, false);
|
||||
|
||||
if (message.getExpiresInSeconds() != 0 && message.getExpiresInSeconds() != getMessageDestination(content, message).getExpireMessages()) {
|
||||
handleExpirationUpdate(content, message, Optional.absent(), Optional.of(groupId), receivedTime);
|
||||
if (message.getExpiresInSeconds() != 0 && message.getExpiresInSeconds() != threadRecipient.getExpireMessages()) {
|
||||
handleExpirationUpdate(content, message, Optional.absent(), Optional.of(groupId), senderRecipient, threadRecipient, receivedTime);
|
||||
}
|
||||
|
||||
if (smsMessageId.isPresent()) {
|
||||
|
@ -728,13 +735,14 @@ public final class MessageContentProcessor {
|
|||
}
|
||||
|
||||
private void handleUnknownGroupMessage(@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceGroupContext group)
|
||||
@NonNull SignalServiceGroupContext group,
|
||||
@NonNull Recipient senderRecipient)
|
||||
throws BadGroupIdException
|
||||
{
|
||||
if (group.getGroupV1().isPresent()) {
|
||||
SignalServiceGroup groupV1 = group.getGroupV1().get();
|
||||
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 {
|
||||
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 Optional<Long> smsMessageId,
|
||||
@NonNull Optional<GroupId> groupId,
|
||||
@NonNull Recipient senderRecipient,
|
||||
@NonNull Recipient threadRecipient,
|
||||
long receivedTime)
|
||||
throws StorageFailedException, BadGroupIdException
|
||||
throws StorageFailedException
|
||||
{
|
||||
if (groupId.isPresent() && groupId.get().isV2()) {
|
||||
warn(String.valueOf(content.getTimestamp()), "Expiration update received for GV2. Ignoring.");
|
||||
|
@ -760,17 +770,15 @@ public final class MessageContentProcessor {
|
|||
|
||||
int expiresInSeconds = message.getExpiresInSeconds();
|
||||
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.");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
MessageDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(sender.getId(),
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(senderRecipient.getId(),
|
||||
content.getTimestamp(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
receivedTime,
|
||||
|
@ -791,7 +799,7 @@ public final class MessageContentProcessor {
|
|||
|
||||
Optional<InsertResult> insertResult = database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
|
||||
|
||||
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(recipient.getId(), expiresInSeconds);
|
||||
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(threadRecipient.getId(), expiresInSeconds);
|
||||
|
||||
if (smsMessageId.isPresent()) {
|
||||
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
|
||||
|
@ -807,7 +815,7 @@ public final class MessageContentProcessor {
|
|||
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();
|
||||
|
||||
if (!EmojiUtil.isEmoji(reaction.getEmoji())) {
|
||||
|
@ -815,7 +823,6 @@ public final class MessageContentProcessor {
|
|||
return null;
|
||||
}
|
||||
|
||||
Recipient reactionAuthor = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
Recipient targetAuthor = Recipient.externalPush(context, reaction.getTargetAuthor());
|
||||
MessageRecord targetMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(reaction.getTargetSentTimestamp(), targetAuthor.getId());
|
||||
|
||||
|
@ -839,12 +846,12 @@ public final class MessageContentProcessor {
|
|||
|
||||
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());
|
||||
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());
|
||||
return null;
|
||||
}
|
||||
|
@ -852,10 +859,10 @@ public final class MessageContentProcessor {
|
|||
MessageDatabase db = targetMessage.isMms() ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context);
|
||||
|
||||
if (reaction.isRemove()) {
|
||||
db.deleteReaction(targetMessage.getId(), reactionAuthor.getId());
|
||||
db.deleteReaction(targetMessage.getId(), senderRecipient.getId());
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||
} 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);
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false);
|
||||
}
|
||||
|
@ -863,24 +870,23 @@ public final class MessageContentProcessor {
|
|||
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();
|
||||
|
||||
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
MessageRecord targetMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(delete.getTargetSentTimestamp(), sender.getId());
|
||||
MessageRecord targetMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(delete.getTargetSentTimestamp(), senderRecipient.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);
|
||||
db.markAsRemoteDelete(targetMessage.getId());
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false);
|
||||
return new MessageId(targetMessage.getId(), targetMessage.isMms());
|
||||
} else if (targetMessage == null) {
|
||||
warn(String.valueOf(content.getTimestamp()), "[handleRemoteDelete] Could not find matching message! timestamp: " + delete.getTargetSentTimestamp() + " author: " + sender.getId());
|
||||
ApplicationDependencies.getEarlyMessageCache().store(sender.getId(), delete.getTargetSentTimestamp(), content);
|
||||
warn(String.valueOf(content.getTimestamp()), "[handleRemoteDelete] Could not find matching message! timestamp: " + delete.getTargetSentTimestamp() + " author: " + senderRecipient.getId());
|
||||
ApplicationDependencies.getEarlyMessageCache().store(senderRecipient.getId(), delete.getTargetSentTimestamp(), content);
|
||||
return null;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -952,7 +958,7 @@ public final class MessageContentProcessor {
|
|||
throws BadGroupIdException
|
||||
{
|
||||
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
||||
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||
|
||||
Recipient recipient;
|
||||
|
||||
|
@ -1025,7 +1031,8 @@ public final class MessageContentProcessor {
|
|||
}
|
||||
|
||||
private void handleSynchronizeSentMessage(@NonNull SignalServiceContent content,
|
||||
@NonNull SentTranscriptMessage message)
|
||||
@NonNull SentTranscriptMessage message,
|
||||
@NonNull Recipient senderRecipient)
|
||||
throws StorageFailedException, BadGroupIdException, IOException, GroupChangeBusyException
|
||||
{
|
||||
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()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1053,16 +1060,16 @@ public final class MessageContentProcessor {
|
|||
handleSynchronizeSentGv2Update(content, message);
|
||||
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(getSyncMessageDestination(message));
|
||||
} 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()) {
|
||||
warn(content.getTimestamp(), "Empty GV2 message! Doing nothing.");
|
||||
} else if (message.getMessage().isExpirationUpdate()) {
|
||||
threadId = handleSynchronizeSentExpirationUpdate(message);
|
||||
} else if (message.getMessage().getReaction().isPresent()) {
|
||||
handleReaction(content, message.getMessage());
|
||||
handleReaction(content, message.getMessage(), senderRecipient);
|
||||
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(getSyncMessageDestination(message));
|
||||
} 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()) {
|
||||
threadId = handleSynchronizeSentMediaMessage(message);
|
||||
} else {
|
||||
|
@ -1070,7 +1077,7 @@ public final class MessageContentProcessor {
|
|||
}
|
||||
|
||||
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()) {
|
||||
|
@ -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<>();
|
||||
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,
|
||||
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,
|
||||
threadToLatestRead);
|
||||
|
||||
|
@ -1210,10 +1217,12 @@ public final class MessageContentProcessor {
|
|||
private @Nullable MessageId handleMediaMessage(@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceDataMessage message,
|
||||
@NonNull Optional<Long> smsMessageId,
|
||||
@NonNull Recipient senderRecipient,
|
||||
@NonNull Recipient threadRecipient,
|
||||
long receivedTime)
|
||||
throws StorageFailedException, BadGroupIdException
|
||||
throws StorageFailedException
|
||||
{
|
||||
notifyTypingStoppedFromIncomingMessage(getMessageDestination(content, message), content.getSender(), content.getSenderDevice());
|
||||
notifyTypingStoppedFromIncomingMessage(senderRecipient, threadRecipient, content.getSenderDevice());
|
||||
|
||||
Optional<InsertResult> insertResult;
|
||||
|
||||
|
@ -1227,7 +1236,7 @@ public final class MessageContentProcessor {
|
|||
Optional<List<Mention>> mentions = getMentions(message.getMentions());
|
||||
Optional<Attachment> sticker = getStickerAttachment(message.getSticker());
|
||||
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(RecipientId.fromHighTrust(content.getSender()),
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(senderRecipient.getId(),
|
||||
message.getTimestamp(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
receivedTime,
|
||||
|
@ -1414,18 +1423,18 @@ public final class MessageContentProcessor {
|
|||
}
|
||||
|
||||
private void updateGroupReceiptStatus(@NonNull SentTranscriptMessage message, long messageId, @NonNull GroupId groupString) {
|
||||
GroupReceiptDatabase receiptDatabase = DatabaseFactory.getGroupReceiptDatabase(context);
|
||||
List<Recipient> messageRecipients = Stream.of(message.getRecipients()).map(address -> Recipient.externalPush(context, address)).toList();
|
||||
List<Recipient> members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupString, GroupDatabase.MemberSet.FULL_MEMBERS_EXCLUDING_SELF);
|
||||
Map<RecipientId, Integer> localReceipts = Stream.of(receiptDatabase.getGroupReceiptInfo(messageId))
|
||||
.collect(Collectors.toMap(GroupReceiptInfo::getRecipientId, GroupReceiptInfo::getStatus));
|
||||
GroupReceiptDatabase receiptDatabase = DatabaseFactory.getGroupReceiptDatabase(context);
|
||||
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);
|
||||
Map<RecipientId, Integer> localReceipts = Stream.of(receiptDatabase.getGroupReceiptInfo(messageId))
|
||||
.collect(Collectors.toMap(GroupReceiptInfo::getRecipientId, GroupReceiptInfo::getStatus));
|
||||
|
||||
for (Recipient messageRecipient : messageRecipients) {
|
||||
for (RecipientId messageRecipientId : messageRecipientIds) {
|
||||
//noinspection ConstantConditions
|
||||
if (localReceipts.containsKey(messageRecipient.getId()) && localReceipts.get(messageRecipient.getId()) < GroupReceiptDatabase.STATUS_UNDELIVERED) {
|
||||
receiptDatabase.update(messageRecipient.getId(), messageId, GroupReceiptDatabase.STATUS_UNDELIVERED, message.getTimestamp());
|
||||
} else if (!localReceipts.containsKey(messageRecipient.getId())) {
|
||||
receiptDatabase.insert(Collections.singletonList(messageRecipient.getId()), messageId, GroupReceiptDatabase.STATUS_UNDELIVERED, message.getTimestamp());
|
||||
if (localReceipts.containsKey(messageRecipientId) && localReceipts.get(messageRecipientId) < GroupReceiptDatabase.STATUS_UNDELIVERED) {
|
||||
receiptDatabase.update(messageRecipientId, messageId, GroupReceiptDatabase.STATUS_UNDELIVERED, message.getTimestamp());
|
||||
} else if (!localReceipts.containsKey(messageRecipientId)) {
|
||||
receiptDatabase.insert(Collections.singletonList(messageRecipientId), messageId, GroupReceiptDatabase.STATUS_UNDELIVERED, message.getTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1439,15 +1448,16 @@ public final class MessageContentProcessor {
|
|||
@NonNull SignalServiceDataMessage message,
|
||||
@NonNull Optional<Long> smsMessageId,
|
||||
@NonNull Optional<GroupId> groupId,
|
||||
@NonNull Recipient senderRecipient,
|
||||
@NonNull Recipient threadRecipient,
|
||||
long receivedTime)
|
||||
throws StorageFailedException, BadGroupIdException
|
||||
throws StorageFailedException
|
||||
{
|
||||
MessageDatabase database = DatabaseFactory.getSmsDatabase(context);
|
||||
String body = message.getBody().isPresent() ? message.getBody().get() : "";
|
||||
Recipient recipient = getMessageDestination(content, message);
|
||||
MessageDatabase database = DatabaseFactory.getSmsDatabase(context);
|
||||
String body = message.getBody().isPresent() ? message.getBody().get() : "";
|
||||
|
||||
if (message.getExpiresInSeconds() != recipient.getExpireMessages()) {
|
||||
handleExpirationUpdate(content, message, Optional.absent(), groupId, receivedTime);
|
||||
if (message.getExpiresInSeconds() != threadRecipient.getExpireMessages()) {
|
||||
handleExpirationUpdate(content, message, Optional.absent(), groupId, senderRecipient, threadRecipient, receivedTime);
|
||||
}
|
||||
|
||||
Optional<InsertResult> insertResult;
|
||||
|
@ -1455,9 +1465,9 @@ public final class MessageContentProcessor {
|
|||
if (smsMessageId.isPresent() && !message.getGroupContext().isPresent()) {
|
||||
insertResult = Optional.of(database.updateBundleMessageBody(smsMessageId.get(), body));
|
||||
} 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(),
|
||||
message.getTimestamp(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
|
@ -1635,15 +1645,15 @@ public final class MessageContentProcessor {
|
|||
}
|
||||
|
||||
private void handleProfileKey(@NonNull SignalServiceContent content,
|
||||
@NonNull byte[] messageProfileKeyBytes)
|
||||
@NonNull byte[] messageProfileKeyBytes,
|
||||
@NonNull Recipient senderRecipient)
|
||||
{
|
||||
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 (database.setProfileKey(recipient.getId(), messageProfileKey)) {
|
||||
ApplicationDependencies.getJobManager().add(RetrieveProfileJob.forRecipient(recipient.getId()));
|
||||
if (database.setProfileKey(senderRecipient.getId(), messageProfileKey)) {
|
||||
ApplicationDependencies.getJobManager().add(RetrieveProfileJob.forRecipient(senderRecipient.getId()));
|
||||
}
|
||||
} else {
|
||||
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,
|
||||
@NonNull SignalServiceReceiptMessage message)
|
||||
@NonNull SignalServiceReceiptMessage message,
|
||||
@NonNull Recipient senderRecipient)
|
||||
{
|
||||
if (!TextSecurePreferences.isReadReceiptsEnabled(context)) {
|
||||
log("Ignoring viewed receipts for IDs: " + Util.join(message.getTimestamps(), ", "));
|
||||
return;
|
||||
}
|
||||
|
||||
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
log(TAG, "Processing viewed receipts. Sender: " + sender.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
|
||||
log(TAG, "Processing viewed receipts. Sender: " + senderRecipient.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
|
||||
|
||||
List<SyncMessageId> ids = Stream.of(message.getTimestamps())
|
||||
.map(t -> new SyncMessageId(sender.getId(), t))
|
||||
.map(t -> new SyncMessageId(senderRecipient.getId(), t))
|
||||
.toList();
|
||||
|
||||
Collection<SyncMessageId> unhandled = DatabaseFactory.getMmsSmsDatabase(context)
|
||||
.incrementViewedReceiptCounts(ids, content.getTimestamp());
|
||||
|
||||
for (SyncMessageId id : unhandled) {
|
||||
warn(String.valueOf(content.getTimestamp()), "[handleViewedReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + " author: " + sender.getId());
|
||||
ApplicationDependencies.getEarlyMessageCache().store(sender.getId(), id.getTimetamp(), content);
|
||||
warn(String.valueOf(content.getTimestamp()), "[handleViewedReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + " author: " + senderRecipient.getId());
|
||||
ApplicationDependencies.getEarlyMessageCache().store(senderRecipient.getId(), id.getTimetamp(), content);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
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: " + sender.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
|
||||
log(TAG, "Processing delivery receipts. Sender: " + senderRecipient.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
|
||||
|
||||
List<SyncMessageId> ids = Stream.of(message.getTimestamps())
|
||||
.map(t -> new SyncMessageId(sender.getId(), t))
|
||||
.map(t -> new SyncMessageId(senderRecipient.getId(), t))
|
||||
.toList();
|
||||
|
||||
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")
|
||||
private void handleReadReceipt(@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceReceiptMessage message)
|
||||
@NonNull SignalServiceReceiptMessage message,
|
||||
@NonNull Recipient senderRecipient)
|
||||
{
|
||||
if (!TextSecurePreferences.isReadReceiptsEnabled(context)) {
|
||||
log("Ignoring read receipts for IDs: " + Util.join(message.getTimestamps(), ", "));
|
||||
return;
|
||||
}
|
||||
|
||||
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
log(TAG, "Processing read receipts. Sender: " + sender.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
|
||||
log(TAG, "Processing read receipts. Sender: " + senderRecipient.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
|
||||
|
||||
List<SyncMessageId> ids = Stream.of(message.getTimestamps())
|
||||
.map(t -> new SyncMessageId(sender.getId(), t))
|
||||
.map(t -> new SyncMessageId(senderRecipient.getId(), t))
|
||||
.toList();
|
||||
|
||||
Collection<SyncMessageId> unhandled = DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCounts(ids, content.getTimestamp());
|
||||
|
||||
for (SyncMessageId id : unhandled) {
|
||||
warn(String.valueOf(content.getTimestamp()), "[handleReadReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + " author: " + sender.getId());
|
||||
ApplicationDependencies.getEarlyMessageCache().store(sender.getId(), id.getTimetamp(), content);
|
||||
warn(String.valueOf(content.getTimestamp()), "[handleReadReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + " author: " + senderRecipient.getId());
|
||||
ApplicationDependencies.getEarlyMessageCache().store(senderRecipient.getId(), id.getTimetamp(), content);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleTypingMessage(@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceTypingMessage typingMessage)
|
||||
@NonNull SignalServiceTypingMessage typingMessage,
|
||||
@NonNull Recipient senderRecipient)
|
||||
throws BadGroupIdException
|
||||
{
|
||||
if (!TextSecurePreferences.isTypingIndicatorsEnabled(context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Recipient author = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
|
||||
long threadId;
|
||||
|
||||
if (typingMessage.getGroupId().isPresent()) {
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
@ -1750,7 +1759,7 @@ public final class MessageContentProcessor {
|
|||
|
||||
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
|
||||
} else {
|
||||
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(author);
|
||||
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(senderRecipient);
|
||||
}
|
||||
|
||||
if (threadId <= 0) {
|
||||
|
@ -1760,35 +1769,34 @@ public final class MessageContentProcessor {
|
|||
|
||||
if (typingMessage.isTypingStarted()) {
|
||||
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 {
|
||||
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()) {
|
||||
warn(String.valueOf(content.getTimestamp()), "[RetryReceipt] Sender key not enabled, skipping retry receipt.");
|
||||
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()) {
|
||||
warn(content.getTimestamp(), "[RetryReceipt] Requester " + requester.getId() + " somehow has no UUID! timestamp: " + sentTimestamp);
|
||||
if (!senderRecipient.hasUuid()) {
|
||||
warn(content.getTimestamp(), "[RetryReceipt] Requester " + senderRecipient.getId() + " somehow has no UUID! timestamp: " + sentTimestamp);
|
||||
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()) {
|
||||
handleIndividualRetryReceipt(requester, messageLogEntry, content, decryptionErrorMessage);
|
||||
handleIndividualRetryReceipt(senderRecipient, messageLogEntry, content, decryptionErrorMessage);
|
||||
} 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()));
|
||||
}
|
||||
|
||||
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)
|
||||
throws BadGroupIdException
|
||||
{
|
||||
|
@ -2111,29 +2105,20 @@ public final class MessageContentProcessor {
|
|||
return Optional.absent();
|
||||
}
|
||||
|
||||
private void notifyTypingStoppedFromIncomingMessage(@NonNull Recipient conversationRecipient, @NonNull SignalServiceAddress sender, int device) {
|
||||
Recipient author = Recipient.externalPush(context, sender);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(conversationRecipient);
|
||||
private void notifyTypingStoppedFromIncomingMessage(@NonNull Recipient senderRecipient, @NonNull Recipient conversationRecipient, int device) {
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(conversationRecipient);
|
||||
|
||||
if (threadId > 0 && TextSecurePreferences.isTypingIndicatorsEnabled(context)) {
|
||||
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
|
||||
{
|
||||
if (content == null) {
|
||||
warn("Got a message with null content.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
|
||||
if (content.getDataMessage().isPresent()) {
|
||||
SignalServiceDataMessage message = content.getDataMessage().get();
|
||||
Recipient conversation = getMessageDestination(content, message);
|
||||
SignalServiceDataMessage message = content.getDataMessage().get();
|
||||
|
||||
if (conversation.isGroup() && conversation.isBlocked()) {
|
||||
return true;
|
||||
|
|
Loading…
Add table
Reference in a new issue