Add delivery receipts to the MSL.

fork-5.53.8
Greyson Parrelli 2021-06-30 14:36:00 -04:00 zatwierdzone przez Alex Hart
rodzic 5372f79c40
commit 3d0e15e2b8
15 zmienionych plików z 182 dodań i 88 usunięć

Wyświetl plik

@ -300,6 +300,9 @@ class ConversationSettingsFragment : DSLSettingsFragment(
recipient = state.recipient,
onDisableProfileSharingClick = {
viewModel.disableProfileSharing()
},
onDeleteSessionClick = {
viewModel.deleteSession()
}
)
)

Wyświetl plik

@ -24,6 +24,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.recipients.RecipientUtil
import org.thoughtcrime.securesms.util.FeatureFlags
import org.whispersystems.libsignal.util.guava.Optional
import org.whispersystems.libsignal.util.guava.Preconditions
import java.io.IOException
private val TAG = Log.tag(ConversationSettingsRepository::class.java)
@ -185,12 +186,22 @@ class ConversationSettingsRepository(
}
}
fun disableProfileSharing(recipientId: RecipientId) {
fun disableProfileSharingForInternalUser(recipientId: RecipientId) {
Preconditions.checkArgument(FeatureFlags.internalUser(), "Internal users only!");
SignalExecutors.BOUNDED.execute {
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipientId, false)
}
}
fun deleteSessionForInternalUser(recipientId: RecipientId) {
Preconditions.checkArgument(FeatureFlags.internalUser(), "Internal users only!");
SignalExecutors.BOUNDED.execute {
DatabaseFactory.getSessionDatabase(context).deleteAllFor(recipientId)
}
}
@WorkerThread
fun isMessageRequestAccepted(recipient: Recipient): Boolean {
return RecipientUtil.isMessageRequestAccepted(context, recipient)

Wyświetl plik

@ -116,6 +116,8 @@ sealed class ConversationSettingsViewModel(
open fun disableProfileSharing(): Unit = error("This ViewModel does not support this interaction")
open fun deleteSession(): Unit = error("This ViewModel does not support this interaction")
open fun initiateGroupUpgrade(): Unit = error("This ViewModel does not support this interaction")
private class RecipientSettingsViewModel(
@ -237,7 +239,11 @@ sealed class ConversationSettingsViewModel(
}
override fun disableProfileSharing() {
repository.disableProfileSharing(recipientId)
repository.disableProfileSharingForInternalUser(recipientId)
}
override fun deleteSession() {
repository.deleteSessionForInternalUser(recipientId)
}
}

Wyświetl plik

@ -19,7 +19,8 @@ object InternalPreference {
class Model(
private val recipient: Recipient,
val onDisableProfileSharingClick: () -> Unit
val onDisableProfileSharingClick: () -> Unit,
val onDeleteSessionClick: () -> Unit
) : PreferenceModel<Model>() {
val body: String get() {
@ -58,10 +59,12 @@ object InternalPreference {
private val body: TextView = itemView.findViewById(R.id.internal_preference_body)
private val disableProfileSharing: View = itemView.findViewById(R.id.internal_disable_profile_sharing)
private val deleteSession: View = itemView.findViewById(R.id.internal_delete_session)
override fun bind(model: Model) {
body.text = model.body
disableProfileSharing.setOnClickListener { model.onDisableProfileSharingClick() }
deleteSession.setOnClickListener { model.onDeleteSessionClick() }
}
}
}

Wyświetl plik

@ -131,7 +131,7 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
public abstract List<MarkedMessageInfo> setEntireThreadRead(long threadId);
public abstract List<MarkedMessageInfo> setMessagesReadSince(long threadId, long timestamp);
public abstract List<MarkedMessageInfo> setAllMessagesRead();
public abstract Pair<Long, Long> updateBundleMessageBody(long messageId, String body);
public abstract InsertResult updateBundleMessageBody(long messageId, String body);
public abstract @NonNull List<MarkedMessageInfo> getViewedIncomingMessages(long threadId);
public abstract @Nullable MarkedMessageInfo setIncomingMessageViewed(long messageId);
public abstract @NonNull List<MarkedMessageInfo> setIncomingMessagesViewed(@NonNull List<Long> messageIds);

Wyświetl plik

@ -142,12 +142,12 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: SQLC
)
}
fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, relatedMessageId: Long, isRelatedMessageMms: Boolean) {
fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId) {
if (!FeatureFlags.senderKey()) return
if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) {
val recipientDevice = listOf(RecipientDevice(recipientId, sendMessageResult.success.devices))
insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, listOf(MessageId(relatedMessageId, isRelatedMessageMms)))
insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, listOf(messageId))
}
}

Wyświetl plik

@ -380,7 +380,7 @@ public class MmsDatabase extends MessageDatabase {
}
@Override
public Pair<Long, Long> updateBundleMessageBody(long messageId, String body) {
public InsertResult updateBundleMessageBody(long messageId, String body) {
throw new UnsupportedOperationException();
}

Wyświetl plik

@ -664,7 +664,7 @@ public class SmsDatabase extends MessageDatabase {
}
@Override
public Pair<Long, Long> updateBundleMessageBody(long messageId, String body) {
public InsertResult updateBundleMessageBody(long messageId, String body) {
long type = Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT | Types.PUSH_MESSAGE_BIT;
return updateMessageBodyAndType(messageId, body, Types.TOTAL_MASK, type);
}
@ -684,7 +684,7 @@ public class SmsDatabase extends MessageDatabase {
return Collections.emptyList();
}
private Pair<Long, Long> updateMessageBodyAndType(long messageId, String body, long maskOff, long maskOn) {
private InsertResult updateMessageBodyAndType(long messageId, String body, long maskOff, long maskOn) {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.execSQL("UPDATE " + TABLE_NAME + " SET " + BODY + " = ?, " +
TYPE + " = (" + TYPE + " & " + (Types.TOTAL_MASK - maskOff) + " | " + maskOn + ") " +
@ -697,7 +697,7 @@ public class SmsDatabase extends MessageDatabase {
notifyConversationListeners(threadId);
notifyConversationListListeners();
return new Pair<>(messageId, threadId);
return new InsertResult(messageId, threadId);
}
@Override

Wyświetl plik

@ -7,4 +7,16 @@ package org.thoughtcrime.securesms.database.model
data class MessageId(
val id: Long,
@get:JvmName("isMms") val mms: Boolean
)
) {
fun serialize(): String {
return "$id|$mms"
}
companion object {
@JvmStatic
fun deserialize(serialized: String): MessageId {
val parts: List<String> = serialized.split("|")
return MessageId(parts[0].toLong(), parts[1].toBoolean())
}
}
}

Wyświetl plik

@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.database.MessageDatabase;
import org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
import org.thoughtcrime.securesms.database.model.MessageId;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
@ -224,11 +225,11 @@ public class PushMediaSendJob extends PushSendJob {
SignalServiceSyncMessage syncMessage = buildSelfSendSyncMessage(context, mediaMessage, syncAccess);
SendMessageResult result = messageSender.sendSyncMessage(syncMessage, syncAccess);
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, messageId, true);
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true));
return syncAccess.isPresent();
} else {
SendMessageResult result = messageSender.sendDataMessage(address, UnidentifiedAccessUtil.getAccessFor(context, messageRecipient), ContentHint.RESENDABLE, mediaMessage);
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, messageId, true);
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true));
return result.getSuccess().isUnidentified();
}
} catch (UnregisteredUserException e) {

Wyświetl plik

@ -9,6 +9,7 @@ import org.thoughtcrime.securesms.database.MessageDatabase;
import org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
import org.thoughtcrime.securesms.database.model.MessageId;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobmanager.Data;
@ -176,11 +177,11 @@ public class PushTextSendJob extends PushSendJob {
SignalServiceSyncMessage syncMessage = buildSelfSendSyncMessage(context, textSecureMessage, syncAccess);
SendMessageResult result = messageSender.sendSyncMessage(syncMessage, syncAccess);
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, messageId, false);
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false));
return syncAccess.isPresent();
} else {
SendMessageResult result = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.RESENDABLE, textSecureMessage);
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, messageId, false);
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false));
return result.getSuccess().isUnidentified();
}
} catch (UnregisteredUserException e) {

Wyświetl plik

@ -2,9 +2,12 @@ package org.thoughtcrime.securesms.jobs;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.model.MessageId;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
@ -15,7 +18,9 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.crypto.ContentHint;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.SendMessageResult;
import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
@ -29,17 +34,21 @@ public class SendDeliveryReceiptJob extends BaseJob {
public static final String KEY = "SendDeliveryReceiptJob";
private static final String KEY_RECIPIENT = "recipient";
private static final String KEY_MESSAGE_ID = "message_id";
private static final String KEY_TIMESTAMP = "timestamp";
private static final String KEY_RECIPIENT = "recipient";
private static final String KEY_MESSAGE_SENT_TIMESTAMP = "message_id";
private static final String KEY_TIMESTAMP = "timestamp";
private static final String KEY_MESSAGE_ID = "message_db_id";
private static final String TAG = Log.tag(SendReadReceiptJob.class);
private RecipientId recipientId;
private long messageId;
private long timestamp;
private final RecipientId recipientId;
private final long messageSentTimestamp;
private final long timestamp;
public SendDeliveryReceiptJob(@NonNull RecipientId recipientId, long messageId) {
@Nullable
private final MessageId messageId;
public SendDeliveryReceiptJob(@NonNull RecipientId recipientId, long messageSentTimestamp, @NonNull MessageId messageId) {
this(new Job.Parameters.Builder()
.addConstraint(NetworkConstraint.KEY)
.setLifespan(TimeUnit.DAYS.toMillis(1))
@ -47,28 +56,36 @@ public class SendDeliveryReceiptJob extends BaseJob {
.setQueue(recipientId.toQueueKey())
.build(),
recipientId,
messageSentTimestamp,
messageId,
System.currentTimeMillis());
}
private SendDeliveryReceiptJob(@NonNull Job.Parameters parameters,
@NonNull RecipientId recipientId,
long messageId,
long messageSentTimestamp,
@Nullable MessageId messageId,
long timestamp)
{
super(parameters);
this.recipientId = recipientId;
this.messageId = messageId;
this.timestamp = timestamp;
this.recipientId = recipientId;
this.messageSentTimestamp = messageSentTimestamp;
this.messageId = messageId;
this.timestamp = timestamp;
}
@Override
public @NonNull Data serialize() {
return new Data.Builder().putString(KEY_RECIPIENT, recipientId.serialize())
.putLong(KEY_MESSAGE_ID, messageId)
.putLong(KEY_TIMESTAMP, timestamp)
.build();
Data.Builder builder = new Data.Builder().putString(KEY_RECIPIENT, recipientId.serialize())
.putLong(KEY_MESSAGE_SENT_TIMESTAMP, messageSentTimestamp)
.putLong(KEY_TIMESTAMP, timestamp);
if (messageId != null) {
builder.putString(KEY_MESSAGE_ID, messageId.serialize());
}
return builder.build();
}
@Override
@ -86,12 +103,16 @@ public class SendDeliveryReceiptJob extends BaseJob {
Recipient recipient = Recipient.resolved(recipientId);
SignalServiceAddress remoteAddress = RecipientUtil.toSignalServiceAddress(context, recipient);
SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.DELIVERY,
Collections.singletonList(messageId),
Collections.singletonList(messageSentTimestamp),
timestamp);
messageSender.sendReceipt(remoteAddress,
UnidentifiedAccessUtil.getAccessFor(context, recipient),
receiptMessage);
SendMessageResult result = messageSender.sendReceipt(remoteAddress,
UnidentifiedAccessUtil.getAccessFor(context, recipient),
receiptMessage);
if (messageId != null) {
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageId);
}
}
@Override
@ -109,9 +130,16 @@ public class SendDeliveryReceiptJob extends BaseJob {
public static final class Factory implements Job.Factory<SendDeliveryReceiptJob> {
@Override
public @NonNull SendDeliveryReceiptJob create(@NonNull Parameters parameters, @NonNull Data data) {
MessageId messageId = null;
if (data.hasString(KEY_MESSAGE_ID)) {
messageId = MessageId.deserialize(data.getString(KEY_MESSAGE_ID));
}
return new SendDeliveryReceiptJob(parameters,
RecipientId.from(data.getString(KEY_RECIPIENT)),
data.getLong(KEY_MESSAGE_ID),
data.getLong(KEY_MESSAGE_SENT_TIMESTAMP),
messageId,
data.getLong(KEY_TIMESTAMP));
}
}

Wyświetl plik

@ -253,15 +253,17 @@ public final class MessageContentProcessor {
}
}
MessageId messageId = null;
if (isInvalidMessage(message)) handleInvalidMessage(content.getSender(), content.getSenderDevice(), groupId, content.getTimestamp(), smsMessageId);
else if (message.isEndSession()) handleEndSessionMessage(content, smsMessageId);
else if (message.isEndSession()) messageId = handleEndSessionMessage(content, smsMessageId);
else if (message.isGroupV1Update()) handleGroupV1Message(content, message, smsMessageId, groupId.get().requireV1(), receivedTime);
else if (message.isExpirationUpdate()) handleExpirationUpdate(content, message, smsMessageId, groupId, receivedTime);
else if (message.getReaction().isPresent()) handleReaction(content, message);
else if (message.getRemoteDelete().isPresent()) handleRemoteDelete(content, message);
else if (message.isExpirationUpdate()) messageId = handleExpirationUpdate(content, message, smsMessageId, groupId, receivedTime);
else if (message.getReaction().isPresent()) messageId = handleReaction(content, message);
else if (message.getRemoteDelete().isPresent()) messageId = handleRemoteDelete(content, message);
else if (message.getPayment().isPresent()) handlePayment(content, message);
else if (isMediaMessage) handleMediaMessage(content, message, smsMessageId, receivedTime);
else if (message.getBody().isPresent()) handleTextMessage(content, message, smsMessageId, groupId, receivedTime);
else if (isMediaMessage) messageId = handleMediaMessage(content, message, smsMessageId, receivedTime);
else if (message.getBody().isPresent()) messageId = handleTextMessage(content, message, smsMessageId, groupId, receivedTime);
else if (Build.VERSION.SDK_INT > 19 && message.getGroupCallUpdate().isPresent()) handleGroupCallUpdateMessage(content, message, groupId);
if (groupId.isPresent() && groupDatabase.isUnknownGroup(groupId.get())) {
@ -272,9 +274,9 @@ public final class MessageContentProcessor {
handleProfileKey(content, message.getProfileKey().get());
}
if (content.isNeedsReceipt()) {
handleNeedsDeliveryReceipt(content, message);
} else {
if (content.isNeedsReceipt() && messageId != null) {
handleNeedsDeliveryReceipt(content, message, messageId);
} else if (!content.isNeedsReceipt()) {
Recipient sender = getMessageDestination(content, message);
if (RecipientUtil.shouldHaveProfileKey(context, sender)) {
@ -643,8 +645,8 @@ public final class MessageContentProcessor {
GroupCallPeekJob.enqueue(groupRecipientId);
}
private void handleEndSessionMessage(@NonNull SignalServiceContent content,
@NonNull Optional<Long> smsMessageId)
private @Nullable MessageId handleEndSessionMessage(@NonNull SignalServiceContent content,
@NonNull Optional<Long> smsMessageId)
{
MessageDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(Recipient.externalHighTrustPush(context, content.getSender()).getId(),
@ -658,25 +660,27 @@ public final class MessageContentProcessor {
content.isNeedsReceipt(),
content.getServerUuid());
Long threadId;
Optional<InsertResult> insertResult;
if (!smsMessageId.isPresent()) {
IncomingEndSessionMessage incomingEndSessionMessage = new IncomingEndSessionMessage(incomingTextMessage);
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(incomingEndSessionMessage);
if (insertResult.isPresent()) threadId = insertResult.get().getThreadId();
else threadId = null;
insertResult = smsDatabase.insertMessageInbox(incomingEndSessionMessage);
} else {
smsDatabase.markAsEndSession(smsMessageId.get());
threadId = smsDatabase.getThreadIdForMessage(smsMessageId.get());
insertResult = Optional.of(new InsertResult(smsMessageId.get(), smsDatabase.getThreadIdForMessage(smsMessageId.get())));
}
if (threadId != null) {
if (insertResult.isPresent()) {
SessionStore sessionStore = new TextSecureSessionStore(context);
sessionStore.deleteAllSessions(content.getSender().getIdentifier());
SecurityEvent.broadcastSecurityUpdateEvent(context);
ApplicationDependencies.getMessageNotifier().updateNotification(context, threadId);
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
return new MessageId(insertResult.get().getMessageId(), true);
} else {
return null;
}
}
@ -742,16 +746,16 @@ public final class MessageContentProcessor {
}
}
private void handleExpirationUpdate(@NonNull SignalServiceContent content,
@NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId,
@NonNull Optional<GroupId> groupId,
long receivedTime)
private @Nullable MessageId handleExpirationUpdate(@NonNull SignalServiceContent content,
@NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId,
@NonNull Optional<GroupId> groupId,
long receivedTime)
throws StorageFailedException, BadGroupIdException
{
if (groupId.isPresent() && groupId.get().isV2()) {
warn(String.valueOf(content.getTimestamp()), "Expiration update received for GV2. Ignoring.");
return;
return null;
}
int expiresInSeconds = message.getExpiresInSeconds();
@ -760,7 +764,7 @@ public final class MessageContentProcessor {
if (recipient.getExpireMessages() == expiresInSeconds) {
log(String.valueOf(content.getTimestamp()), "No change in message expiry for group. Ignoring.");
return;
return null;
}
try {
@ -785,24 +789,30 @@ public final class MessageContentProcessor {
Optional.absent(),
content.getServerUuid());
database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
Optional<InsertResult> insertResult = database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(recipient.getId(), expiresInSeconds);
if (smsMessageId.isPresent()) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
}
if (insertResult.isPresent()) {
return new MessageId(insertResult.get().getMessageId(), true);
}
} catch (MmsException e) {
throw new StorageFailedException(e, content.getSender().getIdentifier(), content.getSenderDevice());
}
return null;
}
private void handleReaction(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
private @Nullable MessageId handleReaction(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
SignalServiceDataMessage.Reaction reaction = message.getReaction().get();
if (!EmojiUtil.isEmoji(reaction.getEmoji())) {
Log.w(TAG, "Reaction text is not a valid emoji! Ignoring the message.");
return;
return null;
}
Recipient reactionAuthor = Recipient.externalHighTrustPush(context, content.getSender());
@ -812,31 +822,31 @@ public final class MessageContentProcessor {
if (targetMessage == null) {
warn(String.valueOf(content.getTimestamp()), "[handleReaction] Could not find matching message! Putting it in the early message cache. timestamp: " + reaction.getTargetSentTimestamp() + " author: " + targetAuthor.getId());
ApplicationDependencies.getEarlyMessageCache().store(targetAuthor.getId(), reaction.getTargetSentTimestamp(), content);
return;
return null;
}
if (targetMessage.isRemoteDelete()) {
warn(String.valueOf(content.getTimestamp()), "[handleReaction] Found a matching message, but it's flagged as remotely deleted. timestamp: " + reaction.getTargetSentTimestamp() + " author: " + targetAuthor.getId());
return;
return null;
}
ThreadRecord targetThread = DatabaseFactory.getThreadDatabase(context).getThreadRecord(targetMessage.getThreadId());
if (targetThread == null) {
warn(String.valueOf(content.getTimestamp()), "[handleReaction] Could not find a thread for the message! timestamp: " + reaction.getTargetSentTimestamp() + " author: " + targetAuthor.getId());
return;
return null;
}
Recipient threadRecipient = targetThread.getRecipient().resolve();
if (threadRecipient.isGroup() && !threadRecipient.getParticipants().contains(reactionAuthor)) {
warn(String.valueOf(content.getTimestamp()), "[handleReaction] Reaction author is not in the group! timestamp: " + reaction.getTargetSentTimestamp() + " author: " + targetAuthor.getId());
return;
return null;
}
if (!threadRecipient.isGroup() && !reactionAuthor.equals(threadRecipient) && !reactionAuthor.isSelf()) {
warn(String.valueOf(content.getTimestamp()), "[handleReaction] Reaction author is not a part of the 1:1 thread! timestamp: " + reaction.getTargetSentTimestamp() + " author: " + targetAuthor.getId());
return;
return null;
}
MessageDatabase db = targetMessage.isMms() ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context);
@ -849,9 +859,11 @@ public final class MessageContentProcessor {
db.addReaction(targetMessage.getId(), reactionRecord);
ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false);
}
return new MessageId(targetMessage.getId(), targetMessage.isMms());
}
private void handleRemoteDelete(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
private @Nullable MessageId handleRemoteDelete(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
SignalServiceDataMessage.RemoteDelete delete = message.getRemoteDelete().get();
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
@ -861,12 +873,15 @@ public final class MessageContentProcessor {
MessageDatabase db = targetMessage.isMms() ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context);
db.markAsRemoteDelete(targetMessage.getId());
ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false);
return new MessageId(targetMessage.getId(), targetMessage.isMms());
} else if (targetMessage == null) {
warn(String.valueOf(content.getTimestamp()), "[handleRemoteDelete] Could not find matching message! timestamp: " + delete.getTargetSentTimestamp() + " author: " + sender.getId());
ApplicationDependencies.getEarlyMessageCache().store(sender.getId(), delete.getTargetSentTimestamp(), content);
return null;
} else {
warn(String.valueOf(content.getTimestamp()), String.format(Locale.ENGLISH, "[handleRemoteDelete] Invalid remote delete! deleteTime: %d, targetTime: %d, deleteAuthor: %s, targetAuthor: %s",
content.getServerReceivedTimestamp(), targetMessage.getServerTimestamp(), sender.getId(), targetMessage.getRecipient().getId()));
return null;
}
}
@ -1192,10 +1207,10 @@ public final class MessageContentProcessor {
messageNotifier.updateNotification(context);
}
private void handleMediaMessage(@NonNull SignalServiceContent content,
@NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId,
long receivedTime)
private @Nullable MessageId handleMediaMessage(@NonNull SignalServiceContent content,
@NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId,
long receivedTime)
throws StorageFailedException, BadGroupIdException
{
notifyTypingStoppedFromIncomingMessage(getMessageDestination(content, message), content.getSender(), content.getSenderDevice());
@ -1263,6 +1278,10 @@ public final class MessageContentProcessor {
if (message.isViewOnce()) {
ApplicationDependencies.getViewOnceMessageManager().scheduleIfNecessary();
}
return new MessageId(insertResult.get().getMessageId(), true);
} else {
return null;
}
}
@ -1416,11 +1435,11 @@ public final class MessageContentProcessor {
receiptDatabase.setUnidentified(unidentifiedStatus, messageId);
}
private void handleTextMessage(@NonNull SignalServiceContent content,
@NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId,
@NonNull Optional<GroupId> groupId,
long receivedTime)
private @Nullable MessageId handleTextMessage(@NonNull SignalServiceContent content,
@NonNull SignalServiceDataMessage message,
@NonNull Optional<Long> smsMessageId,
@NonNull Optional<GroupId> groupId,
long receivedTime)
throws StorageFailedException, BadGroupIdException
{
MessageDatabase database = DatabaseFactory.getSmsDatabase(context);
@ -1431,10 +1450,10 @@ public final class MessageContentProcessor {
handleExpirationUpdate(content, message, Optional.absent(), groupId, receivedTime);
}
Long threadId;
Optional<InsertResult> insertResult;
if (smsMessageId.isPresent() && !message.getGroupContext().isPresent()) {
threadId = database.updateBundleMessageBody(smsMessageId.get(), body).second();
insertResult = Optional.of(database.updateBundleMessageBody(smsMessageId.get(), body));
} else {
notifyTypingStoppedFromIncomingMessage(recipient, content.getSender(), content.getSenderDevice());
@ -1450,16 +1469,16 @@ public final class MessageContentProcessor {
content.getServerUuid());
textMessage = new IncomingEncryptedMessage(textMessage, body);
Optional<InsertResult> insertResult = database.insertMessageInbox(textMessage);
if (insertResult.isPresent()) threadId = insertResult.get().getThreadId();
else threadId = null;
insertResult = database.insertMessageInbox(textMessage);
if (smsMessageId.isPresent()) database.deleteMessage(smsMessageId.get());
}
if (threadId != null) {
ApplicationDependencies.getMessageNotifier().updateNotification(context, threadId);
if (insertResult.isPresent()) {
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
return new MessageId(insertResult.get().getMessageId(), false);
} else {
return null;
}
}
@ -1638,9 +1657,10 @@ public final class MessageContentProcessor {
}
private void handleNeedsDeliveryReceipt(@NonNull SignalServiceContent content,
@NonNull SignalServiceDataMessage message)
@NonNull SignalServiceDataMessage message,
@NonNull MessageId messageId)
{
ApplicationDependencies.getJobManager().add(new SendDeliveryReceiptJob(RecipientId.fromHighTrust(content.getSender()), message.getTimestamp()));
ApplicationDependencies.getJobManager().add(new SendDeliveryReceiptJob(RecipientId.fromHighTrust(content.getSender()), message.getTimestamp(), messageId));
}
private void handleViewedReceipt(@NonNull SignalServiceContent content,

Wyświetl plik

@ -23,4 +23,12 @@
android:layout_gravity="center_horizontal"
android:text="@string/preferences__internal_disable_profile_sharing" />
<com.google.android.material.button.MaterialButton
android:id="@+id/internal_delete_session"
style="@style/Signal.Widget.Button.Small.Primary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/preferences__internal_delete_session" />
</LinearLayout>

Wyświetl plik

@ -2453,6 +2453,7 @@
<string name="preferences__internal_delete_all_dynamic_shortcuts" translatable="false">Delete all dynamic shortcuts</string>
<string name="preferences__internal_click_to_delete_all_dynamic_shortcuts" translatable="false">Click to delete all dynamic shortcuts</string>
<string name="preferences__internal_disable_profile_sharing" translatable="false">Disable Profile Sharing</string>
<string name="preferences__internal_delete_session" translatable="false">Delete Session</string>
<string name="preferences__internal_sender_key" translatable="false">Sender Key</string>
<string name="preferences__internal_clear_all_state" translatable="false">Clear all state</string>
<string name="preferences__internal_click_to_delete_all_sender_key_state" translatable="false">Click to delete all sender key state</string>