kopia lustrzana https://github.com/ryukoposting/Signal-Android
Fix story sync message behaviour between iOS and Android.
rodzic
e5d196c642
commit
7945b3c971
|
@ -230,16 +230,6 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
|
||||||
return getLocalManifest(sentTimestamp)
|
return getLocalManifest(sentTimestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the manifest after a change to the available distribution lists occurs.
|
|
||||||
*/
|
|
||||||
fun getSentStorySyncManifestForUpdate(sentTimestamp: Long): SentStorySyncManifest {
|
|
||||||
val localManifest: SentStorySyncManifest = getLocalManifest(sentTimestamp)
|
|
||||||
val entries: List<SentStorySyncManifest.Entry> = localManifest.entries
|
|
||||||
|
|
||||||
return SentStorySyncManifest(entries)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the given manifest to the local database. This method will:
|
* Applies the given manifest to the local database. This method will:
|
||||||
*
|
*
|
||||||
|
@ -331,34 +321,34 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLocalManifest(sentTimestamp: Long): SentStorySyncManifest {
|
fun getLocalManifest(sentTimestamp: Long): SentStorySyncManifest {
|
||||||
val entries = readableDatabase.rawQuery(
|
val entries = readableDatabase.rawQuery(
|
||||||
// language=sql
|
// language=sql
|
||||||
"""
|
"""
|
||||||
SELECT
|
SELECT
|
||||||
$RECIPIENT_ID,
|
$RECIPIENT_ID,
|
||||||
$ALLOWS_REPLIES,
|
$ALLOWS_REPLIES,
|
||||||
$DISTRIBUTION_ID
|
$DISTRIBUTION_ID,
|
||||||
|
${MmsTable.REMOTE_DELETED}
|
||||||
FROM $TABLE_NAME
|
FROM $TABLE_NAME
|
||||||
WHERE $TABLE_NAME.$SENT_TIMESTAMP = ? AND (
|
INNER JOIN ${MmsTable.TABLE_NAME} ON ${MmsTable.TABLE_NAME}.${MmsTable.ID} = $TABLE_NAME.$MESSAGE_ID
|
||||||
SELECT ${MmsTable.REMOTE_DELETED}
|
WHERE $TABLE_NAME.$SENT_TIMESTAMP = ?
|
||||||
FROM ${MmsTable.TABLE_NAME}
|
|
||||||
WHERE ${MmsTable.ID} = $TABLE_NAME.$MESSAGE_ID
|
|
||||||
) = 0
|
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
arrayOf(sentTimestamp)
|
arrayOf(sentTimestamp)
|
||||||
).use { cursor ->
|
).use { cursor ->
|
||||||
val results: MutableMap<RecipientId, SentStorySyncManifest.Entry> = mutableMapOf()
|
val results: MutableMap<RecipientId, SentStorySyncManifest.Entry> = mutableMapOf()
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
|
val isRemoteDeleted = CursorUtil.requireBoolean(cursor, MmsTable.REMOTE_DELETED)
|
||||||
val recipientId = RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID))
|
val recipientId = RecipientId.from(CursorUtil.requireLong(cursor, RECIPIENT_ID))
|
||||||
val distributionId = DistributionId.from(CursorUtil.requireString(cursor, DISTRIBUTION_ID))
|
val distributionId = DistributionId.from(CursorUtil.requireString(cursor, DISTRIBUTION_ID))
|
||||||
|
val distributionIdList: List<DistributionId> = if (isRemoteDeleted) emptyList() else listOf(distributionId)
|
||||||
val allowsReplies = CursorUtil.requireBoolean(cursor, ALLOWS_REPLIES)
|
val allowsReplies = CursorUtil.requireBoolean(cursor, ALLOWS_REPLIES)
|
||||||
val entry = results[recipientId]?.let {
|
val entry = results[recipientId]?.let {
|
||||||
it.copy(
|
it.copy(
|
||||||
allowedToReply = it.allowedToReply or allowsReplies,
|
allowedToReply = it.allowedToReply or allowsReplies,
|
||||||
distributionLists = it.distributionLists + distributionId
|
distributionLists = it.distributionLists + distributionIdList
|
||||||
)
|
)
|
||||||
} ?: SentStorySyncManifest.Entry(recipientId, canReply(recipientId, sentTimestamp), listOf(distributionId))
|
} ?: SentStorySyncManifest.Entry(recipientId, canReply(recipientId, sentTimestamp), distributionIdList)
|
||||||
|
|
||||||
results[recipientId] = entry
|
results[recipientId] = entry
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,7 @@ import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transmits a sent sync transcript to linked devices containing the story sync manifest for the given sent timestamp.
|
* Transmits a sent sync transcript to linked devices containing the story sync manifest for the given sent timestamp.
|
||||||
* The transmitted message is sent as a recipient update, and will only contain affected recipients that still have a
|
* The transmitted message will contain all current recipients of a given story.
|
||||||
* live story for the given timestamp.
|
|
||||||
*/
|
*/
|
||||||
class MultiDeviceStorySendSyncJob private constructor(parameters: Parameters, private val sentTimestamp: Long, private val deletedMessageId: Long) : BaseJob(parameters) {
|
class MultiDeviceStorySendSyncJob private constructor(parameters: Parameters, private val sentTimestamp: Long, private val deletedMessageId: Long) : BaseJob(parameters) {
|
||||||
|
|
||||||
|
@ -55,20 +54,18 @@ class MultiDeviceStorySendSyncJob private constructor(parameters: Parameters, pr
|
||||||
override fun getFactoryKey(): String = KEY
|
override fun getFactoryKey(): String = KEY
|
||||||
|
|
||||||
override fun onRun() {
|
override fun onRun() {
|
||||||
val updateManifest = SignalDatabase.storySends.getSentStorySyncManifestForUpdate(sentTimestamp)
|
val updateManifest = SignalDatabase.storySends.getLocalManifest(sentTimestamp)
|
||||||
|
val recipientsSet: Set<SignalServiceStoryMessageRecipient> = updateManifest.toRecipientsSet()
|
||||||
if (updateManifest.entries.isEmpty()) {
|
|
||||||
Log.i(TAG, "No entries in updated manifest. Dropping.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val recipientsSet = updateManifest.toRecipientsSet()
|
|
||||||
val transcriptMessage: SignalServiceSyncMessage = SignalServiceSyncMessage.forSentTranscript(buildSentTranscript(recipientsSet))
|
val transcriptMessage: SignalServiceSyncMessage = SignalServiceSyncMessage.forSentTranscript(buildSentTranscript(recipientsSet))
|
||||||
val sendMessageResult = ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(transcriptMessage, Optional.empty())
|
val sendMessageResult = ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(transcriptMessage, Optional.empty())
|
||||||
|
|
||||||
|
Log.i(TAG, "Sent transcript message with ${recipientsSet.size} recipients")
|
||||||
|
|
||||||
if (!sendMessageResult.isSuccess) {
|
if (!sendMessageResult.isSuccess) {
|
||||||
throw RetryableException()
|
throw RetryableException()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SignalDatabase.mms.deleteRemotelyDeletedStory(deletedMessageId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onShouldRetry(e: Exception): Boolean {
|
override fun onShouldRetry(e: Exception): Boolean {
|
||||||
|
|
|
@ -138,8 +138,8 @@ public final class PushDistributionListSendJob extends PushSendJob {
|
||||||
public void onPushSend()
|
public void onPushSend()
|
||||||
throws IOException, MmsException, NoSuchMessageException, RetryLaterException
|
throws IOException, MmsException, NoSuchMessageException, RetryLaterException
|
||||||
{
|
{
|
||||||
MessageTable database = SignalDatabase.mms();
|
MessageTable database = SignalDatabase.mms();
|
||||||
OutgoingMediaMessage message = database.getOutgoingMessage(messageId);
|
OutgoingMediaMessage message = database.getOutgoingMessage(messageId);
|
||||||
Set<NetworkFailure> existingNetworkFailures = message.getNetworkFailures();
|
Set<NetworkFailure> existingNetworkFailures = message.getNetworkFailures();
|
||||||
Set<IdentityKeyMismatch> existingIdentityMismatches = message.getIdentityKeyMismatches();
|
Set<IdentityKeyMismatch> existingIdentityMismatches = message.getIdentityKeyMismatches();
|
||||||
|
|
||||||
|
@ -213,6 +213,8 @@ public final class PushDistributionListSendJob extends PushSendJob {
|
||||||
SentStorySyncManifest manifest = SignalDatabase.storySends().getFullSentStorySyncManifest(messageId, message.getSentTimeMillis());
|
SentStorySyncManifest manifest = SignalDatabase.storySends().getFullSentStorySyncManifest(messageId, message.getSentTimeMillis());
|
||||||
Set<SignalServiceStoryMessageRecipient> manifestCollection = manifest != null ? manifest.toRecipientsSet() : Collections.emptySet();
|
Set<SignalServiceStoryMessageRecipient> manifestCollection = manifest != null ? manifest.toRecipientsSet() : Collections.emptySet();
|
||||||
|
|
||||||
|
Log.d(TAG, "[" + messageId + "] Sending a story message with a manifest of size " + manifestCollection.size());
|
||||||
|
|
||||||
return GroupSendUtil.sendStoryMessage(context, message.getRecipient().requireDistributionListId(), destinations, isRecipientUpdate, new MessageId(messageId, true), message.getSentTimeMillis(), storyMessage, manifestCollection);
|
return GroupSendUtil.sendStoryMessage(context, message.getRecipient().requireDistributionListId(), destinations, isRecipientUpdate, new MessageId(messageId, true), message.getSentTimeMillis(), storyMessage, manifestCollection);
|
||||||
} catch (ServerRejectedException e) {
|
} catch (ServerRejectedException e) {
|
||||||
throw new UndeliverableMessageException(e);
|
throw new UndeliverableMessageException(e);
|
||||||
|
|
|
@ -189,10 +189,6 @@ public class RemoteDeleteSendJob extends BaseJob {
|
||||||
|
|
||||||
if (recipients.isEmpty()) {
|
if (recipients.isEmpty()) {
|
||||||
db.markAsSent(messageId, true);
|
db.markAsSent(messageId, true);
|
||||||
|
|
||||||
if (MessageRecordUtil.isStory(message)) {
|
|
||||||
db.deleteRemotelyDeletedStory(messageId);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Still need to send to " + recipients.size() + " recipients. Retrying.");
|
Log.w(TAG, "Still need to send to " + recipients.size() + " recipients. Retrying.");
|
||||||
throw new RetryLaterException();
|
throw new RetryLaterException();
|
||||||
|
|
|
@ -278,6 +278,11 @@ public class SignalServiceMessageSender {
|
||||||
Set<SignalServiceStoryMessageRecipient> manifest)
|
Set<SignalServiceStoryMessageRecipient> manifest)
|
||||||
throws IOException, UntrustedIdentityException
|
throws IOException, UntrustedIdentityException
|
||||||
{
|
{
|
||||||
|
if (manifest.isEmpty()) {
|
||||||
|
Log.w(TAG, "Refusing to send sync message for empty manifest.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SignalServiceSyncMessage syncMessage = createSelfSendSyncMessageForStory(message, timestamp, isRecipientUpdate, manifest);
|
SignalServiceSyncMessage syncMessage = createSelfSendSyncMessageForStory(message, timestamp, isRecipientUpdate, manifest);
|
||||||
sendSyncMessage(syncMessage, Optional.empty());
|
sendSyncMessage(syncMessage, Optional.empty());
|
||||||
}
|
}
|
||||||
|
@ -300,8 +305,7 @@ public class SignalServiceMessageSender {
|
||||||
List<SendMessageResult> sendMessageResults = sendGroupMessage(distributionId, recipients, unidentifiedAccess, timestamp, content, ContentHint.IMPLICIT, groupId, false, SenderKeyGroupEvents.EMPTY, false, true);
|
List<SendMessageResult> sendMessageResults = sendGroupMessage(distributionId, recipients, unidentifiedAccess, timestamp, content, ContentHint.IMPLICIT, groupId, false, SenderKeyGroupEvents.EMPTY, false, true);
|
||||||
|
|
||||||
if (aciStore.isMultiDevice()) {
|
if (aciStore.isMultiDevice()) {
|
||||||
SignalServiceSyncMessage syncMessage = createSelfSendSyncMessageForStory(message, timestamp, isRecipientUpdate, manifest);
|
sendStorySyncMessage(message, timestamp, isRecipientUpdate, manifest);
|
||||||
sendSyncMessage(syncMessage, Optional.empty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sendMessageResults;
|
return sendMessageResults;
|
||||||
|
|
|
@ -763,8 +763,10 @@ public final class SignalServiceContent {
|
||||||
|
|
||||||
if (!address.isPresent() &&
|
if (!address.isPresent() &&
|
||||||
!dataMessage.flatMap(SignalServiceDataMessage::getGroupContext).isPresent() &&
|
!dataMessage.flatMap(SignalServiceDataMessage::getGroupContext).isPresent() &&
|
||||||
!storyMessage.flatMap(SignalServiceStoryMessage::getGroupContext).isPresent()) {
|
!storyMessage.flatMap(SignalServiceStoryMessage::getGroupContext).isPresent() &&
|
||||||
throw new InvalidMessageStructureException("SyncMessage missing both destination and group ID!");
|
recipientManifest.isEmpty())
|
||||||
|
{
|
||||||
|
throw new InvalidMessageStructureException("SyncMessage missing destination, group ID, and recipient manifest!");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SignalServiceProtos.SyncMessage.Sent.UnidentifiedDeliveryStatus status : sentContent.getUnidentifiedStatusList()) {
|
for (SignalServiceProtos.SyncMessage.Sent.UnidentifiedDeliveryStatus status : sentContent.getUnidentifiedStatusList()) {
|
||||||
|
|
Ładowanie…
Reference in New Issue