kopia lustrzana https://github.com/ryukoposting/Signal-Android
Add delivery receipts to the MSL.
rodzic
5372f79c40
commit
3d0e15e2b8
|
@ -300,6 +300,9 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
|||
recipient = state.recipient,
|
||||
onDisableProfileSharingClick = {
|
||||
viewModel.disableProfileSharing()
|
||||
},
|
||||
onDeleteSessionClick = {
|
||||
viewModel.deleteSession()
|
||||
}
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
Ładowanie…
Reference in New Issue