Add urgency flag to message sends.

fork-5.53.8
Cody Henthorne 2022-08-01 13:06:51 -04:00 zatwierdzone przez Greyson Parrelli
rodzic c7cd261641
commit dc04c8ed98
38 zmienionych plików z 256 dodań i 139 usunięć

Wyświetl plik

@ -6,6 +6,8 @@ import net.zetetic.database.sqlcipher.SQLiteConstraintException
import org.signal.core.util.CursorUtil
import org.signal.core.util.SqlUtil
import org.signal.core.util.logging.Log
import org.signal.core.util.requireBoolean
import org.signal.core.util.toInt
import org.thoughtcrime.securesms.database.model.MessageId
import org.thoughtcrime.securesms.database.model.MessageLogEntry
import org.thoughtcrime.securesms.recipients.Recipient
@ -67,13 +69,15 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
const val DATE_SENT = "date_sent"
const val CONTENT = "content"
const val CONTENT_HINT = "content_hint"
const val URGENT = "urgent"
const val CREATE_TABLE = """
CREATE TABLE $TABLE_NAME (
$ID INTEGER PRIMARY KEY,
$DATE_SENT INTEGER NOT NULL,
$CONTENT BLOB NOT NULL,
$CONTENT_HINT INTEGER NOT NULL
$CONTENT_HINT INTEGER NOT NULL,
$URGENT INTEGER NOT NULL DEFAULT 1
)
"""
@ -152,31 +156,31 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
}
/** @return The ID of the inserted entry, or -1 if none was inserted. Can be used with [addRecipientToExistingEntryIfPossible] */
fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId): Long {
fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId, urgent: Boolean): Long {
if (!FeatureFlags.retryReceipts()) return -1
if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) {
val recipientDevice = listOf(RecipientDevice(recipientId, sendMessageResult.success.devices))
return insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, listOf(messageId))
return insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, listOf(messageId), urgent)
}
return -1
}
/** @return The ID of the inserted entry, or -1 if none was inserted. Can be used with [addRecipientToExistingEntryIfPossible] */
fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageIds: List<MessageId>): Long {
fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageIds: List<MessageId>, urgent: Boolean): Long {
if (!FeatureFlags.retryReceipts()) return -1
if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) {
val recipientDevice = listOf(RecipientDevice(recipientId, sendMessageResult.success.devices))
return insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, messageIds)
return insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, messageIds, urgent)
}
return -1
}
/** @return The ID of the inserted entry, or -1 if none was inserted. Can be used with [addRecipientToExistingEntryIfPossible] */
fun insertIfPossible(sentTimestamp: Long, possibleRecipients: List<Recipient>, results: List<SendMessageResult>, contentHint: ContentHint, messageId: MessageId): Long {
fun insertIfPossible(sentTimestamp: Long, possibleRecipients: List<Recipient>, results: List<SendMessageResult>, contentHint: ContentHint, messageId: MessageId, urgent: Boolean): Long {
if (!FeatureFlags.retryReceipts()) return -1
val accessList = RecipientAccessList(possibleRecipients)
@ -194,10 +198,10 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
val content: SignalServiceProtos.Content = results.first { it.isSuccess && it.success.content.isPresent }.success.content.get()
return insert(recipientDevices, sentTimestamp, content, contentHint, listOf(messageId))
return insert(recipientDevices, sentTimestamp, content, contentHint, listOf(messageId), urgent)
}
fun addRecipientToExistingEntryIfPossible(payloadId: Long, recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId): Long {
fun addRecipientToExistingEntryIfPossible(payloadId: Long, recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId, urgent: Boolean): Long {
if (!FeatureFlags.retryReceipts()) return payloadId
if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) {
@ -218,9 +222,9 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
db.setTransactionSuccessful()
} catch (e: SQLiteConstraintException) {
Log.w(TAG, "Failed to append to existing entry. Creating a new one.")
val payloadId = insertIfPossible(recipientId, sentTimestamp, sendMessageResult, contentHint, messageId)
val newPayloadId = insertIfPossible(recipientId, sentTimestamp, sendMessageResult, contentHint, messageId, urgent)
db.setTransactionSuccessful()
return payloadId
return newPayloadId
} finally {
db.endTransaction()
}
@ -229,7 +233,7 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
return payloadId
}
private fun insert(recipients: List<RecipientDevice>, dateSent: Long, content: SignalServiceProtos.Content, contentHint: ContentHint, messageIds: List<MessageId>): Long {
private fun insert(recipients: List<RecipientDevice>, dateSent: Long, content: SignalServiceProtos.Content, contentHint: ContentHint, messageIds: List<MessageId>, urgent: Boolean): Long {
val db = databaseHelper.signalWritableDatabase
db.beginTransaction()
@ -238,6 +242,7 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
put(PayloadTable.DATE_SENT, dateSent)
put(PayloadTable.CONTENT, content.toByteArray())
put(PayloadTable.CONTENT_HINT, contentHint.type)
put(PayloadTable.URGENT, urgent.toInt())
}
val payloadId: Long = db.insert(PayloadTable.TABLE_NAME, null, payloadValues)
@ -304,6 +309,7 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
dateSent = CursorUtil.requireLong(entryCursor, PayloadTable.DATE_SENT),
content = SignalServiceProtos.Content.parseFrom(CursorUtil.requireBlob(entryCursor, PayloadTable.CONTENT)),
contentHint = ContentHint.fromType(CursorUtil.requireInt(entryCursor, PayloadTable.CONTENT_HINT)),
urgent = entryCursor.requireBoolean(PayloadTable.URGENT),
relatedMessages = messageIds
)
}

Wyświetl plik

@ -94,7 +94,8 @@ public class PushDatabase extends Database {
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_RECEIVED_TIMESTAMP)),
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_DELIVERED_TIMESTAMP)),
cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID)),
"");
"",
true);
}
} catch (IOException e) {
Log.w(TAG, e);
@ -180,7 +181,8 @@ public class PushDatabase extends Database {
serverReceivedTimestamp,
serverDeliveredTimestamp,
serverGuid,
"");
"",
true);
} catch (IOException e) {
throw new AssertionError(e);
}

Wyświetl plik

@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.conversation.colors.ChatColors
import org.thoughtcrime.securesms.conversation.colors.ChatColorsMapper.entrySet
import org.thoughtcrime.securesms.database.KeyValueDatabase
import org.thoughtcrime.securesms.database.RecipientDatabase
import org.thoughtcrime.securesms.database.helpers.migration.UrgentMslFlagMigration
import org.thoughtcrime.securesms.database.model.databaseprotos.ReactionList
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.groups.GroupId
@ -203,8 +204,9 @@ object SignalDatabaseMigrations {
private const val QUOTE_INDEX = 147
private const val MY_STORY_PRIVACY_MODE = 148
private const val EXPIRING_PROFILE_CREDENTIALS = 149
private const val URGENT_FLAG = 150
const val DATABASE_VERSION = 149
const val DATABASE_VERSION = 150
@JvmStatic
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
@ -2663,6 +2665,10 @@ object SignalDatabaseMigrations {
if (oldVersion < EXPIRING_PROFILE_CREDENTIALS) {
db.execSQL("UPDATE recipient SET profile_key_credential = NULL")
}
if (oldVersion < URGENT_FLAG) {
UrgentMslFlagMigration.migrate(context, db, oldVersion, newVersion)
}
}
@JvmStatic

Wyświetl plik

@ -0,0 +1,11 @@
package org.thoughtcrime.securesms.database.helpers.migration
import android.app.Application
import net.zetetic.database.sqlcipher.SQLiteDatabase
/**
* Simple interface for allowing database migrations to live outside of [org.thoughtcrime.securesms.database.helpers.SignalDatabaseMigrations].
*/
interface SignalDatabaseMigration {
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int)
}

Wyświetl plik

@ -0,0 +1,14 @@
package org.thoughtcrime.securesms.database.helpers.migration
import android.app.Application
import net.zetetic.database.sqlcipher.SQLiteDatabase
/**
* Adding an urgent flag to message envelopes to help with notifications. Need to track flag in
* MSL table so can be resent with the correct urgency.
*/
object UrgentMslFlagMigration : SignalDatabaseMigration {
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("ALTER TABLE msl_payload ADD COLUMN urgent INTEGER NOT NULL DEFAULT 1")
}
}

Wyświetl plik

@ -12,6 +12,8 @@ data class MessageLogEntry(
val dateSent: Long,
val content: SignalServiceProtos.Content,
val contentHint: ContentHint,
@get:JvmName("isUrgent")
val urgent: Boolean,
val relatedMessages: List<MessageId>
) {
val hasRelatedMessage: Boolean

Wyświetl plik

@ -1273,16 +1273,7 @@ final class GroupManagerV2 {
GroupId.V2 groupId = GroupId.v2(masterKey);
Recipient groupRecipient = Recipient.externalGroupExact(groupId);
DecryptedGroupV2Context decryptedGroupV2Context = GroupProtoUtil.createDecryptedGroupV2Context(masterKey, groupMutation, signedGroupChange);
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(groupRecipient,
decryptedGroupV2Context,
null,
System.currentTimeMillis(),
0,
false,
null,
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList());
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(groupRecipient, decryptedGroupV2Context, System.currentTimeMillis());
DecryptedGroupChange plainGroupChange = groupMutation.getGroupChange();

Wyświetl plik

@ -464,18 +464,8 @@ public class GroupsV2StateProcessor {
.addDeleteMembers(UuidUtil.toByteString(selfUuid))
.build();
DecryptedGroupV2Context decryptedGroupV2Context = GroupProtoUtil.createDecryptedGroupV2Context(masterKey, new GroupMutation(decryptedGroup, simulatedGroupChange, simulatedGroupState), null);
OutgoingGroupUpdateMessage leaveMessage = new OutgoingGroupUpdateMessage(groupRecipient,
decryptedGroupV2Context,
null,
System.currentTimeMillis(),
0,
false,
null,
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList());
DecryptedGroupV2Context decryptedGroupV2Context = GroupProtoUtil.createDecryptedGroupV2Context(masterKey, new GroupMutation(decryptedGroup, simulatedGroupChange, simulatedGroupState), null);
OutgoingGroupUpdateMessage leaveMessage = new OutgoingGroupUpdateMessage(groupRecipient, decryptedGroupV2Context, System.currentTimeMillis());
try {
MessageDatabase mmsDatabase = SignalDatabase.mms();
@ -703,7 +693,7 @@ public class GroupsV2StateProcessor {
ThreadDatabase threadDatabase = SignalDatabase.threads();
RecipientId recipientId = recipientDatabase.getOrInsertFromGroupId(groupId);
Recipient recipient = Recipient.resolved(recipientId);
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, decryptedGroupV2Context, null, timestamp, 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, decryptedGroupV2Context, timestamp);
long threadId = threadDatabase.getOrCreateThreadIdFor(recipient);
long messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null);

Wyświetl plik

@ -57,9 +57,9 @@ public class GroupCallUpdateSendJob extends BaseJob {
}
List<RecipientId> recipientIds = Stream.of(RecipientUtil.getEligibleForSending(Recipient.resolvedList(conversationRecipient.getParticipantIds())))
.filterNot(Recipient::isSelf)
.map(Recipient::getId)
.toList();
.filterNot(Recipient::isSelf)
.map(Recipient::getId)
.toList();
return new GroupCallUpdateSendJob(recipientId,
eraId,
@ -161,7 +161,8 @@ public class GroupCallUpdateSendJob extends BaseJob {
nonSelfDestinations,
false,
ContentHint.DEFAULT,
dataMessage);
dataMessage,
false);
if (includesSelf) {
results.add(ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(dataMessage));

Wyświetl plik

@ -110,7 +110,7 @@ public final class PaymentNotificationSendJob extends BaseJob {
.withPayment(new SignalServiceDataMessage.Payment(new SignalServiceDataMessage.PaymentNotification(payment.getReceipt(), payment.getNote())))
.build();
SendMessageResult sendMessageResult = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.DEFAULT, dataMessage, IndividualSendEvents.EMPTY);
SendMessageResult sendMessageResult = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.DEFAULT, dataMessage, IndividualSendEvents.EMPTY, false);
if (sendMessageResult.getIdentityFailure() != null) {
Log.w(TAG, "Identity failure for " + recipient.getId());

Wyświetl plik

@ -153,7 +153,7 @@ public class ProfileKeySendJob extends BaseJob {
.withTimestamp(System.currentTimeMillis())
.withProfileKey(Recipient.self().resolve().getProfileKey());
List<SendMessageResult> results = GroupSendUtil.sendUnresendableDataMessage(context, null, destinations, false, ContentHint.IMPLICIT, dataMessage.build());
List<SendMessageResult> results = GroupSendUtil.sendUnresendableDataMessage(context, null, destinations, false, ContentHint.IMPLICIT, dataMessage.build(), false);
return GroupSendJobHelper.getCompletedSends(destinations, results).completed;
}

Wyświetl plik

@ -292,7 +292,7 @@ public final class PushGroupSendJob extends PushSendJob {
.withExpiration(groupRecipient.getExpiresInSeconds())
.asGroupMessage(group)
.build();
return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.requireGroupId().requireV2(), destinations, isRecipientUpdate, ContentHint.IMPLICIT, new MessageId(messageId, true), groupDataMessage);
return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.requireGroupId().requireV2(), destinations, isRecipientUpdate, ContentHint.IMPLICIT, new MessageId(messageId, true), groupDataMessage, message.isUrgent());
} else {
throw new UndeliverableMessageException("Messages can no longer be sent to V1 groups!");
}
@ -351,7 +351,8 @@ public final class PushGroupSendJob extends PushSendJob {
isRecipientUpdate,
ContentHint.RESENDABLE,
new MessageId(messageId, true),
groupMessageBuilder.build());
groupMessageBuilder.build(),
message.isUrgent());
}
} catch (ServerRejectedException e) {
throw new UndeliverableMessageException(e);

Wyświetl plik

@ -175,7 +175,7 @@ public final class PushGroupSilentUpdateSendJob extends BaseJob {
.asGroupMessage(group)
.build();
List<SendMessageResult> results = GroupSendUtil.sendUnresendableDataMessage(context, groupId, destinations, false, ContentHint.IMPLICIT, groupDataMessage);
List<SendMessageResult> results = GroupSendUtil.sendUnresendableDataMessage(context, groupId, destinations, false, ContentHint.IMPLICIT, groupDataMessage, false);
return GroupSendJobHelper.getCompletedSends(destinations, results).completed;
}

Wyświetl plik

@ -254,11 +254,11 @@ public class PushMediaSendJob extends PushSendJob {
if (Util.equals(SignalStore.account().getAci(), address.getServiceId())) {
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
SendMessageResult result = messageSender.sendSyncMessage(mediaMessage);
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true));
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true), false);
return syncAccess.isPresent();
} else {
SendMessageResult result = messageSender.sendDataMessage(address, UnidentifiedAccessUtil.getAccessFor(context, messageRecipient), ContentHint.RESENDABLE, mediaMessage, IndividualSendEvents.EMPTY);
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true));
SendMessageResult result = messageSender.sendDataMessage(address, UnidentifiedAccessUtil.getAccessFor(context, messageRecipient), ContentHint.RESENDABLE, mediaMessage, IndividualSendEvents.EMPTY, message.isUrgent());
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true), message.isUrgent());
return result.getSuccess().isUnidentified();
}
} catch (UnregisteredUserException e) {

Wyświetl plik

@ -194,13 +194,13 @@ public class PushTextSendJob extends PushSendJob {
SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId);
SendMessageResult result = messageSender.sendSyncMessage(textSecureMessage);
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false));
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false), false);
return syncAccess.isPresent();
} else {
SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId);
SendMessageResult result = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.RESENDABLE, textSecureMessage, new MetricEventListener(messageId));
SendMessageResult result = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.RESENDABLE, textSecureMessage, new MetricEventListener(messageId), true);
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false));
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false), true);
return result.getSuccess().isUnidentified();
}
} catch (UnregisteredUserException e) {

Wyświetl plik

@ -242,7 +242,8 @@ public class ReactionSendJob extends BaseJob {
false,
ContentHint.RESENDABLE,
messageId,
dataMessage);
dataMessage,
true);
if (includesSelf) {
results.add(ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(dataMessage));

Wyświetl plik

@ -214,7 +214,8 @@ public class RemoteDeleteSendJob extends BaseJob {
false,
ContentHint.RESENDABLE,
new MessageId(messageId, isMms),
dataMessage);
dataMessage,
true);
return GroupSendJobHelper.getCompletedSends(destinations, results);
}

Wyświetl plik

@ -51,6 +51,7 @@ public class ResendMessageJob extends BaseJob {
private final long sentTimestamp;
private final Content content;
private final ContentHint contentHint;
private final boolean urgent;
private final GroupId.V2 groupId;
private final DistributionId distributionId;
@ -58,6 +59,7 @@ public class ResendMessageJob extends BaseJob {
private static final String KEY_SENT_TIMESTAMP = "sent_timestamp";
private static final String KEY_CONTENT = "content";
private static final String KEY_CONTENT_HINT = "content_hint";
private static final String KEY_URGENT = "urgent";
private static final String KEY_GROUP_ID = "group_id";
private static final String KEY_DISTRIBUTION_ID = "distribution_id";
@ -65,6 +67,7 @@ public class ResendMessageJob extends BaseJob {
long sentTimestamp,
@NonNull Content content,
@NonNull ContentHint contentHint,
boolean urgent,
@Nullable GroupId.V2 groupId,
@Nullable DistributionId distributionId)
{
@ -72,6 +75,7 @@ public class ResendMessageJob extends BaseJob {
sentTimestamp,
content,
contentHint,
urgent,
groupId,
distributionId,
new Parameters.Builder().setQueue(recipientId.toQueueKey())
@ -85,6 +89,7 @@ public class ResendMessageJob extends BaseJob {
long sentTimestamp,
@NonNull Content content,
@NonNull ContentHint contentHint,
boolean urgent,
@Nullable GroupId.V2 groupId,
@Nullable DistributionId distributionId,
@NonNull Parameters parameters)
@ -95,6 +100,7 @@ public class ResendMessageJob extends BaseJob {
this.sentTimestamp = sentTimestamp;
this.content = content;
this.contentHint = contentHint;
this.urgent = urgent;
this.groupId = groupId;
this.distributionId = distributionId;
}
@ -106,6 +112,7 @@ public class ResendMessageJob extends BaseJob {
.putLong(KEY_SENT_TIMESTAMP, sentTimestamp)
.putBlobAsString(KEY_CONTENT, content.toByteArray())
.putInt(KEY_CONTENT_HINT, contentHint.getType())
.putBoolean(KEY_URGENT, urgent)
.putBlobAsString(KEY_GROUP_ID, groupId != null ? groupId.getDecodedId() : null)
.putString(KEY_DISTRIBUTION_ID, distributionId != null ? distributionId.toString() : null)
.build();
@ -152,7 +159,7 @@ public class ResendMessageJob extends BaseJob {
contentToSend = contentToSend.toBuilder().setSenderKeyDistributionMessage(distributionBytes).build();
}
SendMessageResult result = messageSender.resendContent(address, access, sentTimestamp, contentToSend, contentHint, Optional.ofNullable(groupId).map(GroupId::getDecodedId));
SendMessageResult result = messageSender.resendContent(address, access, sentTimestamp, contentToSend, contentHint, Optional.ofNullable(groupId).map(GroupId::getDecodedId), urgent);
if (result.isSuccess() && distributionId != null) {
List<SignalProtocolAddress> addresses = result.getSuccess()
@ -195,6 +202,7 @@ public class ResendMessageJob extends BaseJob {
data.getLong(KEY_SENT_TIMESTAMP),
content,
ContentHint.fromType(data.getInt(KEY_CONTENT_HINT)),
data.getBooleanOrDefault(KEY_URGENT, true),
groupId,
distributionId,
parameters);

Wyświetl plik

@ -122,7 +122,7 @@ public class SendDeliveryReceiptJob extends BaseJob {
receiptMessage);
if (messageId != null) {
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageId);
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageId, false);
}
}

Wyświetl plik

@ -186,7 +186,7 @@ public class SendReadReceiptJob extends BaseJob {
receiptMessage);
if (Util.hasItems(messageIds)) {
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds);
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds, false);
}
}

Wyświetl plik

@ -182,7 +182,7 @@ public class SendViewedReceiptJob extends BaseJob {
receiptMessage);
if (Util.hasItems(messageIds)) {
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds);
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds, false);
}
}

Wyświetl plik

@ -101,7 +101,7 @@ public final class SenderKeyDistributionSendJob extends BaseJob {
SenderKeyDistributionMessage message = messageSender.getOrCreateNewGroupSession(distributionId);
List<Optional<UnidentifiedAccessPair>> access = UnidentifiedAccessUtil.getAccessFor(context, Collections.singletonList(recipient));
SendMessageResult result = messageSender.sendSenderKeyDistributionMessage(distributionId, address, access, message, Optional.of(groupId.getDecodedId())).get(0);
SendMessageResult result = messageSender.sendSenderKeyDistributionMessage(distributionId, address, access, message, Optional.of(groupId.getDecodedId()), false).get(0);
if (result.isSuccess()) {
List<SignalProtocolAddress> addresses = result.getSuccess()

Wyświetl plik

@ -88,10 +88,11 @@ public final class GroupSendUtil {
boolean isRecipientUpdate,
ContentHint contentHint,
@NonNull MessageId messageId,
@NonNull SignalServiceDataMessage message)
@NonNull SignalServiceDataMessage message,
boolean urgent)
throws IOException, UntrustedIdentityException
{
return sendMessage(context, groupId, getDistributionId(groupId), messageId, allTargets, isRecipientUpdate, DataSendOperation.resendable(message, contentHint, messageId), null);
return sendMessage(context, groupId, getDistributionId(groupId), messageId, allTargets, isRecipientUpdate, DataSendOperation.resendable(message, contentHint, messageId, urgent), null);
}
/**
@ -109,10 +110,11 @@ public final class GroupSendUtil {
@NonNull List<Recipient> allTargets,
boolean isRecipientUpdate,
ContentHint contentHint,
@NonNull SignalServiceDataMessage message)
@NonNull SignalServiceDataMessage message,
boolean urgent)
throws IOException, UntrustedIdentityException
{
return sendMessage(context, groupId, getDistributionId(groupId), null, allTargets, isRecipientUpdate, DataSendOperation.unresendable(message, contentHint), null);
return sendMessage(context, groupId, getDistributionId(groupId), null, allTargets, isRecipientUpdate, DataSendOperation.unresendable(message, contentHint, urgent), null);
}
/**
@ -295,7 +297,7 @@ public final class GroupSendUtil {
Log.d(TAG, "Successfully sent using sender key to " + successCount + "/" + targets.size() + " sender key targets.");
if (sendOperation.shouldIncludeInMessageLog()) {
SignalDatabase.messageLog().insertIfPossible(sendOperation.getSentTimestamp(), senderKeyTargets, results, sendOperation.getContentHint(), sendOperation.getRelatedMessageId());
SignalDatabase.messageLog().insertIfPossible(sendOperation.getSentTimestamp(), senderKeyTargets, results, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isUrgent());
}
if (relatedMessageId != null) {
@ -353,9 +355,9 @@ public final class GroupSendUtil {
synchronized (entryId) {
if (entryId.get() == -1) {
entryId.set(messageLogDatabase.insertIfPossible(recipients.requireRecipientId(result.getAddress()), sendOperation.getSentTimestamp(), result, sendOperation.getContentHint(), sendOperation.getRelatedMessageId()));
entryId.set(messageLogDatabase.insertIfPossible(recipients.requireRecipientId(result.getAddress()), sendOperation.getSentTimestamp(), result, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isUrgent()));
} else {
entryId.set(messageLogDatabase.addRecipientToExistingEntryIfPossible(entryId.get(), recipients.requireRecipientId(result.getAddress()), sendOperation.getSentTimestamp(), result, sendOperation.getContentHint(), sendOperation.getRelatedMessageId()));
entryId.set(messageLogDatabase.addRecipientToExistingEntryIfPossible(entryId.get(), recipients.requireRecipientId(result.getAddress()), sendOperation.getSentTimestamp(), result, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isUrgent()));
}
}
}, cancelationSignal);
@ -424,6 +426,7 @@ public final class GroupSendUtil {
long getSentTimestamp();
boolean shouldIncludeInMessageLog();
@NonNull MessageId getRelatedMessageId();
boolean isUrgent();
}
private static class DataSendOperation implements SendOperation {
@ -431,20 +434,22 @@ public final class GroupSendUtil {
private final ContentHint contentHint;
private final MessageId relatedMessageId;
private final boolean resendable;
private final boolean urgent;
public static DataSendOperation resendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, @NonNull MessageId relatedMessageId) {
return new DataSendOperation(message, contentHint, true, relatedMessageId);
public static DataSendOperation resendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, @NonNull MessageId relatedMessageId, boolean urgent) {
return new DataSendOperation(message, contentHint, true, relatedMessageId, urgent);
}
public static DataSendOperation unresendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint) {
return new DataSendOperation(message, contentHint, false, null);
public static DataSendOperation unresendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean urgent) {
return new DataSendOperation(message, contentHint, false, null, urgent);
}
private DataSendOperation(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean resendable, @Nullable MessageId relatedMessageId) {
this.message = message;
this.contentHint = contentHint;
this.resendable = resendable;
this.relatedMessageId = relatedMessageId;
private DataSendOperation(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean resendable, @Nullable MessageId relatedMessageId, boolean urgent) {
this.message = message;
this.contentHint = contentHint;
this.resendable = resendable;
this.relatedMessageId = relatedMessageId;
this.urgent = urgent;
if (resendable && relatedMessageId == null) {
throw new IllegalArgumentException("If a message is resendable, it must have a related message ID!");
@ -460,7 +465,7 @@ public final class GroupSendUtil {
throws NoSessionException, UntrustedIdentityException, InvalidKeyException, IOException, InvalidRegistrationIdException
{
SenderKeyGroupEvents listener = relatedMessageId != null ? new SenderKeyMetricEventListener(relatedMessageId.getId()) : SenderKeyGroupEvents.EMPTY;
return messageSender.sendGroupDataMessage(distributionId, targets, access, isRecipientUpdate, contentHint, message, listener);
return messageSender.sendGroupDataMessage(distributionId, targets, access, isRecipientUpdate, contentHint, message, listener, urgent);
}
@Override
@ -473,7 +478,7 @@ public final class GroupSendUtil {
throws IOException, UntrustedIdentityException
{
LegacyGroupEvents listener = relatedMessageId != null ? new LegacyMetricEventListener(relatedMessageId.getId()) : LegacyGroupEvents.EMPTY;
return messageSender.sendDataMessage(targets, access, isRecipientUpdate, contentHint, message, listener, partialListener, cancelationSignal);
return messageSender.sendDataMessage(targets, access, isRecipientUpdate, contentHint, message, listener, partialListener, cancelationSignal, urgent);
}
@Override
@ -499,6 +504,11 @@ public final class GroupSendUtil {
throw new UnsupportedOperationException();
}
}
@Override
public boolean isUrgent() {
return urgent;
}
}
private static class TypingSendOperation implements SendOperation {
@ -553,6 +563,11 @@ public final class GroupSendUtil {
public @NonNull MessageId getRelatedMessageId() {
throw new UnsupportedOperationException();
}
@Override
public boolean isUrgent() {
return false;
}
}
private static class CallSendOperation implements SendOperation {
@ -605,6 +620,11 @@ public final class GroupSendUtil {
public @NonNull MessageId getRelatedMessageId() {
throw new UnsupportedOperationException();
}
@Override
public boolean isUrgent() {
return message.isUrgent();
}
}
public static class StorySendOperation implements SendOperation {
@ -670,6 +690,11 @@ public final class GroupSendUtil {
public @NonNull MessageId getRelatedMessageId() {
return relatedMessageId;
}
@Override
public boolean isUrgent() {
return false;
}
}
private static final class SenderKeyMetricEventListener implements SenderKeyGroupEvents {

Wyświetl plik

@ -2694,6 +2694,7 @@ public final class MessageContentProcessor {
messageLogEntry.getDateSent(),
messageLogEntry.getContent(),
messageLogEntry.getContentHint(),
messageLogEntry.isUrgent(),
groupId,
distributionId));
} else {
@ -2735,6 +2736,7 @@ public final class MessageContentProcessor {
messageLogEntry.getDateSent(),
messageLogEntry.getContent(),
messageLogEntry.getContentHint(),
messageLogEntry.isUrgent(),
null,
null));
} else if (archivedSession) {

Wyświetl plik

@ -32,4 +32,8 @@ public class OutgoingExpirationUpdateMessage extends OutgoingSecureMediaMessage
return true;
}
@Override
public boolean isUrgent() {
return false;
}
}

Wyświetl plik

@ -67,16 +67,9 @@ public final class OutgoingGroupUpdateMessage extends OutgoingSecureMediaMessage
public OutgoingGroupUpdateMessage(@NonNull Recipient recipient,
@NonNull DecryptedGroupV2Context group,
@Nullable final Attachment avatar,
long sentTimeMillis,
long expireIn,
boolean viewOnce,
@Nullable QuoteModel quote,
@NonNull List<Contact> contacts,
@NonNull List<LinkPreview> previews,
@NonNull List<Mention> mentions)
long sentTimeMillis)
{
this(recipient, new MessageGroupContext(group), getAttachments(avatar), sentTimeMillis, expireIn, viewOnce, quote, contacts, previews, mentions);
this(recipient, new MessageGroupContext(group), Collections.emptyList(), sentTimeMillis, 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
}
@Override
@ -100,6 +93,11 @@ public final class OutgoingGroupUpdateMessage extends OutgoingSecureMediaMessage
return messageGroupContext.requireGroupV2Properties();
}
@Override
public boolean isUrgent() {
return false;
}
private static List<Attachment> getAttachments(@Nullable Attachment avatar) {
return avatar == null ? Collections.emptyList() : Collections.singletonList(avatar);
}

Wyświetl plik

@ -249,6 +249,10 @@ public class OutgoingMediaMessage {
return giftBadge;
}
public boolean isUrgent() {
return true;
}
private static String buildMessage(SlideDeck slideDeck, String message) {
if (!TextUtils.isEmpty(message) && !TextUtils.isEmpty(slideDeck.getBody())) {
return slideDeck.getBody() + "\n\n" + message;

Wyświetl plik

@ -225,7 +225,8 @@ public class SignalServiceMessageReceiver {
entity.getServerTimestamp(),
messageResult.getServerDeliveredTimestamp(),
entity.getServerUuid(),
entity.getDestinationUuid());
entity.getDestinationUuid(),
entity.isUrgent());
} else {
envelope = new SignalServiceEnvelope(entity.getType(),
entity.getTimestamp(),
@ -234,7 +235,8 @@ public class SignalServiceMessageReceiver {
entity.getServerTimestamp(),
messageResult.getServerDeliveredTimestamp(),
entity.getServerUuid(),
entity.getDestinationUuid());
entity.getDestinationUuid(),
entity.isUrgent());
}
callback.onMessage(envelope);

Wyświetl plik

@ -203,7 +203,7 @@ public class SignalServiceMessageSender {
Content content = createReceiptContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty());
return sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), message.getWhen(), envelopeContent, false, null);
return sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), message.getWhen(), envelopeContent, false, null, false);
}
/**
@ -219,7 +219,7 @@ public class SignalServiceMessageSender {
PlaintextContent content = new PlaintextContent(errorMessage);
EnvelopeContent envelopeContent = EnvelopeContent.plaintext(content, groupId);
sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null);
sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null, false);
}
/**
@ -234,7 +234,7 @@ public class SignalServiceMessageSender {
Content content = createTypingContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty());
sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), message.getTimestamp(), envelopeContent, true, null, cancelationSignal);
sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), message.getTimestamp(), envelopeContent, true, null, cancelationSignal, false);
}
/**
@ -247,7 +247,7 @@ public class SignalServiceMessageSender {
throws IOException, UntrustedIdentityException, InvalidKeyException, NoSessionException, InvalidRegistrationIdException
{
Content content = createTypingContent(message);
sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp(), content, ContentHint.IMPLICIT, message.getGroupId(), true, SenderKeyGroupEvents.EMPTY);
sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp(), content, ContentHint.IMPLICIT, message.getGroupId(), true, SenderKeyGroupEvents.EMPTY, false);
}
public List<SendMessageResult> sendStory(List<SignalServiceAddress> recipients,
@ -260,7 +260,7 @@ public class SignalServiceMessageSender {
{
Content content = createStoryContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.RESENDABLE, Optional.empty());
List<SendMessageResult> sendMessageResults = sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null, null);
List<SendMessageResult> sendMessageResults = sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null, null, false);
if (store.isMultiDevice()) {
SignalServiceSyncMessage syncMessage = createSelfSendSyncMessageForStory(message, timestamp, isRecipientUpdate, manifest);
@ -284,7 +284,7 @@ public class SignalServiceMessageSender {
throws IOException, UntrustedIdentityException, InvalidKeyException, NoSessionException, InvalidRegistrationIdException
{
Content content = createStoryContent(message);
List<SendMessageResult> sendMessageResults = sendGroupMessage(distributionId, recipients, unidentifiedAccess, timestamp, content, ContentHint.RESENDABLE, groupId, false, SenderKeyGroupEvents.EMPTY);
List<SendMessageResult> sendMessageResults = sendGroupMessage(distributionId, recipients, unidentifiedAccess, timestamp, content, ContentHint.RESENDABLE, groupId, false, SenderKeyGroupEvents.EMPTY, false);
if (store.isMultiDevice()) {
SignalServiceSyncMessage syncMessage = createSelfSendSyncMessageForStory(message, timestamp, isRecipientUpdate, manifest);
@ -310,7 +310,7 @@ public class SignalServiceMessageSender {
Content content = createCallContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.DEFAULT, Optional.empty());
sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null);
sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null, message.isUrgent());
}
public List<SendMessageResult> sendCallMessage(List<SignalServiceAddress> recipients,
@ -321,7 +321,7 @@ public class SignalServiceMessageSender {
Content content = createCallContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.DEFAULT, Optional.empty());
return sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null, null);
return sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null, null, message.isUrgent());
}
public List<SendMessageResult> sendCallMessage(DistributionId distributionId,
@ -331,7 +331,7 @@ public class SignalServiceMessageSender {
throws IOException, UntrustedIdentityException, InvalidKeyException, NoSessionException, InvalidRegistrationIdException
{
Content content = createCallContent(message);
return sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp().get(), content, ContentHint.IMPLICIT, message.getGroupId(), false, SenderKeyGroupEvents.EMPTY);
return sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp().get(), content, ContentHint.IMPLICIT, message.getGroupId(), false, SenderKeyGroupEvents.EMPTY, message.isUrgent());
}
/**
@ -360,7 +360,8 @@ public class SignalServiceMessageSender {
Optional<UnidentifiedAccessPair> unidentifiedAccess,
ContentHint contentHint,
SignalServiceDataMessage message,
IndividualSendEvents sendEvents)
IndividualSendEvents sendEvents,
boolean urgent)
throws UntrustedIdentityException, IOException
{
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a data message.");
@ -371,7 +372,7 @@ public class SignalServiceMessageSender {
sendEvents.onMessageEncrypted();
long timestamp = message.getTimestamp();
SendMessageResult result = sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null);
SendMessageResult result = sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null, urgent);
sendEvents.onMessageSent();
@ -379,7 +380,7 @@ public class SignalServiceMessageSender {
Content syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.of(recipient), timestamp, Collections.singletonList(result), false, Collections.emptySet());
EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.empty());
sendMessage(localAddress, Optional.empty(), timestamp, syncMessageContent, false, null);
sendMessage(localAddress, Optional.empty(), timestamp, syncMessageContent, false, null, false);
}
sendEvents.onSyncMessageSent();
@ -403,7 +404,8 @@ public class SignalServiceMessageSender {
List<SignalServiceAddress> recipients,
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess,
SenderKeyDistributionMessage message,
Optional<byte[]> groupId)
Optional<byte[]> groupId,
boolean urgent)
throws IOException
{
ByteString distributionBytes = ByteString.copyFrom(message.serialize());
@ -412,7 +414,7 @@ public class SignalServiceMessageSender {
long timestamp = System.currentTimeMillis();
Log.d(TAG, "[" + timestamp + "] Sending SKDM to " + recipients.size() + " recipients for DistributionId " + distributionId);
return sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null, null);
return sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null, null, urgent);
}
/**
@ -430,13 +432,14 @@ public class SignalServiceMessageSender {
long timestamp,
Content content,
ContentHint contentHint,
Optional<byte[]> groupId)
Optional<byte[]> groupId,
boolean urgent)
throws UntrustedIdentityException, IOException
{
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, contentHint, groupId);
Optional<UnidentifiedAccess> access = unidentifiedAccess.isPresent() ? unidentifiedAccess.get().getTargetUnidentifiedAccess() : Optional.empty();
return sendMessage(address, access, timestamp, envelopeContent, false, null);
return sendMessage(address, access, timestamp, envelopeContent, false, null, urgent);
}
/**
@ -448,14 +451,15 @@ public class SignalServiceMessageSender {
boolean isRecipientUpdate,
ContentHint contentHint,
SignalServiceDataMessage message,
SenderKeyGroupEvents sendEvents)
SenderKeyGroupEvents sendEvents,
boolean urgent)
throws IOException, UntrustedIdentityException, NoSessionException, InvalidKeyException, InvalidRegistrationIdException
{
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a group data message to " + recipients.size() + " recipients using DistributionId " + distributionId);
Content content = createMessageContent(message);
Optional<byte[]> groupId = message.getGroupId();
List<SendMessageResult> results = sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp(), content, contentHint, groupId, false, sendEvents);
List<SendMessageResult> results = sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp(), content, contentHint, groupId, false, sendEvents, urgent);
sendEvents.onMessageSent();
@ -463,7 +467,7 @@ public class SignalServiceMessageSender {
Content syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.empty(), message.getTimestamp(), results, isRecipientUpdate, Collections.emptySet());
EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.empty());
sendMessage(localAddress, Optional.empty(), message.getTimestamp(), syncMessageContent, false, null);
sendMessage(localAddress, Optional.empty(), message.getTimestamp(), syncMessageContent, false, null, false);
}
sendEvents.onSyncMessageSent();
@ -484,7 +488,8 @@ public class SignalServiceMessageSender {
SignalServiceDataMessage message,
LegacyGroupEvents sendEvents,
PartialSendCompleteListener partialListener,
CancelationSignal cancelationSignal)
CancelationSignal cancelationSignal,
boolean urgent)
throws IOException, UntrustedIdentityException
{
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a data message to " + recipients.size() + " recipients.");
@ -492,7 +497,7 @@ public class SignalServiceMessageSender {
Content content = createMessageContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, contentHint, message.getGroupId());
long timestamp = message.getTimestamp();
List<SendMessageResult> results = sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, partialListener, cancelationSignal);
List<SendMessageResult> results = sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, partialListener, cancelationSignal, urgent);
boolean needsSyncInResults = false;
sendEvents.onMessageSent();
@ -513,7 +518,7 @@ public class SignalServiceMessageSender {
Content syncMessage = createMultiDeviceSentTranscriptContent(content, recipient, timestamp, results, isRecipientUpdate, Collections.emptySet());
EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.empty());
sendMessage(localAddress, Optional.empty(), timestamp, syncMessageContent, false, null);
sendMessage(localAddress, Optional.empty(), timestamp, syncMessageContent, false, null, false);
}
sendEvents.onSyncMessageSent();
@ -531,14 +536,15 @@ public class SignalServiceMessageSender {
throws IOException, UntrustedIdentityException
{
Content content;
boolean urgent = false;
if (message.getContacts().isPresent()) {
content = createMultiDeviceContactsContent(message.getContacts().get().getContactsStream().asStream(),
message.getContacts().get().isComplete());
content = createMultiDeviceContactsContent(message.getContacts().get().getContactsStream().asStream(), message.getContacts().get().isComplete());
} else if (message.getGroups().isPresent()) {
content = createMultiDeviceGroupsContent(message.getGroups().get().asStream());
} else if (message.getRead().isPresent()) {
content = createMultiDeviceReadContent(message.getRead().get());
urgent = true;
} else if (message.getViewed().isPresent()) {
content = createMultiDeviceViewedContent(message.getViewed().get());
} else if (message.getViewOnceOpen().isPresent()) {
@ -563,6 +569,7 @@ public class SignalServiceMessageSender {
return sendVerifiedSyncMessage(message.getVerified().get());
} else if (message.getRequest().isPresent()) {
content = createRequestContent(message.getRequest().get().getRequest());
urgent = message.getRequest().get().isUrgent();
} else if (message.getPniIdentity().isPresent()) {
content = createPniIdentityContent(message.getPniIdentity().get());
} else {
@ -574,7 +581,7 @@ public class SignalServiceMessageSender {
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty());
return sendMessage(localAddress, Optional.empty(), timestamp, envelopeContent, false, null);
return sendMessage(localAddress, Optional.empty(), timestamp, envelopeContent, false, null, urgent);
}
public void setSoTimeoutMillis(long soTimeoutMillis) {
@ -711,13 +718,13 @@ public class SignalServiceMessageSender {
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty());
SendMessageResult result = sendMessage(message.getDestination(), Optional.empty(), message.getTimestamp(), envelopeContent, false, null);
SendMessageResult result = sendMessage(message.getDestination(), Optional.empty(), message.getTimestamp(), envelopeContent, false, null, false);
if (result.getSuccess().isNeedsSync()) {
Content syncMessage = createMultiDeviceVerifiedContent(message, nullMessage.toByteArray());
EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.empty());
sendMessage(localAddress, Optional.empty(), message.getTimestamp(), syncMessageContent, false, null);
sendMessage(localAddress, Optional.empty(), message.getTimestamp(), syncMessageContent, false, null, false);
}
return result;
@ -741,7 +748,7 @@ public class SignalServiceMessageSender {
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty());
return sendMessage(address, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null);
return sendMessage(address, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null, false);
}
private Content createTypingContent(SignalServiceTypingMessage message) {
@ -1616,7 +1623,8 @@ public class SignalServiceMessageSender {
EnvelopeContent content,
boolean online,
PartialSendCompleteListener partialListener,
CancelationSignal cancelationSignal)
CancelationSignal cancelationSignal,
boolean urgent)
throws IOException
{
Log.d(TAG, "[" + timestamp + "] Sending to " + recipients.size() + " recipients.");
@ -1631,7 +1639,7 @@ public class SignalServiceMessageSender {
SignalServiceAddress recipient = recipientIterator.next();
Optional<UnidentifiedAccess> access = unidentifiedAccessIterator.next();
futureResults.add(executor.submit(() -> {
SendMessageResult result = sendMessage(recipient, access, timestamp, content, online, cancelationSignal);
SendMessageResult result = sendMessage(recipient, access, timestamp, content, online, cancelationSignal, urgent);
if (partialListener != null) {
partialListener.onPartialSendComplete(result);
}
@ -1698,7 +1706,8 @@ public class SignalServiceMessageSender {
long timestamp,
EnvelopeContent content,
boolean online,
CancelationSignal cancelationSignal)
CancelationSignal cancelationSignal,
boolean urgent)
throws UntrustedIdentityException, IOException
{
enforceMaxContentSize(content);
@ -1711,7 +1720,7 @@ public class SignalServiceMessageSender {
}
try {
OutgoingPushMessageList messages = getEncryptedMessages(socket, recipient, unidentifiedAccess, timestamp, content, online);
OutgoingPushMessageList messages = getEncryptedMessages(socket, recipient, unidentifiedAccess, timestamp, content, online, urgent);
if (content.getContent().isPresent() && content.getContent().get().getSyncMessage() != null && content.getContent().get().getSyncMessage().hasSent()) {
Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a sent sync message to devices: " + messages.getDevices());
@ -1796,7 +1805,8 @@ public class SignalServiceMessageSender {
ContentHint contentHint,
Optional<byte[]> groupId,
boolean online,
SenderKeyGroupEvents sendEvents)
SenderKeyGroupEvents sendEvents,
boolean urgent)
throws IOException, UntrustedIdentityException, NoSessionException, InvalidKeyException, InvalidRegistrationIdException
{
if (recipients.isEmpty()) {
@ -1833,7 +1843,7 @@ public class SignalServiceMessageSender {
})
.collect(Collectors.toList());
List<SendMessageResult> results = sendSenderKeyDistributionMessage(distributionId, needsSenderKey, access, message, groupId);
List<SendMessageResult> results = sendSenderKeyDistributionMessage(distributionId, needsSenderKey, access, message, groupId, urgent);
List<SignalServiceAddress> successes = results.stream()
.filter(SendMessageResult::isSuccess)
@ -1895,7 +1905,7 @@ public class SignalServiceMessageSender {
try {
try {
SendGroupMessageResponse response = new MessagingService.SendResponseProcessor<>(messagingService.sendToGroup(ciphertext, joinedUnidentifiedAccess, timestamp, online).blockingGet()).getResultOrThrow();
SendGroupMessageResponse response = new MessagingService.SendResponseProcessor<>(messagingService.sendToGroup(ciphertext, joinedUnidentifiedAccess, timestamp, online, urgent).blockingGet()).getResultOrThrow();
return transformGroupResponseToMessageResults(targetInfo.devices, response, content);
} catch (InvalidUnidentifiedAccessHeaderException | NotFoundException | GroupMismatchedDevicesException | GroupStaleDevicesException e) {
// Non-technical failures shouldn't be retried with socket
@ -1906,7 +1916,7 @@ public class SignalServiceMessageSender {
Log.w(TAG, "[sendGroupMessage][" + timestamp + "] Pipe failed, falling back... (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
}
SendGroupMessageResponse response = socket.sendGroupMessage(ciphertext, joinedUnidentifiedAccess, timestamp, online);
SendGroupMessageResponse response = socket.sendGroupMessage(ciphertext, joinedUnidentifiedAccess, timestamp, online, urgent);
return transformGroupResponseToMessageResults(targetInfo.devices, response, content);
} catch (GroupMismatchedDevicesException e) {
Log.w(TAG, "[sendGroupMessage][" + timestamp + "] Handling mismatched devices. (" + e.getMessage() + ")");
@ -2070,7 +2080,8 @@ public class SignalServiceMessageSender {
Optional<UnidentifiedAccess> unidentifiedAccess,
long timestamp,
EnvelopeContent plaintext,
boolean online)
boolean online,
boolean urgent)
throws IOException, InvalidKeyException, UntrustedIdentityException
{
List<OutgoingPushMessage> messages = new LinkedList<>();
@ -2091,7 +2102,7 @@ public class SignalServiceMessageSender {
}
}
return new OutgoingPushMessageList(recipient.getIdentifier(), timestamp, messages, online);
return new OutgoingPushMessageList(recipient.getIdentifier(), timestamp, messages, online, urgent);
}
private OutgoingPushMessage getEncryptedMessage(PushServiceSocket socket,

Wyświetl plik

@ -65,14 +65,16 @@ public class SignalServiceEnvelope {
long serverReceivedTimestamp,
long serverDeliveredTimestamp,
String uuid,
String destinationUuid)
String destinationUuid,
boolean urgent)
{
Envelope.Builder builder = Envelope.newBuilder()
.setType(Envelope.Type.valueOf(type))
.setSourceDevice(senderDevice)
.setTimestamp(timestamp)
.setServerTimestamp(serverReceivedTimestamp)
.setDestinationUuid(destinationUuid);
.setDestinationUuid(destinationUuid)
.setUrgent(urgent);
if (sender.isPresent()) {
builder.setSourceUuid(sender.get().getServiceId().toString());
@ -100,13 +102,15 @@ public class SignalServiceEnvelope {
long serverReceivedTimestamp,
long serverDeliveredTimestamp,
String uuid,
String destinationUuid)
String destinationUuid,
boolean urgent)
{
Envelope.Builder builder = Envelope.newBuilder()
.setType(Envelope.Type.valueOf(type))
.setTimestamp(timestamp)
.setServerTimestamp(serverReceivedTimestamp)
.setDestinationUuid(destinationUuid);
.setDestinationUuid(destinationUuid)
.setUrgent(urgent);
if (uuid != null) {
builder.setServerGuid(uuid);
@ -273,6 +277,9 @@ public class SignalServiceEnvelope {
return envelope.getDestinationUuid();
}
public boolean isUrgent() {
return envelope.getUrgent();
}
private SignalServiceEnvelopeProto.Builder serializeToProto() {
SignalServiceEnvelopeProto.Builder builder = SignalServiceEnvelopeProto.newBuilder()
@ -280,7 +287,8 @@ public class SignalServiceEnvelope {
.setDeviceId(getSourceDevice())
.setTimestamp(getTimestamp())
.setServerReceivedTimestamp(getServerReceivedTimestamp())
.setServerDeliveredTimestamp(getServerDeliveredTimestamp());
.setServerDeliveredTimestamp(getServerDeliveredTimestamp())
.setUrgent(isUrgent());
if (getSourceUuid().isPresent()) {
builder.setSourceUuid(getSourceUuid().get());
@ -330,6 +338,7 @@ public class SignalServiceEnvelope {
proto.getServerReceivedTimestamp(),
proto.getServerDeliveredTimestamp(),
proto.getServerGuid(),
proto.getDestinationUuid());
proto.getDestinationUuid(),
proto.getUrgent());
}
}

Wyświetl plik

@ -198,4 +198,10 @@ public class SignalServiceCallMessage {
public Optional<Long> getTimestamp() {
return timestamp;
}
public boolean isUrgent() {
return offerMessage.isPresent() ||
hangupMessage.isPresent() ||
opaqueMessage.map(m -> m.getUrgency() == OpaqueMessage.Urgency.HANDLE_IMMEDIATELY).orElse(false);
}
}

Wyświetl plik

@ -47,4 +47,8 @@ public class RequestMessage {
public boolean isPniIdentityRequest() {
return request.getType() == Request.Type.PNI_IDENTITY;
}
public boolean isUrgent() {
return isContactsRequest() || isKeysRequest() || isPniIdentityRequest();
}
}

Wyświetl plik

@ -72,13 +72,13 @@ public class MessagingService {
.onErrorReturn(ServiceResponse::forUnknownError);
}
public Single<ServiceResponse<SendGroupMessageResponse>> sendToGroup(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online) {
public Single<ServiceResponse<SendGroupMessageResponse>> sendToGroup(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online, boolean urgent) {
List<String> headers = new LinkedList<String>() {{
add("content-type:application/vnd.signal-messenger.mrm");
add("Unidentified-Access-Key:" + Base64.encodeBytes(joinedUnidentifiedAccess));
}};
String path = String.format(Locale.US, "/v1/messages/multi_recipient?ts=%s&online=%s", timestamp, online);
String path = String.format(Locale.US, "/v1/messages/multi_recipient?ts=%s&online=%s&urgent=%s", timestamp, online, urgent);
WebSocketRequestMessage requestMessage = WebSocketRequestMessage.newBuilder()
.setId(new SecureRandom().nextLong())

Wyświetl plik

@ -26,15 +26,20 @@ public class OutgoingPushMessageList {
@JsonProperty
private boolean online;
@JsonProperty
private boolean urgent;
public OutgoingPushMessageList(String destination,
long timestamp,
List<OutgoingPushMessage> messages,
boolean online)
boolean online,
boolean urgent)
{
this.timestamp = timestamp;
this.destination = destination;
this.messages = messages;
this.online = online;
this.urgent = urgent;
}
public String getDestination() {
@ -53,6 +58,10 @@ public class OutgoingPushMessageList {
return online;
}
public boolean isUrgent() {
return urgent;
}
@JsonIgnore
public List<Integer> getDevices() {
return messages.stream().map(OutgoingPushMessage::getDestinationDeviceId).collect(Collectors.toList());

Wyświetl plik

@ -212,7 +212,7 @@ public class PushServiceSocket {
private static final String DIRECTORY_AUTH_PATH = "/v1/directory/auth";
private static final String MESSAGE_PATH = "/v1/messages/%s";
private static final String GROUP_MESSAGE_PATH = "/v1/messages/multi_recipient?ts=%s&online=%s";
private static final String GROUP_MESSAGE_PATH = "/v1/messages/multi_recipient?ts=%s&online=%s&urgent=%s";
private static final String SENDER_ACK_MESSAGE_PATH = "/v1/messages/%s/%d";
private static final String UUID_ACK_MESSAGE_PATH = "/v1/messages/uuid/%s";
private static final String ATTACHMENT_V2_PATH = "/v2/attachments/form/upload";
@ -463,12 +463,12 @@ public class PushServiceSocket {
return JsonUtil.fromJson(responseText, SenderCertificate.class).getCertificate();
}
public SendGroupMessageResponse sendGroupMessage(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online)
public SendGroupMessageResponse sendGroupMessage(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online, boolean urgent)
throws IOException
{
ServiceConnectionHolder connectionHolder = (ServiceConnectionHolder) getRandom(serviceClients, random);
String path = String.format(Locale.US, GROUP_MESSAGE_PATH, timestamp, online);
String path = String.format(Locale.US, GROUP_MESSAGE_PATH, timestamp, online, urgent);
Request.Builder requestBuilder = new Request.Builder();
requestBuilder.url(String.format("%s%s", connectionHolder.getUrl(), path));

Wyświetl plik

@ -37,6 +37,9 @@ public class SignalServiceEnvelopeEntity {
@JsonProperty
private String guid;
@JsonProperty
private Boolean urgent;
public SignalServiceEnvelopeEntity() {}
public int getType() {
@ -86,4 +89,8 @@ public class SignalServiceEnvelopeEntity {
public String getDestinationUuid() {
return destinationUuid;
}
public boolean isUrgent() {
return urgent == null || urgent;
}
}

Wyświetl plik

@ -33,6 +33,7 @@ message SignalServiceEnvelopeProto {
optional int64 serverDeliveredTimestamp = 9;
optional string serverGuid = 10;
optional string destinationUuid = 11;
optional bool urgent = 12 [default = true];
}
message MetadataProto {

Wyświetl plik

@ -33,7 +33,8 @@ message Envelope {
optional bytes content = 8; // Contains an encrypted Content
optional string serverGuid = 9;
optional uint64 serverTimestamp = 10;
// NEXT ID: 14
optional bool urgent = 14 [default = true];
// NEXT ID: 15
}
message Content {