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();
|
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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue