mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-24 06:02:22 +00:00
Better UX handling on identity key mismatches.
1) Migrate from GSON to Jackson everywhere. 2) Add support for storing identity key conflicts on message rows. 3) Add limited support for surfacing identity key conflicts in UI.
This commit is contained in:
@@ -30,6 +30,7 @@ import org.thoughtcrime.securesms.util.Base64;
|
||||
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;
|
||||
@@ -37,13 +38,14 @@ 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.TextSecureEnvelope;
|
||||
import org.whispersystems.textsecure.api.messages.TextSecureGroup;
|
||||
import org.whispersystems.textsecure.api.messages.TextSecureMessage;
|
||||
import org.whispersystems.textsecure.api.crypto.TextSecureCipher;
|
||||
|
||||
import ws.com.google.android.mms.MmsException;
|
||||
|
||||
@@ -52,14 +54,20 @@ public class PushDecryptJob extends MasterSecretJob {
|
||||
public static final String TAG = PushDecryptJob.class.getSimpleName();
|
||||
|
||||
private final long messageId;
|
||||
private final long smsMessageId;
|
||||
|
||||
public PushDecryptJob(Context context, long messageId, String sender) {
|
||||
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()
|
||||
.withRequirement(new MasterSecretRequirement(context))
|
||||
.withGroupId(sender)
|
||||
.create());
|
||||
this.messageId = messageId;
|
||||
this.messageId = pushMessageId;
|
||||
this.smsMessageId = smsMessageId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,7 +82,7 @@ public class PushDecryptJob extends MasterSecretJob {
|
||||
PushDatabase database = DatabaseFactory.getPushDatabase(context);
|
||||
TextSecureEnvelope envelope = database.get(messageId);
|
||||
|
||||
handleMessage(masterSecret, envelope);
|
||||
handleMessage(masterSecret, envelope, smsMessageId);
|
||||
database.delete(messageId);
|
||||
}
|
||||
|
||||
@@ -88,7 +96,7 @@ public class PushDecryptJob extends MasterSecretJob {
|
||||
|
||||
}
|
||||
|
||||
private void handleMessage(MasterSecret masterSecret, TextSecureEnvelope envelope) {
|
||||
private void handleMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
|
||||
try {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, envelope.getSource(), false);
|
||||
long recipientId = recipients.getPrimaryRecipient().getRecipientId();
|
||||
@@ -98,59 +106,72 @@ public class PushDecryptJob extends MasterSecretJob {
|
||||
|
||||
TextSecureMessage message = cipher.decrypt(envelope);
|
||||
|
||||
if (message.isEndSession()) handleEndSessionMessage(masterSecret, recipientId, envelope, message);
|
||||
else if (message.isGroupUpdate()) handleGroupMessage(masterSecret, envelope, message);
|
||||
else if (message.getAttachments().isPresent()) handleMediaMessage(masterSecret, envelope, message);
|
||||
else handleTextMessage(masterSecret, envelope, message);
|
||||
if (message.isEndSession()) handleEndSessionMessage(masterSecret, recipientId, 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);
|
||||
|
||||
if (envelope.isPreKeyWhisperMessage()) {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new RefreshPreKeysJob(context));
|
||||
}
|
||||
} catch (InvalidVersionException e) {
|
||||
Log.w(TAG, e);
|
||||
handleInvalidVersionMessage(masterSecret, envelope);
|
||||
handleInvalidVersionMessage(masterSecret, envelope, smsMessageId);
|
||||
} catch (InvalidMessageException | InvalidKeyIdException | InvalidKeyException | MmsException | RecipientFormattingException e) {
|
||||
Log.w(TAG, e);
|
||||
handleCorruptMessage(masterSecret, envelope);
|
||||
handleCorruptMessage(masterSecret, envelope, smsMessageId);
|
||||
} catch (NoSessionException e) {
|
||||
Log.w(TAG, e);
|
||||
handleNoSessionMessage(masterSecret, envelope);
|
||||
handleNoSessionMessage(masterSecret, envelope, smsMessageId);
|
||||
} catch (LegacyMessageException e) {
|
||||
Log.w(TAG, e);
|
||||
handleLegacyMessage(masterSecret, envelope);
|
||||
handleLegacyMessage(masterSecret, envelope, smsMessageId);
|
||||
} catch (DuplicateMessageException e) {
|
||||
Log.w(TAG, e);
|
||||
handleDuplicateMessage(masterSecret, envelope);
|
||||
handleDuplicateMessage(masterSecret, envelope, smsMessageId);
|
||||
} catch (UntrustedIdentityException e) {
|
||||
Log.w(TAG, e);
|
||||
handleUntrustedIdentityMessage(masterSecret, envelope);
|
||||
handleUntrustedIdentityMessage(masterSecret, envelope, smsMessageId);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEndSessionMessage(MasterSecret masterSecret, long recipientId,
|
||||
TextSecureEnvelope envelope, TextSecureMessage message)
|
||||
TextSecureEnvelope envelope, TextSecureMessage message,
|
||||
long smsMessageId)
|
||||
{
|
||||
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(envelope.getSource(),
|
||||
envelope.getSourceDevice(),
|
||||
message.getTimestamp(),
|
||||
"", Optional.<TextSecureGroup>absent());
|
||||
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(envelope.getSource(),
|
||||
envelope.getSourceDevice(),
|
||||
message.getTimestamp(),
|
||||
"", Optional.<TextSecureGroup>absent());
|
||||
|
||||
IncomingEndSessionMessage incomingEndSessionMessage = new IncomingEndSessionMessage(incomingTextMessage);
|
||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(masterSecret, incomingEndSessionMessage);
|
||||
long threadId;
|
||||
|
||||
if (smsMessageId <= 0) {
|
||||
IncomingEndSessionMessage incomingEndSessionMessage = new IncomingEndSessionMessage(incomingTextMessage);
|
||||
Pair<Long, Long> messageAndThreadId = smsDatabase.insertMessageInbox(masterSecret, incomingEndSessionMessage);
|
||||
threadId = messageAndThreadId.second;
|
||||
} else {
|
||||
smsDatabase.markAsEndSession(smsMessageId);
|
||||
threadId = smsDatabase.getThreadIdForMessage(smsMessageId);
|
||||
}
|
||||
|
||||
SessionStore sessionStore = new TextSecureSessionStore(context, masterSecret);
|
||||
sessionStore.deleteAllSessions(recipientId);
|
||||
|
||||
SecurityEvent.broadcastSecurityUpdateEvent(context, messageAndThreadId.second);
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
SecurityEvent.broadcastSecurityUpdateEvent(context, threadId);
|
||||
MessageNotifier.updateNotification(context, masterSecret, threadId);
|
||||
}
|
||||
|
||||
private void handleGroupMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, TextSecureMessage message) {
|
||||
private void handleGroupMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, TextSecureMessage message, long smsMessageId) {
|
||||
GroupMessageProcessor.process(context, masterSecret, envelope, message);
|
||||
|
||||
if (smsMessageId > 0) {
|
||||
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMediaMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, TextSecureMessage message)
|
||||
private void handleMediaMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, TextSecureMessage message, long smsMessageId)
|
||||
throws MmsException
|
||||
{
|
||||
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
||||
@@ -174,73 +195,123 @@ public class PushDecryptJob extends MasterSecretJob {
|
||||
.getJobManager()
|
||||
.add(new AttachmentDownloadJob(context, messageAndThreadId.first));
|
||||
|
||||
if (smsMessageId >= 0) {
|
||||
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId);
|
||||
}
|
||||
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
}
|
||||
|
||||
private void handleTextMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, TextSecureMessage message) {
|
||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
String body = message.getBody().isPresent() ? message.getBody().get() : "";
|
||||
IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(),
|
||||
private void handleTextMessage(MasterSecret masterSecret, TextSecureEnvelope envelope,
|
||||
TextSecureMessage message, long smsMessageId)
|
||||
{
|
||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
String body = message.getBody().isPresent() ? message.getBody().get() : "";
|
||||
|
||||
if (smsMessageId > 0) {
|
||||
database.updateBundleMessageBody(masterSecret, smsMessageId, body);
|
||||
} else {
|
||||
IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(),
|
||||
envelope.getSourceDevice(),
|
||||
message.getTimestamp(), body,
|
||||
message.getGroupInfo());
|
||||
|
||||
if (message.isSecure()) {
|
||||
textMessage = new IncomingEncryptedMessage(textMessage, body);
|
||||
if (message.isSecure()) {
|
||||
textMessage = new IncomingEncryptedMessage(textMessage, body);
|
||||
}
|
||||
|
||||
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(masterSecret, textMessage);
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
}
|
||||
|
||||
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(masterSecret, textMessage);
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
}
|
||||
|
||||
private void handleInvalidVersionMessage(MasterSecret masterSecret, TextSecureEnvelope envelope) {
|
||||
Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
||||
DatabaseFactory.getEncryptingSmsDatabase(context).markAsInvalidVersionKeyExchange(messageAndThreadId.first);
|
||||
private void handleInvalidVersionMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
|
||||
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
if (smsMessageId <= 0) {
|
||||
Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
||||
smsDatabase.markAsInvalidVersionKeyExchange(messageAndThreadId.first);
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
} else {
|
||||
smsDatabase.markAsInvalidVersionKeyExchange(smsMessageId);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCorruptMessage(MasterSecret masterSecret, TextSecureEnvelope envelope) {
|
||||
Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
||||
DatabaseFactory.getEncryptingSmsDatabase(context).markAsDecryptFailed(messageAndThreadId.first);
|
||||
private void handleCorruptMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
|
||||
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
if (smsMessageId <= 0) {
|
||||
Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
||||
smsDatabase.markAsDecryptFailed(messageAndThreadId.first);
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
} else {
|
||||
smsDatabase.markAsDecryptFailed(smsMessageId);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleNoSessionMessage(MasterSecret masterSecret, TextSecureEnvelope envelope) {
|
||||
Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
||||
DatabaseFactory.getEncryptingSmsDatabase(context).markAsNoSession(messageAndThreadId.first);
|
||||
private void handleNoSessionMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
|
||||
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
if (smsMessageId <= 0) {
|
||||
Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
||||
smsDatabase.markAsNoSession(messageAndThreadId.first);
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
} else {
|
||||
smsDatabase.markAsNoSession(smsMessageId);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLegacyMessage(MasterSecret masterSecret, TextSecureEnvelope envelope) {
|
||||
Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
||||
DatabaseFactory.getEncryptingSmsDatabase(context).markAsLegacyVersion(messageAndThreadId.first);
|
||||
private void handleLegacyMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
|
||||
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
if (smsMessageId <= 0) {
|
||||
Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
||||
smsDatabase.markAsLegacyVersion(messageAndThreadId.first);
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
} else {
|
||||
smsDatabase.markAsLegacyVersion(smsMessageId);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDuplicateMessage(MasterSecret masterSecret, TextSecureEnvelope envelope) {
|
||||
// Let's start ignoring these now.
|
||||
|
||||
// Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
||||
// DatabaseFactory.getEncryptingSmsDatabase(context).markAsDecryptDuplicate(messageAndThreadId.first);
|
||||
private void handleDuplicateMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) {
|
||||
// Let's start ignoring these now
|
||||
// SmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
//
|
||||
// MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
// 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(MasterSecret masterSecret, TextSecureEnvelope envelope) {
|
||||
String encoded = Base64.encodeBytes(envelope.getMessage());
|
||||
IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(), envelope.getSourceDevice(),
|
||||
envelope.getTimestamp(), encoded,
|
||||
Optional.<TextSecureGroup>absent());
|
||||
private void handleUntrustedIdentityMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, 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.getMessage());
|
||||
IdentityKey identityKey = whisperMessage.getIdentityKey();
|
||||
String encoded = Base64.encodeBytes(envelope.getMessage());
|
||||
IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(), envelope.getSourceDevice(),
|
||||
envelope.getTimestamp(), encoded,
|
||||
Optional.<TextSecureGroup>absent());
|
||||
|
||||
IncomingPreKeyBundleMessage bundleMessage = new IncomingPreKeyBundleMessage(textMessage, encoded);
|
||||
Pair<Long, Long> messageAndThreadId = DatabaseFactory.getEncryptingSmsDatabase(context)
|
||||
.insertMessageInbox(masterSecret, bundleMessage);
|
||||
if (smsMessageId <= 0) {
|
||||
IncomingPreKeyBundleMessage bundleMessage = new IncomingPreKeyBundleMessage(textMessage, encoded);
|
||||
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(masterSecret, bundleMessage);
|
||||
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
database.addMismatchedIdentity(messageAndThreadId.first, recipientId, identityKey);
|
||||
MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
} else {
|
||||
database.updateMessageBody(masterSecret, smsMessageId, encoded);
|
||||
database.markAsPreKeyBundle(smsMessageId);
|
||||
database.addMismatchedIdentity(smsMessageId, recipientId, identityKey);
|
||||
}
|
||||
} catch (RecipientFormattingException | InvalidMessageException | InvalidVersionException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<Long, Long> insertPlaceholder(MasterSecret masterSecret, TextSecureEnvelope envelope) {
|
||||
|
||||
@@ -8,13 +8,14 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.mms.PartParser;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.IncomingIdentityUpdateMessage;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
@@ -25,9 +26,11 @@ import org.whispersystems.textsecure.api.messages.TextSecureAttachment;
|
||||
import org.whispersystems.textsecure.api.messages.TextSecureGroup;
|
||||
import org.whispersystems.textsecure.api.messages.TextSecureMessage;
|
||||
import org.whispersystems.textsecure.api.push.PushAddress;
|
||||
import org.whispersystems.textsecure.internal.push.PushMessageProtos;
|
||||
import org.whispersystems.textsecure.api.push.exceptions.EncapsulatedExceptions;
|
||||
import org.whispersystems.textsecure.api.push.exceptions.NetworkFailureException;
|
||||
import org.whispersystems.textsecure.api.push.exceptions.UnregisteredUserException;
|
||||
import org.whispersystems.textsecure.api.util.InvalidNumberException;
|
||||
import org.whispersystems.textsecure.internal.push.PushMessageProtos;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
@@ -47,8 +50,9 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
@Inject transient TextSecureMessageSenderFactory messageSenderFactory;
|
||||
|
||||
private final long messageId;
|
||||
private final long filterRecipientId;
|
||||
|
||||
public PushGroupSendJob(Context context, long messageId, String destination) {
|
||||
public PushGroupSendJob(Context context, long messageId, String destination, long filterRecipientId) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withPersistence()
|
||||
.withGroupId(destination)
|
||||
@@ -57,21 +61,25 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
.withRetryCount(5)
|
||||
.create());
|
||||
|
||||
this.messageId = messageId;
|
||||
this.messageId = messageId;
|
||||
this.filterRecipientId = filterRecipientId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
|
||||
DatabaseFactory.getMmsDatabase(context)
|
||||
.markAsSending(messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSend(MasterSecret masterSecret) throws MmsException, IOException, NoSuchMessageException {
|
||||
public void onSend(MasterSecret masterSecret)
|
||||
throws MmsException, IOException, NoSuchMessageException, RecipientFormattingException
|
||||
{
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
SendReq message = database.getOutgoingMessage(masterSecret, messageId);
|
||||
|
||||
try {
|
||||
deliver(masterSecret, message);
|
||||
deliver(masterSecret, message, filterRecipientId);
|
||||
|
||||
database.markAsPush(messageId);
|
||||
database.markAsSecure(messageId);
|
||||
@@ -82,16 +90,27 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
notifyMediaMessageDeliveryFailed(context, messageId);
|
||||
} catch (EncapsulatedExceptions e) {
|
||||
Log.w(TAG, e);
|
||||
if (!e.getUnregisteredUserExceptions().isEmpty()) {
|
||||
database.markAsSentFailed(messageId);
|
||||
List<NetworkFailure> failures = new LinkedList<>();
|
||||
|
||||
for (NetworkFailureException nfe : e.getNetworkExceptions()) {
|
||||
Recipient recipient = RecipientFactory.getRecipientsFromString(context, nfe.getE164number(), false).getPrimaryRecipient();
|
||||
failures.add(new NetworkFailure(recipient.getRecipientId()));
|
||||
}
|
||||
|
||||
// for (UnregisteredUserException uue : e.getUnregisteredUserExceptions()) {
|
||||
// Recipient recipient = RecipientFactory.getRecipientsFromString(context, uue.getE164Number(), false).getPrimaryRecipient();
|
||||
// failures.add(new NetworkFailure(recipient.getRecipientId(), NetworkFailure.UNREGISTERED_FAILURE));
|
||||
// }
|
||||
|
||||
for (UntrustedIdentityException uie : e.getUntrustedIdentityExceptions()) {
|
||||
IncomingIdentityUpdateMessage identityUpdateMessage = IncomingIdentityUpdateMessage.createFor(message.getTo()[0].getString(), uie.getIdentityKey());
|
||||
DatabaseFactory.getEncryptingSmsDatabase(context).insertMessageInbox(masterSecret, identityUpdateMessage);
|
||||
database.markAsSentFailed(messageId);
|
||||
Recipient recipient = RecipientFactory.getRecipientsFromString(context, uie.getE164Number(), false).getPrimaryRecipient();
|
||||
database.addMismatchedIdentity(messageId, recipient.getRecipientId(), uie.getIdentityKey());
|
||||
}
|
||||
|
||||
database.addFailures(messageId, failures);
|
||||
database.markAsSentFailed(messageId);
|
||||
database.markAsPush(messageId);
|
||||
|
||||
notifyMediaMessageDeliveryFailed(context, messageId);
|
||||
}
|
||||
}
|
||||
@@ -107,14 +126,17 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
DatabaseFactory.getMmsDatabase(context).markAsSentFailed(messageId);
|
||||
}
|
||||
|
||||
private void deliver(MasterSecret masterSecret, SendReq message)
|
||||
private void deliver(MasterSecret masterSecret, SendReq message, long filterRecipientId)
|
||||
throws IOException, RecipientFormattingException, InvalidNumberException, EncapsulatedExceptions
|
||||
{
|
||||
TextSecureMessageSender messageSender = messageSenderFactory.create(masterSecret);
|
||||
byte[] groupId = GroupUtil.getDecodedId(message.getTo()[0].getString());
|
||||
Recipients recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
|
||||
List<PushAddress> addresses = getPushAddresses(recipients);
|
||||
List<TextSecureAttachment> attachments = getAttachments(masterSecret, message);
|
||||
List<PushAddress> addresses;
|
||||
|
||||
if (filterRecipientId >= 0) addresses = getPushAddresses(filterRecipientId);
|
||||
else addresses = getPushAddresses(recipients);
|
||||
|
||||
if (MmsSmsColumns.Types.isGroupUpdate(message.getDatabaseMessageBox()) ||
|
||||
MmsSmsColumns.Types.isGroupQuit(message.getDatabaseMessageBox()))
|
||||
@@ -149,4 +171,10 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
private List<PushAddress> getPushAddresses(long filterRecipientId) throws InvalidNumberException {
|
||||
List<PushAddress> addresses = new LinkedList<>();
|
||||
addresses.add(getPushAddress(RecipientFactory.getRecipientForId(context, filterRecipientId, false)));
|
||||
return addresses;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.thoughtcrime.securesms.crypto.storage.TextSecureAxolotlStore;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||
import org.thoughtcrime.securesms.mms.PartParser;
|
||||
@@ -16,7 +17,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.IncomingIdentityUpdateMessage;
|
||||
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.transport.SecureFallbackApprovalException;
|
||||
@@ -55,12 +55,15 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
|
||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||
mmsDatabase.markAsSending(messageId);
|
||||
mmsDatabase.markAsPush(messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSend(MasterSecret masterSecret)
|
||||
throws RetryLaterException, MmsException, NoSuchMessageException, UndeliverableMessageException
|
||||
throws RetryLaterException, MmsException, NoSuchMessageException,
|
||||
UndeliverableMessageException, RecipientFormattingException
|
||||
{
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
SendReq message = database.getOutgoingMessage(masterSecret, messageId);
|
||||
@@ -80,9 +83,13 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
database.markAsPendingSecureSmsFallback(messageId);
|
||||
notifyMediaMessageDeliveryFailed(context, messageId);
|
||||
} catch (UntrustedIdentityException uie) {
|
||||
IncomingIdentityUpdateMessage identityUpdateMessage = IncomingIdentityUpdateMessage.createFor(message.getTo()[0].getString(), uie.getIdentityKey());
|
||||
DatabaseFactory.getEncryptingSmsDatabase(context).insertMessageInbox(masterSecret, identityUpdateMessage);
|
||||
Log.w(TAG, uie);
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, uie.getE164Number(), false);
|
||||
long recipientId = recipients.getPrimaryRecipient().getRecipientId();
|
||||
|
||||
database.addMismatchedIdentity(messageId, recipientId, uie.getIdentityKey());
|
||||
database.markAsSentFailed(messageId);
|
||||
database.markAsPush(messageId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,14 @@ import org.thoughtcrime.securesms.crypto.storage.TextSecureAxolotlStore;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.IncomingIdentityUpdateMessage;
|
||||
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.transport.SecureFallbackApprovalException;
|
||||
@@ -47,14 +49,16 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
|
||||
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||
smsDatabase.markAsSending(messageId);
|
||||
smsDatabase.markAsPush(messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSend(MasterSecret masterSecret) throws NoSuchMessageException, RetryLaterException {
|
||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
SmsMessageRecord record = database.getMessage(masterSecret, messageId);
|
||||
String destination = record.getIndividualRecipient().getNumber();
|
||||
public void onSend(MasterSecret masterSecret) throws NoSuchMessageException, RetryLaterException, RecipientFormattingException {
|
||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
SmsMessageRecord record = database.getMessage(masterSecret, messageId);
|
||||
String destination = record.getIndividualRecipient().getNumber();
|
||||
|
||||
try {
|
||||
Log.w(TAG, "Sending message: " + messageId);
|
||||
@@ -74,9 +78,12 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipients(), record.getThreadId());
|
||||
} catch (UntrustedIdentityException e) {
|
||||
Log.w(TAG, e);
|
||||
IncomingIdentityUpdateMessage identityUpdateMessage = IncomingIdentityUpdateMessage.createFor(e.getE164Number(), e.getIdentityKey());
|
||||
database.insertMessageInbox(masterSecret, identityUpdateMessage);
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, e.getE164Number(), false);
|
||||
long recipientId = recipients.getPrimaryRecipient().getRecipientId();
|
||||
|
||||
database.addMismatchedIdentity(record.getId(), recipientId, e.getIdentityKey());
|
||||
database.markAsSentFailed(record.getId());
|
||||
database.markAsPush(record.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user