mirror of
https://github.com/oxen-io/session-android.git
synced 2023-12-14 02:53:01 +01:00
1) The group ID for jobs that process received messages was previously set to the sender's e164. This guaranteed serialization of messages per-recipient, while allowing processing of multiple recipients in parallel. Unfortunately in the case of groups, this results in out of order conversations, since the "sender" for each message is different. And we can't determine that it was a group message until *after* we process it. So this change just puts all message processing from all senders in one big queue. 2) Synchronization messages were always being displayed before received messages, due to the "received time" for those being set to the time they were sent. Fixes #3618 Fixes #2385 // FREEBIE
481 lines
24 KiB
Java
481 lines
24 KiB
Java
package org.thoughtcrime.securesms.jobs;
|
|
|
|
import android.content.Context;
|
|
import android.support.annotation.NonNull;
|
|
import android.util.Log;
|
|
import android.util.Pair;
|
|
|
|
import org.thoughtcrime.securesms.ApplicationContext;
|
|
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
|
import org.thoughtcrime.securesms.attachments.PointerAttachment;
|
|
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
|
|
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
|
import org.thoughtcrime.securesms.crypto.SecurityEvent;
|
|
import org.thoughtcrime.securesms.crypto.storage.TextSecureAxolotlStore;
|
|
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
|
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
|
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
|
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
|
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
|
import org.thoughtcrime.securesms.database.PushDatabase;
|
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
|
import org.thoughtcrime.securesms.groups.GroupMessageProcessor;
|
|
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
|
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
|
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
|
import org.thoughtcrime.securesms.recipients.Recipients;
|
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
|
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage;
|
|
import org.thoughtcrime.securesms.sms.IncomingEndSessionMessage;
|
|
import org.thoughtcrime.securesms.sms.IncomingPreKeyBundleMessage;
|
|
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
|
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
|
import org.thoughtcrime.securesms.util.Base64;
|
|
import org.thoughtcrime.securesms.util.GroupUtil;
|
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
|
import org.whispersystems.jobqueue.JobParameters;
|
|
import org.whispersystems.libaxolotl.DuplicateMessageException;
|
|
import org.whispersystems.libaxolotl.IdentityKey;
|
|
import org.whispersystems.libaxolotl.InvalidKeyException;
|
|
import org.whispersystems.libaxolotl.InvalidKeyIdException;
|
|
import org.whispersystems.libaxolotl.InvalidMessageException;
|
|
import org.whispersystems.libaxolotl.InvalidVersionException;
|
|
import org.whispersystems.libaxolotl.LegacyMessageException;
|
|
import org.whispersystems.libaxolotl.NoSessionException;
|
|
import org.whispersystems.libaxolotl.UntrustedIdentityException;
|
|
import org.whispersystems.libaxolotl.protocol.PreKeyWhisperMessage;
|
|
import org.whispersystems.libaxolotl.state.AxolotlStore;
|
|
import org.whispersystems.libaxolotl.state.SessionStore;
|
|
import org.whispersystems.libaxolotl.util.guava.Optional;
|
|
import org.whispersystems.textsecure.api.crypto.TextSecureCipher;
|
|
import org.whispersystems.textsecure.api.messages.TextSecureContent;
|
|
import org.whispersystems.textsecure.api.messages.TextSecureDataMessage;
|
|
import org.whispersystems.textsecure.api.messages.TextSecureEnvelope;
|
|
import org.whispersystems.textsecure.api.messages.TextSecureGroup;
|
|
import org.whispersystems.textsecure.api.messages.multidevice.RequestMessage;
|
|
import org.whispersystems.textsecure.api.messages.multidevice.SentTranscriptMessage;
|
|
import org.whispersystems.textsecure.api.messages.multidevice.TextSecureSyncMessage;
|
|
import org.whispersystems.textsecure.api.push.TextSecureAddress;
|
|
|
|
import java.util.List;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import ws.com.google.android.mms.MmsException;
|
|
|
|
public class PushDecryptJob extends ContextJob {
|
|
|
|
private static final long serialVersionUID = 2L;
|
|
|
|
public static final String TAG = PushDecryptJob.class.getSimpleName();
|
|
|
|
private final long messageId;
|
|
private final long smsMessageId;
|
|
|
|
public PushDecryptJob(Context context, long pushMessageId, String sender) {
|
|
this(context, pushMessageId, -1, sender);
|
|
}
|
|
|
|
public PushDecryptJob(Context context, long pushMessageId, long smsMessageId, String sender) {
|
|
super(context, JobParameters.newBuilder()
|
|
.withPersistence()
|
|
.withGroupId("__PUSH_DECRYPT_JOB__")
|
|
.withWakeLock(true, 5, TimeUnit.SECONDS)
|
|
.create());
|
|
this.messageId = pushMessageId;
|
|
this.smsMessageId = smsMessageId;
|
|
}
|
|
|
|
@Override
|
|
public void onAdded() {}
|
|
|
|
@Override
|
|
public void onRun() throws NoSuchMessageException {
|
|
|
|
if (!IdentityKeyUtil.hasIdentityKey(context)) {
|
|
Log.w(TAG, "Skipping job, waiting for migration...");
|
|
MessageNotifier.updateNotification(context, null, true, -2);
|
|
return;
|
|
}
|
|
|
|
MasterSecret masterSecret = KeyCachingService.getMasterSecret(context);
|
|
PushDatabase database = DatabaseFactory.getPushDatabase(context);
|
|
TextSecureEnvelope envelope = database.get(messageId);
|
|
Optional<Long> optionalSmsMessageId = smsMessageId > 0 ? Optional.of(smsMessageId) :
|
|
Optional.<Long>absent();
|
|
|
|
MasterSecretUnion masterSecretUnion;
|
|
|
|
if (masterSecret == null) masterSecretUnion = new MasterSecretUnion(MasterSecretUtil.getAsymmetricMasterSecret(context, null));
|
|
else masterSecretUnion = new MasterSecretUnion(masterSecret);
|
|
|
|
handleMessage(masterSecretUnion, envelope, optionalSmsMessageId);
|
|
database.delete(messageId);
|
|
}
|
|
|
|
@Override
|
|
public boolean onShouldRetry(Exception exception) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void onCanceled() {
|
|
|
|
}
|
|
|
|
private void handleMessage(MasterSecretUnion masterSecret, TextSecureEnvelope envelope, Optional<Long> smsMessageId) {
|
|
try {
|
|
AxolotlStore axolotlStore = new TextSecureAxolotlStore(context);
|
|
TextSecureAddress localAddress = new TextSecureAddress(TextSecurePreferences.getLocalNumber(context));
|
|
TextSecureCipher cipher = new TextSecureCipher(localAddress, axolotlStore);
|
|
|
|
TextSecureContent content = cipher.decrypt(envelope);
|
|
|
|
if (content.getDataMessage().isPresent()) {
|
|
TextSecureDataMessage message = content.getDataMessage().get();
|
|
|
|
if (message.isEndSession()) handleEndSessionMessage(masterSecret, envelope, message, smsMessageId);
|
|
else if (message.isGroupUpdate()) handleGroupMessage(masterSecret, envelope, message, smsMessageId);
|
|
else if (message.getAttachments().isPresent()) handleMediaMessage(masterSecret, envelope, message, smsMessageId);
|
|
else handleTextMessage(masterSecret, envelope, message, smsMessageId);
|
|
} else if (content.getSyncMessage().isPresent()) {
|
|
TextSecureSyncMessage syncMessage = content.getSyncMessage().get();
|
|
|
|
if (syncMessage.getSent().isPresent()) handleSynchronizeSentMessage(masterSecret, envelope, syncMessage.getSent().get(), smsMessageId);
|
|
else if (syncMessage.getRequest().isPresent()) handleSynchronizeRequestMessage(masterSecret, syncMessage.getRequest().get());
|
|
}
|
|
|
|
if (envelope.isPreKeyWhisperMessage()) {
|
|
ApplicationContext.getInstance(context).getJobManager().add(new RefreshPreKeysJob(context));
|
|
}
|
|
} catch (InvalidVersionException e) {
|
|
Log.w(TAG, e);
|
|
handleInvalidVersionMessage(masterSecret, envelope, smsMessageId);
|
|
} catch (InvalidMessageException | InvalidKeyIdException | InvalidKeyException | MmsException e) {
|
|
Log.w(TAG, e);
|
|
handleCorruptMessage(masterSecret, envelope, smsMessageId);
|
|
} catch (NoSessionException e) {
|
|
Log.w(TAG, e);
|
|
handleNoSessionMessage(masterSecret, envelope, smsMessageId);
|
|
} catch (LegacyMessageException e) {
|
|
Log.w(TAG, e);
|
|
handleLegacyMessage(masterSecret, envelope, smsMessageId);
|
|
} catch (DuplicateMessageException e) {
|
|
Log.w(TAG, e);
|
|
handleDuplicateMessage(masterSecret, envelope, smsMessageId);
|
|
} catch (UntrustedIdentityException e) {
|
|
Log.w(TAG, e);
|
|
handleUntrustedIdentityMessage(masterSecret, envelope, smsMessageId);
|
|
}
|
|
}
|
|
|
|
private void handleEndSessionMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull TextSecureEnvelope envelope,
|
|
@NonNull TextSecureDataMessage message,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
{
|
|
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
|
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(envelope.getSource(),
|
|
envelope.getSourceDevice(),
|
|
message.getTimestamp(),
|
|
"", Optional.<TextSecureGroup>absent());
|
|
|
|
long threadId;
|
|
|
|
if (!smsMessageId.isPresent()) {
|
|
IncomingEndSessionMessage incomingEndSessionMessage = new IncomingEndSessionMessage(incomingTextMessage);
|
|
Pair<Long, Long> messageAndThreadId = smsDatabase.insertMessageInbox(masterSecret, incomingEndSessionMessage);
|
|
|
|
threadId = messageAndThreadId.second;
|
|
} else {
|
|
smsDatabase.markAsEndSession(smsMessageId.get());
|
|
threadId = smsDatabase.getThreadIdForMessage(smsMessageId.get());
|
|
}
|
|
|
|
SessionStore sessionStore = new TextSecureSessionStore(context);
|
|
sessionStore.deleteAllSessions(envelope.getSource());
|
|
|
|
SecurityEvent.broadcastSecurityUpdateEvent(context);
|
|
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), threadId);
|
|
}
|
|
|
|
private void handleGroupMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull TextSecureEnvelope envelope,
|
|
@NonNull TextSecureDataMessage message,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
{
|
|
GroupMessageProcessor.process(context, masterSecret, envelope, message, false);
|
|
|
|
if (smsMessageId.isPresent()) {
|
|
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
|
|
}
|
|
}
|
|
|
|
private void handleSynchronizeSentMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull TextSecureEnvelope envelope,
|
|
@NonNull SentTranscriptMessage message,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
throws MmsException
|
|
{
|
|
if (message.getMessage().isGroupUpdate()) {
|
|
GroupMessageProcessor.process(context, masterSecret, envelope, message.getMessage(), true);
|
|
} else if (message.getMessage().getAttachments().isPresent()) {
|
|
handleSynchronizeSentMediaMessage(masterSecret, message, smsMessageId);
|
|
} else {
|
|
handleSynchronizeSentTextMessage(masterSecret, message, smsMessageId);
|
|
}
|
|
}
|
|
|
|
private void handleSynchronizeRequestMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull RequestMessage message)
|
|
{
|
|
if (message.isContactsRequest()) {
|
|
ApplicationContext.getInstance(context)
|
|
.getJobManager()
|
|
.add(new MultiDeviceContactUpdateJob(getContext()));
|
|
}
|
|
|
|
if (message.isGroupsRequest()) {
|
|
ApplicationContext.getInstance(context)
|
|
.getJobManager()
|
|
.add(new MultiDeviceGroupUpdateJob(getContext()));
|
|
}
|
|
}
|
|
|
|
private void handleMediaMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull TextSecureEnvelope envelope,
|
|
@NonNull TextSecureDataMessage message,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
throws MmsException
|
|
{
|
|
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
|
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
|
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret, envelope.getSource(),
|
|
localNumber, message.getTimestamp(),
|
|
Optional.fromNullable(envelope.getRelay()),
|
|
message.getBody(),
|
|
message.getGroupInfo(),
|
|
message.getAttachments());
|
|
|
|
Pair<Long, Long> messageAndThreadId = database.insertSecureDecryptedMessageInbox(masterSecret, mediaMessage, -1);
|
|
List<DatabaseAttachment> attachments = DatabaseFactory.getAttachmentDatabase(context).getAttachmentsForMessage(messageAndThreadId.first);
|
|
|
|
for (DatabaseAttachment attachment : attachments) {
|
|
ApplicationContext.getInstance(context)
|
|
.getJobManager()
|
|
.add(new AttachmentDownloadJob(context, messageAndThreadId.first,
|
|
attachment.getAttachmentId()));
|
|
}
|
|
|
|
if (smsMessageId.isPresent()) {
|
|
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
|
|
}
|
|
|
|
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second);
|
|
}
|
|
|
|
private void handleSynchronizeSentMediaMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull SentTranscriptMessage message,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
throws MmsException
|
|
{
|
|
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
|
Recipients recipients = getSyncMessageDestination(message);
|
|
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(recipients, message.getMessage().getBody().orNull(),
|
|
PointerAttachment.forPointers(masterSecret, message.getMessage().getAttachments()),
|
|
message.getTimestamp(), ThreadDatabase.DistributionTypes.DEFAULT);
|
|
|
|
mediaMessage = new OutgoingSecureMediaMessage(mediaMessage);
|
|
|
|
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
|
long messageId = database.insertMessageOutbox(masterSecret, mediaMessage, threadId, false);
|
|
|
|
database.markAsSent(messageId);
|
|
database.markAsPush(messageId);
|
|
|
|
for (DatabaseAttachment attachment : DatabaseFactory.getAttachmentDatabase(context).getAttachmentsForMessage(messageId)) {
|
|
ApplicationContext.getInstance(context)
|
|
.getJobManager()
|
|
.add(new AttachmentDownloadJob(context, messageId, attachment.getAttachmentId()));
|
|
}
|
|
|
|
if (smsMessageId.isPresent()) {
|
|
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
|
|
}
|
|
}
|
|
|
|
private void handleTextMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull TextSecureEnvelope envelope,
|
|
@NonNull TextSecureDataMessage message,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
{
|
|
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
|
String body = message.getBody().isPresent() ? message.getBody().get() : "";
|
|
|
|
Pair<Long, Long> messageAndThreadId;
|
|
|
|
if (smsMessageId.isPresent()) {
|
|
messageAndThreadId = database.updateBundleMessageBody(masterSecret, smsMessageId.get(), body);
|
|
} else {
|
|
IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(),
|
|
envelope.getSourceDevice(),
|
|
message.getTimestamp(), body,
|
|
message.getGroupInfo());
|
|
|
|
textMessage = new IncomingEncryptedMessage(textMessage, body);
|
|
messageAndThreadId = database.insertMessageInbox(masterSecret, textMessage);
|
|
}
|
|
|
|
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second);
|
|
}
|
|
|
|
private void handleSynchronizeSentTextMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull SentTranscriptMessage message,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
{
|
|
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
|
Recipients recipients = getSyncMessageDestination(message);
|
|
String body = message.getMessage().getBody().or("");
|
|
OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipients, body);
|
|
|
|
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
|
long messageId = database.insertMessageOutbox(masterSecret, threadId, outgoingTextMessage, false, message.getTimestamp());
|
|
|
|
database.markAsSent(messageId);
|
|
database.markAsPush(messageId);
|
|
database.markAsSecure(messageId);
|
|
|
|
if (smsMessageId.isPresent()) {
|
|
database.deleteMessage(smsMessageId.get());
|
|
}
|
|
}
|
|
|
|
private void handleInvalidVersionMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull TextSecureEnvelope envelope,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
{
|
|
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
|
|
|
if (!smsMessageId.isPresent()) {
|
|
Pair<Long, Long> messageAndThreadId = insertPlaceholder(envelope);
|
|
smsDatabase.markAsInvalidVersionKeyExchange(messageAndThreadId.first);
|
|
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second);
|
|
} else {
|
|
smsDatabase.markAsInvalidVersionKeyExchange(smsMessageId.get());
|
|
}
|
|
}
|
|
|
|
private void handleCorruptMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull TextSecureEnvelope envelope,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
{
|
|
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
|
|
|
if (!smsMessageId.isPresent()) {
|
|
Pair<Long, Long> messageAndThreadId = insertPlaceholder(envelope);
|
|
smsDatabase.markAsDecryptFailed(messageAndThreadId.first);
|
|
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second);
|
|
} else {
|
|
smsDatabase.markAsDecryptFailed(smsMessageId.get());
|
|
}
|
|
}
|
|
|
|
private void handleNoSessionMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull TextSecureEnvelope envelope,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
{
|
|
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
|
|
|
if (!smsMessageId.isPresent()) {
|
|
Pair<Long, Long> messageAndThreadId = insertPlaceholder(envelope);
|
|
smsDatabase.markAsNoSession(messageAndThreadId.first);
|
|
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second);
|
|
} else {
|
|
smsDatabase.markAsNoSession(smsMessageId.get());
|
|
}
|
|
}
|
|
|
|
private void handleLegacyMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull TextSecureEnvelope envelope,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
{
|
|
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
|
|
|
if (!smsMessageId.isPresent()) {
|
|
Pair<Long, Long> messageAndThreadId = insertPlaceholder(envelope);
|
|
smsDatabase.markAsLegacyVersion(messageAndThreadId.first);
|
|
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second);
|
|
} else {
|
|
smsDatabase.markAsLegacyVersion(smsMessageId.get());
|
|
}
|
|
}
|
|
|
|
private void handleDuplicateMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull TextSecureEnvelope envelope,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
{
|
|
// Let's start ignoring these now
|
|
// SmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
|
//
|
|
// if (smsMessageId <= 0) {
|
|
// Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
|
// smsDatabase.markAsDecryptDuplicate(messageAndThreadId.first);
|
|
// MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
|
// } else {
|
|
// smsDatabase.markAsDecryptDuplicate(smsMessageId);
|
|
// }
|
|
}
|
|
|
|
private void handleUntrustedIdentityMessage(@NonNull MasterSecretUnion masterSecret,
|
|
@NonNull TextSecureEnvelope envelope,
|
|
@NonNull Optional<Long> smsMessageId)
|
|
{
|
|
try {
|
|
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
|
Recipients recipients = RecipientFactory.getRecipientsFromString(context, envelope.getSource(), false);
|
|
long recipientId = recipients.getPrimaryRecipient().getRecipientId();
|
|
PreKeyWhisperMessage whisperMessage = new PreKeyWhisperMessage(envelope.getLegacyMessage());
|
|
IdentityKey identityKey = whisperMessage.getIdentityKey();
|
|
String encoded = Base64.encodeBytes(envelope.getLegacyMessage());
|
|
IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(), envelope.getSourceDevice(),
|
|
envelope.getTimestamp(), encoded,
|
|
Optional.<TextSecureGroup>absent());
|
|
|
|
if (!smsMessageId.isPresent()) {
|
|
IncomingPreKeyBundleMessage bundleMessage = new IncomingPreKeyBundleMessage(textMessage, encoded);
|
|
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(masterSecret, bundleMessage);
|
|
|
|
database.setMismatchedIdentity(messageAndThreadId.first, recipientId, identityKey);
|
|
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), messageAndThreadId.second);
|
|
} else {
|
|
database.updateMessageBody(masterSecret, smsMessageId.get(), encoded);
|
|
database.markAsPreKeyBundle(smsMessageId.get());
|
|
database.setMismatchedIdentity(smsMessageId.get(), recipientId, identityKey);
|
|
}
|
|
} catch (InvalidMessageException | InvalidVersionException e) {
|
|
throw new AssertionError(e);
|
|
}
|
|
}
|
|
|
|
private Pair<Long, Long> insertPlaceholder(@NonNull TextSecureEnvelope envelope) {
|
|
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
|
IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(), envelope.getSourceDevice(),
|
|
envelope.getTimestamp(), "",
|
|
Optional.<TextSecureGroup>absent());
|
|
|
|
textMessage = new IncomingEncryptedMessage(textMessage, "");
|
|
return database.insertMessageInbox(textMessage);
|
|
}
|
|
|
|
private Recipients getSyncMessageDestination(SentTranscriptMessage message) {
|
|
if (message.getMessage().getGroupInfo().isPresent()) {
|
|
return RecipientFactory.getRecipientsFromString(context, GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get().getGroupId()), false);
|
|
} else {
|
|
return RecipientFactory.getRecipientsFromString(context, message.getDestination().get(), false);
|
|
}
|
|
}
|
|
}
|