Merge pull request #494 from hjubb/refactor-sending

Fix expiration timers updates for groups
This commit is contained in:
Niels Andriesse 2021-04-09 16:22:40 +10:00 committed by GitHub
commit 201dde7412
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 93 additions and 37 deletions

View File

@ -28,12 +28,14 @@ import com.annimon.stream.Collectors;
import com.annimon.stream.Stream;
import com.google.android.mms.pdu_alt.NotificationInd;
import com.google.android.mms.pdu_alt.PduHeaders;
import com.google.protobuf.ByteString;
import net.sqlcipher.database.SQLiteDatabase;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.session.libsession.utilities.GroupUtil;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.attachments.MmsNotificationAttachment;
import org.session.libsession.database.documents.IdentityKeyMismatch;
@ -686,7 +688,14 @@ public class MmsDatabase extends MessagingDatabase {
throws MmsException
{
if (threadId == -1) {
threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(retrieved.getRecipient());
if(retrieved.isGroup()) {
ByteString decodedGroupId = ((OutgoingGroupMediaMessage)retrieved).getGroupContext().getId();
String groupId = GroupUtil.doubleEncodeGroupID(decodedGroupId.toByteArray());
Recipient group = Recipient.from(context, Address.fromSerialized(groupId), false);
threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(group);
} else {
threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(retrieved.getRecipient());
}
}
long messageId = insertMessageOutbox(retrieved, threadId, false, null, serverTimestamp);
if (messageId == -1) {

View File

@ -417,7 +417,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
.setName(name)
.addAllMembers(members)
.addAllAdmins(admins)
val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, sentTimestamp, 0, null, listOf(), listOf())
val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, sentTimestamp, 0, false, null, listOf(), listOf())
val mmsDB = DatabaseFactory.getMmsDatabase(context)
val mmsSmsDB = DatabaseFactory.getMmsSmsDatabase(context)
if (mmsSmsDB.getMessageFor(sentTimestamp,userPublicKey) != null) return

View File

@ -2,9 +2,11 @@ package org.thoughtcrime.securesms.service;
import android.content.Context;
import com.google.protobuf.ByteString;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate;
import org.session.libsession.messaging.messages.signal.OutgoingGroupMediaMessage;
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage;
import org.session.libsession.messaging.threads.Address;
import org.session.libsession.messaging.threads.DistributionTypes;
@ -73,32 +75,88 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
@Override
public void setExpirationTimer(@NotNull ExpirationTimerUpdate message) {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
String userPublicKey = TextSecurePreferences.getLocalNumber(context);
String senderPublicKey = message.getSender();
int duration = message.getDuration();
String groupPK = message.getGroupPublicKey();
// Notify the user
if (userPublicKey.equals(senderPublicKey)) {
// sender is a linked device
insertOutgoingExpirationTimerMessage(message);
} else {
insertIncomingExpirationTimerMessage(message);
}
if (message.getId() != null) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(message.getId());
}
}
private void insertIncomingExpirationTimerMessage(ExpirationTimerUpdate message) {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
String senderPublicKey = message.getSender();
Long sentTimestamp = message.getSentTimestamp();
String groupId = message.getGroupPublicKey();
int duration = message.getDuration();
Optional<SignalServiceGroup> groupInfo = Optional.absent();
Address address;
Address address = Address.fromSerialized((message.getSyncTarget() != null && !message.getSyncTarget().isEmpty()) ? message.getSyncTarget() : senderPublicKey);
Recipient recipient = Recipient.from(context, address, false);
// if the sender is blocked, we don't display the update, except if it's in a closed group
if (recipient.isBlocked() && groupId == null) return;
try {
if (groupPK != null) {
String groupID = GroupUtil.doubleEncodeGroupID(groupPK);
if (groupId != null) {
String groupID = GroupUtil.doubleEncodeGroupID(groupId);
groupInfo = Optional.of(new SignalServiceGroup(GroupUtil.getDecodedGroupIDAsData(groupID), SignalServiceGroup.GroupType.SIGNAL));
address = Address.fromSerialized(groupID);
} else {
address = Address.fromSerialized((message.getSyncTarget() != null && !message.getSyncTarget().isEmpty()) ? message.getSyncTarget() : senderPublicKey);
Address groupAddress = Address.fromSerialized(groupID);
recipient = Recipient.from(context, groupAddress, false);
}
Recipient recipient = Recipient.from(context, address, false);
if (recipient.isBlocked()) return;
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(address, sentTimestamp, -1,
duration * 1000L, true,
false,
Optional.absent(),
groupInfo,
Optional.absent(),
Optional.absent(),
Optional.absent(),
Optional.absent());
//insert the timer update message
database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
// Notify the user
if (userPublicKey.equals(senderPublicKey)) {
// sender is a linked device
//set the timer to the conversation
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(recipient, duration);
} catch (IOException | MmsException ioe) {
Log.e("Loki", "Failed to insert expiration update message.");
}
}
private void insertOutgoingExpirationTimerMessage(ExpirationTimerUpdate message) {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
String senderPublicKey = message.getSender();
Long sentTimestamp = message.getSentTimestamp();
String groupId = message.getGroupPublicKey();
int duration = message.getDuration();
Address address = Address.fromSerialized((message.getSyncTarget() != null && !message.getSyncTarget().isEmpty()) ? message.getSyncTarget() : senderPublicKey);
Recipient recipient = Recipient.from(context, address, false);
try {
if (groupId != null) {
// conversation is a closed group
GroupContext groupContext = SignalServiceProtos.GroupContext.newBuilder()
.setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupId))).build();
OutgoingGroupMediaMessage infoMessage = new OutgoingGroupMediaMessage(recipient, groupContext, null, sentTimestamp, duration * 1000L, true, null, Collections.emptyList(), Collections.emptyList());
database.insertSecureDecryptedMessageOutbox(infoMessage, -1, sentTimestamp);
// we need the group ID as recipient for setExpireMessages below
recipient = Recipient.from(context, Address.fromSerialized(GroupUtil.doubleEncodeGroupID(groupId)), false);
} else {
// conversation is a 1-1
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(recipient,
null,
Collections.emptyList(),
@ -113,29 +171,12 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
Collections.emptyList(),
Collections.emptyList());
database.insertSecureDecryptedMessageOutbox(mediaMessage, -1, sentTimestamp);
} else {
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(address, sentTimestamp, -1,
duration * 1000L, true,
false,
Optional.absent(),
groupInfo,
Optional.absent(),
Optional.absent(),
Optional.absent(),
Optional.absent());
//insert the timer update message
database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
}
//set the timer to the conversation
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(recipient, duration);
if (message.getId() != null) {
DatabaseFactory.getSmsDatabase(context).deleteMessage(message.getId());
}
} catch (MmsException e) {
Log.e("Loki", "Failed to insert expiration update message.");
} catch (IOException ioe) {
} catch (MmsException | IOException ioe) {
Log.e("Loki", "Failed to insert expiration update message.");
}
}

View File

@ -58,6 +58,7 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
@Nullable final Attachment avatar,
long sentTime,
long expireIn,
boolean expirationUpdate,
@Nullable QuoteModel quote,
@NonNull List<Contact> contacts,
@NonNull List<LinkPreview> previews)
@ -65,7 +66,7 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
super(recipient, Base64.encodeBytes(group.toByteArray()),
new LinkedList<Attachment>() {{if (avatar != null) add(avatar);}},
sentTime,
DistributionTypes.CONVERSATION, expireIn, false, quote, contacts, previews);
DistributionTypes.CONVERSATION, expireIn, expirationUpdate, quote, contacts, previews);
this.group = group;
}

View File

@ -78,6 +78,11 @@ object GroupUtil {
return getEncodedClosedGroupID(getEncodedClosedGroupID(Hex.fromStringCondensed(groupPublicKey)).toByteArray())
}
@JvmStatic
fun doubleEncodeGroupID(groupID: ByteArray): String {
return getEncodedClosedGroupID(getEncodedClosedGroupID(groupID).toByteArray())
}
@JvmStatic
@Throws(IOException::class)
fun doubleDecodeGroupID(groupID: String): ByteArray {