diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV1.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV1.java index 4d4c989f8..d835b4a48 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV1.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV1.java @@ -157,7 +157,6 @@ final class GroupManagerV1 { Recipient recipient = Recipient.resolved(member); if (recipient.hasE164()) { e164Members.add(recipient.requireE164()); - uuidMembers.add(GroupV1MessageProcessor.createMember(recipient.requireE164())); } } @@ -216,6 +215,6 @@ final class GroupManagerV1 { return Optional.empty(); } - return Optional.of(GroupUtil.createGroupV1LeaveMessage(groupId, groupRecipient)); + return Optional.empty(); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupV1MessageProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupV1MessageProcessor.java deleted file mode 100644 index ec7a0c52c..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupV1MessageProcessor.java +++ /dev/null @@ -1,309 +0,0 @@ -package org.thoughtcrime.securesms.groups; - - -import android.content.Context; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.annimon.stream.Stream; -import com.google.protobuf.ByteString; - -import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.database.GroupDatabase; -import org.thoughtcrime.securesms.database.MessageDatabase; -import org.thoughtcrime.securesms.database.MessageDatabase.InsertResult; -import org.thoughtcrime.securesms.database.SignalDatabase; -import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; -import org.thoughtcrime.securesms.jobs.AvatarGroupsV1DownloadJob; -import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob; -import org.thoughtcrime.securesms.mms.MmsException; -import org.thoughtcrime.securesms.mms.OutgoingGroupUpdateMessage; -import org.thoughtcrime.securesms.notifications.v2.ConversationId; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.sms.IncomingGroupUpdateMessage; -import org.thoughtcrime.securesms.sms.IncomingTextMessage; -import org.thoughtcrime.securesms.util.Base64; -import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; -import org.whispersystems.signalservice.api.messages.SignalServiceContent; -import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; -import org.whispersystems.signalservice.api.messages.SignalServiceGroup; -import org.whispersystems.signalservice.api.messages.SignalServiceGroup.Type; -import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext; -import org.whispersystems.signalservice.api.push.SignalServiceAddress; - -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; -import java.util.Set; - -import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord; -import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.AttachmentPointer; -import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext; - -public final class GroupV1MessageProcessor { - - private static final String TAG = Log.tag(GroupV1MessageProcessor.class); - - public static @Nullable Long process(@NonNull Context context, - @NonNull SignalServiceContent content, - @NonNull SignalServiceDataMessage message, - boolean outgoing) - throws BadGroupIdException - { - SignalServiceGroupContext signalServiceGroupContext = message.getGroupContext().get(); - Optional groupV1 = signalServiceGroupContext.getGroupV1(); - - if (signalServiceGroupContext.getGroupV2().isPresent()) { - throw new AssertionError("Cannot process GV2"); - } - - if (!groupV1.isPresent() || groupV1.get().getGroupId() == null) { - Log.w(TAG, "Received group message with no id! Ignoring..."); - return null; - } - - GroupDatabase database = SignalDatabase.groups(); - SignalServiceGroup group = groupV1.get(); - GroupId id = GroupId.v1(group.getGroupId()); - Optional record = database.getGroup(id); - - if (record.isPresent() && group.getType() == Type.UPDATE) { - return handleGroupUpdate(context, content, group, record.get(), outgoing); - } else if (!record.isPresent() && group.getType() == Type.UPDATE) { - return handleGroupCreate(context, content, group, outgoing); - } else if (record.isPresent() && group.getType() == Type.QUIT) { - return handleGroupLeave(context, content, group, record.get(), outgoing); - } else if (record.isPresent() && group.getType() == Type.REQUEST_INFO) { - return handleGroupInfoRequest(context, content, record.get()); - } else { - Log.w(TAG, "Received unknown type, ignoring..."); - return null; - } - } - - private static @Nullable Long handleGroupCreate(@NonNull Context context, - @NonNull SignalServiceContent content, - @NonNull SignalServiceGroup group, - boolean outgoing) - { - GroupDatabase database = SignalDatabase.groups(); - GroupId.V1 id = GroupId.v1orThrow(group.getGroupId()); - GroupContext.Builder builder = createGroupContext(group); - builder.setType(GroupContext.Type.UPDATE); - - SignalServiceAttachment avatar = group.getAvatar().orElse(null); - List members = new LinkedList<>(); - - if (group.getMembers().isPresent()) { - for (SignalServiceAddress member : group.getMembers().get()) { - members.add(Recipient.externalGV1Member(member).getId()); - } - } - - database.create(id, group.getName().orElse(null), members, - avatar != null && avatar.isPointer() ? avatar.asPointer() : null, null); - - Recipient sender = Recipient.externalPush(content.getSender()); - - if (sender.isSystemContact() || sender.isProfileSharing()) { - Log.i(TAG, "Auto-enabling profile sharing because 'adder' is trusted. contact: " + sender.isSystemContact() + ", profileSharing: " + sender.isProfileSharing()); - SignalDatabase.recipients().setProfileSharing(Recipient.externalGroupExact(id).getId(), true); - } - - return storeMessage(context, content, group, builder.build(), outgoing); - } - - private static @Nullable Long handleGroupUpdate(@NonNull Context context, - @NonNull SignalServiceContent content, - @NonNull SignalServiceGroup group, - @NonNull GroupRecord groupRecord, - boolean outgoing) - { - - GroupDatabase database = SignalDatabase.groups(); - GroupId.V1 id = GroupId.v1orThrow(group.getGroupId()); - - Set recordMembers = new HashSet<>(groupRecord.getMembers()); - Set messageMembers = new HashSet<>(); - - if (group.getMembers().isPresent()) { - for (SignalServiceAddress messageMember : group.getMembers().get()) { - messageMembers.add(Recipient.externalGV1Member(messageMember).getId()); - } - } - - Set addedMembers = new HashSet<>(messageMembers); - addedMembers.removeAll(recordMembers); - - Set missingMembers = new HashSet<>(recordMembers); - missingMembers.removeAll(messageMembers); - - GroupContext.Builder builder = createGroupContext(group); - builder.setType(GroupContext.Type.UPDATE); - - if (addedMembers.size() > 0) { - Set unionMembers = new HashSet<>(recordMembers); - unionMembers.addAll(messageMembers); - database.updateMembers(id, new LinkedList<>(unionMembers)); - - builder.clearMembers(); - builder.clearMembersE164(); - - for (RecipientId addedMember : addedMembers) { - Recipient recipient = Recipient.resolved(addedMember); - - if (recipient.getE164().isPresent()) { - builder.addMembersE164(recipient.requireE164()); - builder.addMembers(createMember(recipient.requireE164())); - } - } - } else { - builder.clearMembers(); - builder.clearMembersE164(); - } - - if (missingMembers.size() > 0) { - // TODO We should tell added and missing about each-other. - } - - if (group.getName().isPresent() || group.getAvatar().isPresent()) { - SignalServiceAttachment avatar = group.getAvatar().orElse(null); - database.update(id, group.getName().orElse(null), avatar != null ? avatar.asPointer() : null); - } - - if (group.getName().isPresent() && group.getName().get().equals(groupRecord.getTitle())) { - builder.clearName(); - } - - if (!groupRecord.isActive()) database.setActive(id, true); - - return storeMessage(context, content, group, builder.build(), outgoing); - } - - private static Long handleGroupInfoRequest(@NonNull Context context, - @NonNull SignalServiceContent content, - @NonNull GroupRecord record) - { - Recipient sender = Recipient.externalPush(content.getSender()); - - if (record.getMembers().contains(sender.getId())) { - ApplicationDependencies.getJobManager().add(new PushGroupUpdateJob(sender.getId(), record.getId())); - } - - return null; - } - - private static Long handleGroupLeave(@NonNull Context context, - @NonNull SignalServiceContent content, - @NonNull SignalServiceGroup group, - @NonNull GroupRecord record, - boolean outgoing) - { - GroupDatabase database = SignalDatabase.groups(); - GroupId id = GroupId.v1orThrow(group.getGroupId()); - List members = record.getMembers(); - - GroupContext.Builder builder = createGroupContext(group); - builder.setType(GroupContext.Type.QUIT); - - RecipientId senderId = RecipientId.from(content.getSender()); - - if (members.contains(senderId)) { - database.remove(id, senderId); - if (outgoing) database.setActive(id, false); - - return storeMessage(context, content, group, builder.build(), outgoing); - } - - return null; - } - - - private static @Nullable Long storeMessage(@NonNull Context context, - @NonNull SignalServiceContent content, - @NonNull SignalServiceGroup group, - @NonNull GroupContext storage, - boolean outgoing) - { - if (group.getAvatar().isPresent()) { - ApplicationDependencies.getJobManager() - .add(new AvatarGroupsV1DownloadJob(GroupId.v1orThrow(group.getGroupId()))); - } - - try { - if (outgoing) { - MessageDatabase mmsDatabase = SignalDatabase.mms(); - RecipientId recipientId = SignalDatabase.recipients().getOrInsertFromGroupId(GroupId.v1orThrow(group.getGroupId())); - Recipient recipient = Recipient.resolved(recipientId); - OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, storage, null, content.getTimestamp(), 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); - long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(recipient); - long messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null); - - mmsDatabase.markAsSent(messageId, true); - - return threadId; - } else { - MessageDatabase smsDatabase = SignalDatabase.sms(); - String body = Base64.encodeBytes(storage.toByteArray()); - IncomingTextMessage incoming = new IncomingTextMessage(Recipient.externalPush(content.getSender()).getId(), content.getSenderDevice(), content.getTimestamp(), content.getServerReceivedTimestamp(), System.currentTimeMillis(), body, Optional.of(GroupId.v1orThrow(group.getGroupId())), 0, content.isNeedsReceipt(), content.getServerUuid()); - IncomingGroupUpdateMessage groupMessage = new IncomingGroupUpdateMessage(incoming, storage, body); - - Optional insertResult = smsDatabase.insertMessageInbox(groupMessage); - - if (insertResult.isPresent()) { - ApplicationDependencies.getMessageNotifier().updateNotification(context, ConversationId.forConversation(insertResult.get().getThreadId())); - return insertResult.get().getThreadId(); - } else { - return null; - } - } - } catch (MmsException e) { - Log.w(TAG, e); - } - - return null; - } - - private static GroupContext.Builder createGroupContext(SignalServiceGroup group) { - GroupContext.Builder builder = GroupContext.newBuilder(); - builder.setId(ByteString.copyFrom(group.getGroupId())); - - if (group.getAvatar().isPresent() && - group.getAvatar().get().isPointer() && - group.getAvatar().get().asPointer().getRemoteId().getV2().isPresent()) - { - builder.setAvatar(AttachmentPointer.newBuilder() - .setCdnId(group.getAvatar().get().asPointer().getRemoteId().getV2().get()) - .setKey(ByteString.copyFrom(group.getAvatar().get().asPointer().getKey())) - .setContentType(group.getAvatar().get().getContentType())); - } - - if (group.getName().isPresent()) { - builder.setName(group.getName().get()); - } - - if (group.getMembers().isPresent()) { - builder.addAllMembersE164(Stream.of(group.getMembers().get()) - .filter(a -> a.getNumber().isPresent()) - .map(a -> a.getNumber().get()) - .toList()); - builder.addAllMembers(Stream.of(group.getMembers().get()) - .filter(address -> address.getNumber().isPresent()) - .map(address -> address.getNumber().get()) - .map(GroupV1MessageProcessor::createMember) - .toList()); - } - - return builder; - } - - public static GroupContext.Member createMember(@NonNull String e164) { - GroupContext.Member.Builder member = GroupContext.Member.newBuilder(); - member.setE164(e164); - return member.build(); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java index a48e1340b..f14a3d692 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java @@ -124,7 +124,7 @@ public final class GroupsV1MigrationUtil { break; case NOT_A_MEMBER: Log.w(TAG, "The migrated group already exists, but we are not a member. Doing a local leave."); - handleLeftBehind(context, gv1Id, groupRecipient, threadId); + handleLeftBehind(gv1Id); return; case FULL_OR_PENDING_MEMBER: Log.w(TAG, "The migrated group already exists, and we're in it. Continuing on."); @@ -177,7 +177,7 @@ public final class GroupsV1MigrationUtil { throw new IOException("[Local] The group should exist already!"); } catch (GroupNotAMemberException e) { Log.w(TAG, "[Local] We are not in the group. Doing a local leave."); - handleLeftBehind(context, gv1Id, groupRecipient, threadId); + handleLeftBehind(gv1Id); return null; } @@ -195,15 +195,7 @@ public final class GroupsV1MigrationUtil { } } - private static void handleLeftBehind(@NonNull Context context, @NonNull GroupId.V1 gv1Id, @NonNull Recipient groupRecipient, long threadId) { - OutgoingMediaMessage leaveMessage = GroupUtil.createGroupV1LeaveMessage(gv1Id, groupRecipient); - try { - long id = SignalDatabase.mms().insertMessageOutbox(leaveMessage, threadId, false, null); - SignalDatabase.mms().markAsSent(id, true); - } catch (MmsException e) { - Log.w(TAG, "Failed to insert group leave message!", e); - } - + private static void handleLeftBehind(@NonNull GroupId.V1 gv1Id) { SignalDatabase.groups().setActive(gv1Id, false); SignalDatabase.groups().remove(gv1Id, Recipient.self().getId()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/migrations/PushProcessMessageQueueJobMigration.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/migrations/PushProcessMessageQueueJobMigration.java index d12711d71..2c5cc3c27 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/migrations/PushProcessMessageQueueJobMigration.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/migrations/PushProcessMessageQueueJobMigration.java @@ -56,14 +56,11 @@ public class PushProcessMessageQueueJobMigration extends JobMigration { if (content != null && content.getDataMessage().isPresent() && content.getDataMessage().get().getGroupContext().isPresent()) { Log.i(TAG, "Migrating a group message."); - try { - GroupId groupId = GroupUtil.idFromGroupContext(content.getDataMessage().get().getGroupContext().get()); - Recipient recipient = Recipient.externalGroupExact(groupId); - suffix = recipient.getId().toQueueKey(); - } catch (BadGroupIdException e) { - Log.w(TAG, "Bad groupId! Using default queue."); - } + GroupId groupId = GroupId.v2(content.getDataMessage().get().getGroupContext().get().getMasterKey()); + Recipient recipient = Recipient.externalGroupExact(groupId); + + suffix = recipient.getId().toQueueKey(); } else if (content != null) { Log.i(TAG, "Migrating an individual message."); suffix = RecipientId.from(content.getSender()).toQueueKey(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java index 3c86805fe..c5898f215 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java @@ -142,7 +142,6 @@ public final class JobManagerFactories { put(PushDistributionListSendJob.KEY, new PushDistributionListSendJob.Factory()); put(PushGroupSendJob.KEY, new PushGroupSendJob.Factory()); put(PushGroupSilentUpdateSendJob.KEY, new PushGroupSilentUpdateSendJob.Factory()); - put(PushGroupUpdateJob.KEY, new PushGroupUpdateJob.Factory()); put(PushMediaSendJob.KEY, new PushMediaSendJob.Factory()); put(PushNotificationReceiveJob.KEY, new PushNotificationReceiveJob.Factory()); put(PushProcessEarlyMessagesJob.KEY, new PushProcessEarlyMessagesJob.Factory()); @@ -156,7 +155,6 @@ public final class JobManagerFactories { put(RemoteConfigRefreshJob.KEY, new RemoteConfigRefreshJob.Factory()); put(RemoteDeleteSendJob.KEY, new RemoteDeleteSendJob.Factory()); put(ReportSpamJob.KEY, new ReportSpamJob.Factory()); - put(RequestGroupInfoJob.KEY, new RequestGroupInfoJob.Factory()); put(ResendMessageJob.KEY, new ResendMessageJob.Factory()); put(ResumableUploadSpecJob.KEY, new ResumableUploadSpecJob.Factory()); put(RequestGroupV2InfoWorkerJob.KEY, new RequestGroupV2InfoWorkerJob.Factory()); @@ -240,6 +238,8 @@ public final class JobManagerFactories { put("StorageSyncJob", new StorageSyncJob.Factory()); put("WakeGroupV2Job", new FailingJob.Factory()); put("LeaveGroupJob", new FailingJob.Factory()); + put("PushGroupUpdateJob", new FailingJob.Factory()); + put("RequestGroupInfoJob", new FailingJob.Factory()); }}; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java deleted file mode 100644 index 3c9862d02..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java +++ /dev/null @@ -1,163 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - - -import androidx.annotation.NonNull; - -import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; -import org.thoughtcrime.securesms.database.GroupDatabase; -import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord; -import org.thoughtcrime.securesms.database.SignalDatabase; -import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; -import org.thoughtcrime.securesms.groups.GroupId; -import org.thoughtcrime.securesms.jobmanager.Data; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.thoughtcrime.securesms.net.NotPushRegisteredException; -import org.thoughtcrime.securesms.profiles.AvatarHelper; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.recipients.RecipientUtil; -import org.whispersystems.signalservice.api.SignalServiceMessageSender; -import org.whispersystems.signalservice.api.SignalServiceMessageSender.IndividualSendEvents; -import org.whispersystems.signalservice.api.crypto.ContentHint; -import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; -import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; -import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream; -import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; -import org.whispersystems.signalservice.api.messages.SignalServiceGroup; -import org.whispersystems.signalservice.api.messages.SignalServiceGroup.Type; -import org.whispersystems.signalservice.api.push.SignalServiceAddress; -import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; - -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.TimeUnit; - -public class PushGroupUpdateJob extends BaseJob { - - public static final String KEY = "PushGroupUpdateJob"; - - private static final String TAG = Log.tag(PushGroupUpdateJob.class); - - private static final String KEY_SOURCE = "source"; - private static final String KEY_GROUP_ID = "group_id"; - - private final RecipientId source; - private final GroupId groupId; - - public PushGroupUpdateJob(@NonNull RecipientId source, @NonNull GroupId groupId) { - this(new Job.Parameters.Builder() - .addConstraint(NetworkConstraint.KEY) - .setLifespan(TimeUnit.DAYS.toMillis(1)) - .setMaxAttempts(Parameters.UNLIMITED) - .build(), - source, - groupId); - } - - private PushGroupUpdateJob(@NonNull Job.Parameters parameters, RecipientId source, @NonNull GroupId groupId) { - super(parameters); - - this.source = source; - this.groupId = groupId; - } - - @Override - public @NonNull Data serialize() { - return new Data.Builder().putString(KEY_SOURCE, source.serialize()) - .putString(KEY_GROUP_ID, groupId.toString()) - .build(); - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public void onRun() throws IOException, UntrustedIdentityException { - if (!Recipient.self().isRegistered()) { - throw new NotPushRegisteredException(); - } - - Recipient sourceRecipient = Recipient.resolved(source); - - if (sourceRecipient.isUnregistered()) { - Log.w(TAG, sourceRecipient.getId() + " not registered!"); - return; - } - - GroupDatabase groupDatabase = SignalDatabase.groups(); - Optional record = groupDatabase.getGroup(groupId); - SignalServiceAttachment avatar = null; - - if (record == null || !record.isPresent()) { - Log.w(TAG, "No information for group record info request: " + groupId.toString()); - return; - } - - if (AvatarHelper.hasAvatar(context, record.get().getRecipientId())) { - avatar = SignalServiceAttachmentStream.newStreamBuilder() - .withContentType("image/jpeg") - .withStream(AvatarHelper.getAvatar(context, record.get().getRecipientId())) - .withLength(AvatarHelper.getAvatarLength(context, record.get().getRecipientId())) - .build(); - } - - List members = new LinkedList<>(); - - for (RecipientId member : record.get().getMembers()) { - Recipient recipient = Recipient.resolved(member); - - if (recipient.isMaybeRegistered()) { - members.add(RecipientUtil.toSignalServiceAddress(context, recipient)); - } - } - - SignalServiceGroup groupContext = SignalServiceGroup.newBuilder(Type.UPDATE) - .withAvatar(avatar) - .withId(groupId.getDecodedId()) - .withMembers(members) - .withName(record.get().getTitle()) - .build(); - - RecipientId groupRecipientId = SignalDatabase.recipients().getOrInsertFromGroupId(groupId); - Recipient groupRecipient = Recipient.resolved(groupRecipientId); - - SignalServiceDataMessage message = SignalServiceDataMessage.newBuilder() - .asGroupMessage(groupContext) - .withTimestamp(System.currentTimeMillis()) - .withExpiration(groupRecipient.getExpiresInSeconds()) - .build(); - - SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); - - messageSender.sendDataMessage(RecipientUtil.toSignalServiceAddress(context, sourceRecipient), - UnidentifiedAccessUtil.getAccessFor(context, sourceRecipient), - ContentHint.DEFAULT, - message, - IndividualSendEvents.EMPTY); - } - - @Override - public boolean onShouldRetry(@NonNull Exception e) { - Log.w(TAG, e); - return e instanceof PushNetworkException; - } - - @Override - public void onFailure() { - } - - public static final class Factory implements Job.Factory { - @Override - public @NonNull PushGroupUpdateJob create(@NonNull Parameters parameters, @NonNull org.thoughtcrime.securesms.jobmanager.Data data) { - return new PushGroupUpdateJob(parameters, - RecipientId.from(data.getString(KEY_SOURCE)), - GroupId.parseOrThrow(data.getString(KEY_GROUP_ID))); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.java index dcf587206..fab5ed954 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.java @@ -24,7 +24,7 @@ import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.GroupUtil; import org.whispersystems.signalservice.api.groupsv2.NoCredentialForRedemptionTimeException; import org.whispersystems.signalservice.api.messages.SignalServiceContent; -import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext; +import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; import java.io.IOException; @@ -120,27 +120,23 @@ public final class PushProcessMessageJob extends BaseJob { .setMaxAttempts(Parameters.UNLIMITED); if (content != null) { - SignalServiceGroupContext signalServiceGroupContext = GroupUtil.getGroupContextIfPresent(content); + SignalServiceGroupV2 signalServiceGroupContext = GroupUtil.getGroupContextIfPresent(content); if (signalServiceGroupContext != null) { - try { - GroupId groupId = GroupUtil.idFromGroupContext(signalServiceGroupContext); + GroupId groupId = GroupId.v2(signalServiceGroupContext.getMasterKey()); - queueName = getQueueName(Recipient.externalPossiblyMigratedGroup(groupId).getId()); + queueName = getQueueName(Recipient.externalPossiblyMigratedGroup(groupId).getId()); - if (groupId.isV2()) { - int localRevision = SignalDatabase.groups().getGroupV2Revision(groupId.requireV2()); + if (groupId.isV2()) { + int localRevision = SignalDatabase.groups().getGroupV2Revision(groupId.requireV2()); - if (signalServiceGroupContext.getGroupV2().get().getRevision() > localRevision || - SignalDatabase.groups().getGroupV1ByExpectedV2(groupId.requireV2()).isPresent()) - { - Log.i(TAG, "Adding network constraint to group-related job."); - builder.addConstraint(NetworkConstraint.KEY) - .setLifespan(TimeUnit.DAYS.toMillis(30)); - } + if (signalServiceGroupContext.getRevision() > localRevision || + SignalDatabase.groups().getGroupV1ByExpectedV2(groupId.requireV2()).isPresent()) + { + Log.i(TAG, "Adding network constraint to group-related job."); + builder.addConstraint(NetworkConstraint.KEY) + .setLifespan(TimeUnit.DAYS.toMillis(30)); } - } catch (BadGroupIdException e) { - Log.w(TAG, "Bad groupId! Using default queue. ID: " + content.getTimestamp()); } } else if (content.getSyncMessage().isPresent() && content.getSyncMessage().get().getSent().isPresent() && content.getSyncMessage().get().getSent().get().getDestination().isPresent()) { queueName = getQueueName(RecipientId.from(content.getSyncMessage().get().getSent().get().getDestination().get())); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java deleted file mode 100644 index 7caf83cdd..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - -import androidx.annotation.NonNull; - -import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; -import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; -import org.thoughtcrime.securesms.groups.GroupId; -import org.thoughtcrime.securesms.jobmanager.Data; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.thoughtcrime.securesms.net.NotPushRegisteredException; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.recipients.RecipientUtil; -import org.whispersystems.signalservice.api.SignalServiceMessageSender; -import org.whispersystems.signalservice.api.SignalServiceMessageSender.IndividualSendEvents; -import org.whispersystems.signalservice.api.crypto.ContentHint; -import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; -import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; -import org.whispersystems.signalservice.api.messages.SignalServiceGroup; -import org.whispersystems.signalservice.api.messages.SignalServiceGroup.Type; -import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; -import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -public class RequestGroupInfoJob extends BaseJob { - - public static final String KEY = "RequestGroupInfoJob"; - - @SuppressWarnings("unused") - private static final String TAG = Log.tag(RequestGroupInfoJob.class); - - private static final String KEY_SOURCE = "source"; - private static final String KEY_GROUP_ID = "group_id"; - - private final RecipientId source; - private final GroupId groupId; - - public RequestGroupInfoJob(@NonNull RecipientId source, @NonNull GroupId groupId) { - this(new Job.Parameters.Builder() - .addConstraint(NetworkConstraint.KEY) - .setLifespan(TimeUnit.DAYS.toMillis(1)) - .setMaxAttempts(Parameters.UNLIMITED) - .build(), - source, - groupId); - - } - - private RequestGroupInfoJob(@NonNull Job.Parameters parameters, @NonNull RecipientId source, @NonNull GroupId groupId) { - super(parameters); - - this.source = source; - this.groupId = groupId; - } - - @Override - public @NonNull Data serialize() { - return new Data.Builder().putString(KEY_SOURCE, source.serialize()) - .putString(KEY_GROUP_ID, groupId.toString()) - .build(); - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public void onRun() throws IOException, UntrustedIdentityException { - if (!Recipient.self().isRegistered()) { - throw new NotPushRegisteredException(); - } - - SignalServiceGroup group = SignalServiceGroup.newBuilder(Type.REQUEST_INFO) - .withId(groupId.getDecodedId()) - .build(); - - SignalServiceDataMessage message = SignalServiceDataMessage.newBuilder() - .asGroupMessage(group) - .withTimestamp(System.currentTimeMillis()) - .build(); - - SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); - Recipient recipient = Recipient.resolved(source); - - if (recipient.isUnregistered()) { - Log.w(TAG, recipient.getId() + " is unregistered!"); - return; - } - - messageSender.sendDataMessage(RecipientUtil.toSignalServiceAddress(context, recipient), - UnidentifiedAccessUtil.getAccessFor(context, recipient), - ContentHint.IMPLICIT, - message, - IndividualSendEvents.EMPTY); - } - - @Override - public boolean onShouldRetry(@NonNull Exception e) { - if (e instanceof ServerRejectedException) return false; - return e instanceof PushNetworkException; - } - - @Override - public void onFailure() { - - } - - public static final class Factory implements Job.Factory { - - @Override - public @NonNull RequestGroupInfoJob create(@NonNull Parameters parameters, @NonNull Data data) { - return new RequestGroupInfoJob(parameters, - RecipientId.from(data.getString(KEY_SOURCE)), - GroupId.parseOrThrow(data.getString(KEY_GROUP_ID))); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageProcessor.java index d3232b530..2863b2217 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageProcessor.java @@ -30,7 +30,7 @@ import org.thoughtcrime.securesms.util.Stopwatch; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.signalservice.api.SignalSessionLock; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; -import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext; +import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; import java.io.Closeable; import java.io.IOException; @@ -177,24 +177,19 @@ public class IncomingMessageProcessor { } private boolean needsToEnqueueProcessing(@NonNull DecryptionResult result) { - SignalServiceGroupContext groupContext = GroupUtil.getGroupContextIfPresent(result.getContent()); + SignalServiceGroupV2 groupContext = GroupUtil.getGroupContextIfPresent(result.getContent()); if (groupContext != null) { - try { - GroupId groupId = GroupUtil.idFromGroupContext(groupContext); + GroupId groupId = GroupId.v2(groupContext.getMasterKey()); - if (groupId.isV2()) { - String queueName = PushProcessMessageJob.getQueueName(Recipient.externalPossiblyMigratedGroup(groupId).getId()); - GroupDatabase groupDatabase = SignalDatabase.groups(); + if (groupId.isV2()) { + String queueName = PushProcessMessageJob.getQueueName(Recipient.externalPossiblyMigratedGroup(groupId).getId()); + GroupDatabase groupDatabase = SignalDatabase.groups(); - return !jobManager.isQueueEmpty(queueName) || - groupContext.getGroupV2().get().getRevision() > groupDatabase.getGroupV2Revision(groupId.requireV2()) || - groupDatabase.getGroupV1ByExpectedV2(groupId.requireV2()).isPresent(); - } else { - return false; - } - } catch (BadGroupIdException e) { - Log.w(TAG, "Bad group ID!"); + return !jobManager.isQueueEmpty(queueName) || + groupContext.getRevision() > groupDatabase.getGroupV2Revision(groupId.requireV2()) || + groupDatabase.getGroupV1ByExpectedV2(groupId.requireV2()).isPresent(); + } else { return false; } } else if (result.getContent() != null) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java index 6726c27fb..a9c016c3a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java @@ -69,7 +69,6 @@ import org.thoughtcrime.securesms.groups.GroupChangeBusyException; import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupNotAMemberException; -import org.thoughtcrime.securesms.groups.GroupV1MessageProcessor; import org.thoughtcrime.securesms.groups.GroupsV1MigrationUtil; import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob; @@ -92,7 +91,6 @@ import org.thoughtcrime.securesms.jobs.PushProcessEarlyMessagesJob; import org.thoughtcrime.securesms.jobs.PushProcessMessageJob; import org.thoughtcrime.securesms.jobs.RefreshAttributesJob; import org.thoughtcrime.securesms.jobs.RefreshOwnProfileJob; -import org.thoughtcrime.securesms.jobs.RequestGroupInfoJob; import org.thoughtcrime.securesms.jobs.ResendMessageJob; import org.thoughtcrime.securesms.jobs.RetrieveProfileJob; import org.thoughtcrime.securesms.jobs.SendDeliveryReceiptJob; @@ -142,8 +140,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; import org.whispersystems.signalservice.api.messages.SignalServiceContent; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; -import org.whispersystems.signalservice.api.messages.SignalServiceGroup; -import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext; import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; import org.whispersystems.signalservice.api.messages.SignalServicePreview; import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage; @@ -283,7 +279,7 @@ public final class MessageContentProcessor { boolean isGv2Message = groupId.isPresent() && groupId.get().isV2(); if (isGv2Message) { - if (handleGv2PreProcessing(groupId.orElse(null).requireV2(), content, content.getDataMessage().get().getGroupContext().get().getGroupV2().get(), senderRecipient)) { + if (handleGv2PreProcessing(groupId.orElse(null).requireV2(), content, content.getDataMessage().get().getGroupContext().get(), senderRecipient)) { return; } } @@ -292,7 +288,6 @@ public final class MessageContentProcessor { if (isInvalidMessage(message)) handleInvalidMessage(content.getSender(), content.getSenderDevice(), groupId, content.getTimestamp(), smsMessageId); else if (message.isEndSession()) messageId = handleEndSessionMessage(content, smsMessageId, senderRecipient); - else if (message.isGroupV1Update()) handleGroupV1Message(content, message, smsMessageId, groupId.get().requireV1(), senderRecipient, threadRecipient, receivedTime); else if (message.isExpirationUpdate()) messageId = handleExpirationUpdate(content, message, smsMessageId, groupId, senderRecipient, threadRecipient, receivedTime, false); else if (message.getReaction().isPresent() && message.getStoryContext().isPresent()) messageId = handleStoryReaction(content, message, senderRecipient); else if (message.getReaction().isPresent()) messageId = handleReaction(content, message, senderRecipient); @@ -516,20 +511,6 @@ public final class MessageContentProcessor { return false; } - - private static @Nullable SignalServiceGroupContext getGroupContextIfPresent(@NonNull SignalServiceContent content) { - if (content.getDataMessage().isPresent() && content.getDataMessage().get().getGroupContext().isPresent()) { - return content.getDataMessage().get().getGroupContext().get(); - } else if (content.getSyncMessage().isPresent() && - content.getSyncMessage().get().getSent().isPresent() && - content.getSyncMessage().get().getSent().get().getDataMessage().get().getGroupContext().isPresent()) - { - return content.getSyncMessage().get().getSent().get().getDataMessage().get().getGroupContext().get(); - } else { - return null; - } - } - /** * Attempts to update the group to the revision mentioned in the message. * If the local version is at least the revision in the message it will not query the server. @@ -790,51 +771,20 @@ public final class MessageContentProcessor { return threadId; } - private void handleGroupV1Message(@NonNull SignalServiceContent content, - @NonNull SignalServiceDataMessage message, - @NonNull Optional smsMessageId, - @NonNull GroupId.V1 groupId, - @NonNull Recipient senderRecipient, - @NonNull Recipient threadRecipient, - long receivedTime) - throws StorageFailedException, BadGroupIdException - { - log(content.getTimestamp(), "GroupV1 message."); - - GroupV1MessageProcessor.process(context, content, message, false); - - handlePossibleExpirationUpdate(content, message, Optional.of(groupId), senderRecipient, threadRecipient, receivedTime); - - if (smsMessageId.isPresent()) { - SignalDatabase.sms().deleteMessage(smsMessageId.get()); - } - } - private void handleUnknownGroupMessage(@NonNull SignalServiceContent content, - @NonNull SignalServiceGroupContext group, + @NonNull SignalServiceGroupV2 group, @NonNull Recipient senderRecipient) throws BadGroupIdException { log(content.getTimestamp(), "Unknown group message."); - if (group.getGroupV1().isPresent()) { - SignalServiceGroup groupV1 = group.getGroupV1().get(); - if (groupV1.getType() != SignalServiceGroup.Type.REQUEST_INFO) { - ApplicationDependencies.getJobManager().add(new RequestGroupInfoJob(senderRecipient.getId(), GroupId.v1(groupV1.getGroupId()))); - } else { - warn(content.getTimestamp(), "Received a REQUEST_INFO message for a group we don't know about. Ignoring."); - } - } else if (group.getGroupV2().isPresent()) { - warn(content.getTimestamp(), "Received a GV2 message for a group we have no knowledge of -- attempting to fix this state."); - ServiceId authServiceId = ServiceId.parseOrNull(content.getDestinationUuid()); - if (authServiceId == null) { - warn(content.getTimestamp(), "Group message missing destination uuid, defaulting to ACI"); - authServiceId = SignalStore.account().requireAci(); - } - SignalDatabase.groups().fixMissingMasterKey(authServiceId, group.getGroupV2().get().getMasterKey()); - } else { - warn(content.getTimestamp(), "Received a message for a group we don't know about without a group context. Ignoring."); + warn(content.getTimestamp(), "Received a GV2 message for a group we have no knowledge of -- attempting to fix this state."); + ServiceId authServiceId = ServiceId.parseOrNull(content.getDestinationUuid()); + if (authServiceId == null) { + warn(content.getTimestamp(), "Group message missing destination uuid, defaulting to ACI"); + authServiceId = SignalStore.account().requireAci(); } + SignalDatabase.groups().fixMissingMasterKey(authServiceId, group.getMasterKey()); } /** @@ -876,8 +826,8 @@ public final class MessageContentProcessor { return null; } - int expiresInSeconds = message.getExpiresInSeconds(); - Optional groupContext = message.getGroupContext(); + int expiresInSeconds = message.getExpiresInSeconds(); + Optional groupContext = message.getGroupContext(); if (threadRecipient.getExpiresInSeconds() == expiresInSeconds) { log(String.valueOf(content.getTimestamp()), "No change in message expiry for group. Ignoring."); @@ -1212,8 +1162,8 @@ public final class MessageContentProcessor { SignalServiceDataMessage dataMessage = message.getDataMessage().get(); if (dataMessage.isGroupV2Message()) { - GroupId.V2 groupId = GroupId.v2(dataMessage.getGroupContext().get().getGroupV2().get().getMasterKey()); - if (handleGv2PreProcessing(groupId, content, dataMessage.getGroupContext().get().getGroupV2().get(), senderRecipient)) { + GroupId.V2 groupId = GroupId.v2(dataMessage.getGroupContext().get().getMasterKey()); + if (handleGv2PreProcessing(groupId, content, dataMessage.getGroupContext().get(), senderRecipient)) { return; } } @@ -1224,9 +1174,6 @@ public final class MessageContentProcessor { handleGroupRecipientUpdate(message, content.getTimestamp()); } else if (dataMessage.isEndSession()) { threadId = handleSynchronizeSentEndSessionMessage(message, content.getTimestamp()); - } else if (dataMessage.isGroupV1Update()) { - Long gv1ThreadId = GroupV1MessageProcessor.process(context, content, dataMessage, true); - threadId = gv1ThreadId == null ? -1 : gv1ThreadId; } else if (dataMessage.isGroupV2Update()) { handleSynchronizeSentGv2Update(content, message); threadId = SignalDatabase.threads().getOrCreateThreadIdFor(getSyncMessageDestination(message)); @@ -1249,7 +1196,7 @@ public final class MessageContentProcessor { threadId = handleSynchronizeSentTextMessage(message, content.getTimestamp()); } - if (dataMessage.getGroupContext().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.idFromGroupContext(dataMessage.getGroupContext().get()))) { + if (dataMessage.getGroupContext().isPresent() && groupDatabase.isUnknownGroup(GroupId.v2(dataMessage.getGroupContext().get().getMasterKey()))) { handleUnknownGroupMessage(content, dataMessage.getGroupContext().get(), senderRecipient); } @@ -1284,7 +1231,7 @@ public final class MessageContentProcessor { log(content.getTimestamp(), "Synchronize sent GV2 update for message with timestamp " + message.getTimestamp()); SignalServiceDataMessage dataMessage = message.getDataMessage().get(); - SignalServiceGroupV2 signalServiceGroupV2 = dataMessage.getGroupContext().get().getGroupV2().get(); + SignalServiceGroupV2 signalServiceGroupV2 = dataMessage.getGroupContext().get(); GroupId.V2 groupIdV2 = GroupId.v2(signalServiceGroupV2.getMasterKey()); if (!updateGv2GroupFromServerOrP2PChange(content, signalServiceGroupV2)) { @@ -3012,9 +2959,7 @@ public final class MessageContentProcessor { return database.insertMessageInbox(textMessage); } - private Recipient getSyncMessageDestination(@NonNull SentTranscriptMessage message) - throws BadGroupIdException - { + private Recipient getSyncMessageDestination(@NonNull SentTranscriptMessage message) { return getGroupRecipient(message.getDataMessage().get().getGroupContext()).orElseGet(() -> Recipient.externalPush(message.getDestination().get())); } @@ -3023,13 +2968,12 @@ public final class MessageContentProcessor { return getGroupRecipient(message != null ? message.getGroupContext() : Optional.empty()).orElseGet(() -> Recipient.externalPush(content.getSender())); } - private Optional getGroupRecipient(Optional message) - throws BadGroupIdException - { + private Optional getGroupRecipient(Optional message) { if (message.isPresent()) { - return Optional.of(Recipient.externalPossiblyMigratedGroup(GroupUtil.idFromGroupContext(message.get()))); + return Optional.of(Recipient.externalPossiblyMigratedGroup(GroupId.v2(message.get().getMasterKey()))); + } else { + return Optional.empty(); } - return Optional.empty(); } private void notifyTypingStoppedFromIncomingMessage(@NonNull Recipient senderRecipient, @NonNull Recipient conversationRecipient, int device) { @@ -3053,15 +2997,6 @@ public final class MessageContentProcessor { GroupDatabase groupDatabase = SignalDatabase.groups(); Optional groupId = GroupUtil.idFromGroupContext(message.getGroupContext()); - if (groupId.isPresent() && - groupId.get().isV1() && - message.isGroupV1Update() && - groupDatabase.groupExists(groupId.get().requireV1().deriveV2MigrationGroupId())) - { - warn(String.valueOf(content.getTimestamp()), "Ignoring V1 update for a group we've already migrated to V2."); - return true; - } - if (groupId.isPresent() && groupDatabase.isUnknownGroup(groupId.get())) { return sender.isBlocked(); } @@ -3070,11 +3005,10 @@ public final class MessageContentProcessor { boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent() || message.getSticker().isPresent(); boolean isExpireMessage = message.isExpirationUpdate(); boolean isGv2Update = message.isGroupV2Update(); - boolean isContentMessage = !message.isGroupV1Update() && !isGv2Update && !isExpireMessage && (isTextMessage || isMediaMessage); + boolean isContentMessage = !isGv2Update && !isExpireMessage && (isTextMessage || isMediaMessage); boolean isGroupActive = groupId.isPresent() && groupDatabase.isActive(groupId.get()); - boolean isLeaveMessage = message.getGroupContext().isPresent() && message.getGroupContext().get().getGroupV1Type() == SignalServiceGroup.Type.QUIT; - return (isContentMessage && !isGroupActive) || (sender.isBlocked() && !isLeaveMessage && !isGv2Update); + return (isContentMessage && !isGroupActive) || (sender.isBlocked() && !isGv2Update); } else { return sender.isBlocked(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java index ae8ba66a0..412dfe463 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java @@ -207,15 +207,7 @@ public final class MessageDecryptionUtil { if (sender == null) throw new NoSenderException(); - GroupId groupId = null; - - if (e.getGroup().isPresent()) { - try { - groupId = GroupUtil.idFromGroupContext(e.getGroup().get()); - } catch (BadGroupIdException ex) { - Log.w(TAG, "Bad group id found in unsupported data message", ex); - } - } + GroupId groupId = e.getGroup().isPresent() ? GroupId.v2(e.getGroup().get().getMasterKey()) : null; return new ExceptionMetadata(sender, e.getSenderDevice(), groupId); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMediaMessage.kt b/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMediaMessage.kt index 5c00d6815..e620f64b2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMediaMessage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMediaMessage.kt @@ -11,9 +11,8 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.linkpreview.LinkPreview import org.thoughtcrime.securesms.recipients.RecipientId -import org.thoughtcrime.securesms.util.GroupUtil import org.whispersystems.signalservice.api.messages.SignalServiceAttachment -import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext +import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2 import java.util.Optional class IncomingMediaMessage( @@ -96,7 +95,7 @@ class IncomingMediaMessage( viewOnce: Boolean, unidentified: Boolean, body: Optional, - group: Optional, + group: Optional, attachments: Optional>, quote: Optional, sharedContacts: Optional>, @@ -107,7 +106,7 @@ class IncomingMediaMessage( giftBadge: GiftBadge? ) : this( from = from, - groupId = if (group.isPresent) GroupUtil.idFromGroupContextOrThrow(group.get()) else null, + groupId = if (group.isPresent) GroupId.v2(group.get().masterKey) else null, body = body.orElse(null), isPushMessage = true, storyType = storyType, diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/GroupUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/GroupUtil.java index ac20cdce6..7025d3e56 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/GroupUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/GroupUtil.java @@ -6,31 +6,23 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; -import com.google.protobuf.ByteString; import org.signal.core.util.StringUtil; import org.signal.core.util.logging.Log; -import org.signal.libsignal.protocol.InvalidMessageException; import org.signal.libsignal.zkgroup.InvalidInputException; import org.signal.libsignal.zkgroup.groups.GroupMasterKey; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.SignalDatabase; -import org.thoughtcrime.securesms.groups.BadGroupIdException; import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.mms.MessageGroupContext; -import org.thoughtcrime.securesms.mms.OutgoingGroupUpdateMessage; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.whispersystems.signalservice.api.messages.SignalServiceContent; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; -import org.whispersystems.signalservice.api.messages.SignalServiceGroup; -import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext; import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; -import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext; import java.io.IOException; -import java.util.Collections; import java.util.List; import java.util.Optional; @@ -44,7 +36,7 @@ public final class GroupUtil { /** * @return The group context present on the content if one exists, otherwise null. */ - public static @Nullable SignalServiceGroupContext getGroupContextIfPresent(@Nullable SignalServiceContent content) { + public static @Nullable SignalServiceGroupV2 getGroupContextIfPresent(@Nullable SignalServiceContent content) { if (content == null) { return null; } else if (content.getDataMessage().isPresent() && content.getDataMessage().get().getGroupContext().isPresent()) { @@ -56,11 +48,7 @@ public final class GroupUtil { { return content.getSyncMessage().get().getSent().get().getDataMessage().get().getGroupContext().get(); } else if (content.getStoryMessage().isPresent() && content.getStoryMessage().get().getGroupContext().isPresent()) { - try { - return SignalServiceGroupContext.create(null, content.getStoryMessage().get().getGroupContext().get()); - } catch (InvalidMessageException e) { - throw new AssertionError(e); - } + return content.getStoryMessage().get().getGroupContext().get(); } else { return null; } @@ -69,36 +57,12 @@ public final class GroupUtil { /** * Result may be a v1 or v2 GroupId. */ - public static @NonNull GroupId idFromGroupContext(@NonNull SignalServiceGroupContext groupContext) - throws BadGroupIdException - { - if (groupContext.getGroupV1().isPresent()) { - return GroupId.v1(groupContext.getGroupV1().get().getGroupId()); - } else if (groupContext.getGroupV2().isPresent()) { - return GroupId.v2(groupContext.getGroupV2().get().getMasterKey()); - } else { - throw new AssertionError(); - } - } - - public static @NonNull GroupId idFromGroupContextOrThrow(@NonNull SignalServiceGroupContext groupContext) { - try { - return idFromGroupContext(groupContext); - } catch (BadGroupIdException e) { - throw new AssertionError(e); - } - } - - /** - * Result may be a v1 or v2 GroupId. - */ - public static @NonNull Optional idFromGroupContext(@NonNull Optional groupContext) - throws BadGroupIdException - { + public static @NonNull Optional idFromGroupContext(@NonNull Optional groupContext) { if (groupContext.isPresent()) { - return Optional.of(idFromGroupContext(groupContext.get())); + return Optional.of(GroupId.v2(groupContext.get().getMasterKey())); + } else { + return Optional.empty(); } - return Optional.empty(); } public static @NonNull GroupMasterKey requireMasterKey(@NonNull byte[] masterKey) { @@ -129,36 +93,14 @@ public final class GroupUtil { @NonNull GroupId.Push groupId) { if (groupId.isV2()) { - GroupDatabase groupDatabase = SignalDatabase.groups(); - GroupDatabase.GroupRecord groupRecord = groupDatabase.requireGroup(groupId); - GroupDatabase.V2GroupProperties v2GroupProperties = groupRecord.requireV2GroupProperties(); - SignalServiceGroupV2 group = SignalServiceGroupV2.newBuilder(v2GroupProperties.getGroupMasterKey()) - .withRevision(v2GroupProperties.getGroupRevision()) - .build(); - dataMessageBuilder.asGroupMessage(group); - } else { - dataMessageBuilder.asGroupMessage(new SignalServiceGroup(groupId.getDecodedId())); - } - } - - public static OutgoingGroupUpdateMessage createGroupV1LeaveMessage(@NonNull GroupId.V1 groupId, - @NonNull Recipient groupRecipient) - { - GroupContext groupContext = GroupContext.newBuilder() - .setId(ByteString.copyFrom(groupId.getDecodedId())) - .setType(GroupContext.Type.QUIT) - .build(); - - return new OutgoingGroupUpdateMessage(groupRecipient, - groupContext, - null, - System.currentTimeMillis(), - 0, - false, - null, - Collections.emptyList(), - Collections.emptyList(), - Collections.emptyList()); + GroupDatabase groupDatabase = SignalDatabase.groups(); + GroupDatabase.GroupRecord groupRecord = groupDatabase.requireGroup(groupId); + GroupDatabase.V2GroupProperties v2GroupProperties = groupRecord.requireV2GroupProperties(); + SignalServiceGroupV2 group = SignalServiceGroupV2.newBuilder(v2GroupProperties.getGroupMasterKey()) + .withRevision(v2GroupProperties.getGroupRevision()) + .build(); + dataMessageBuilder.asGroupMessage(group); + } } public static class GroupDescription { diff --git a/app/src/test/java/org/thoughtcrime/securesms/jobmanager/migrations/RecipientIdFollowUpJobMigrationTest.java b/app/src/test/java/org/thoughtcrime/securesms/jobmanager/migrations/RecipientIdFollowUpJobMigrationTest.java index 182b30e56..e3d37fb69 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/jobmanager/migrations/RecipientIdFollowUpJobMigrationTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/jobmanager/migrations/RecipientIdFollowUpJobMigrationTest.java @@ -10,7 +10,6 @@ import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JobMigration.JobData; import org.thoughtcrime.securesms.jobs.FailingJob; -import org.thoughtcrime.securesms.jobs.RequestGroupInfoJob; import org.thoughtcrime.securesms.jobs.SendDeliveryReceiptJob; import org.thoughtcrime.securesms.recipients.Recipient; @@ -29,35 +28,6 @@ public class RecipientIdFollowUpJobMigrationTest { @Mock private MockedStatic jobParametersMockedStatic; - @Test - public void migrate_requestGroupInfoJob_good() throws Exception { - JobData testData = new JobData("RequestGroupInfoJob", null, new Data.Builder().putString("source", "1") - .putString("group_id", "__textsecure_group__!abcdef0123456789abcdef0123456789") - .build()); - RecipientIdFollowUpJobMigration subject = new RecipientIdFollowUpJobMigration(); - JobData converted = subject.migrate(testData); - - assertEquals("RequestGroupInfoJob", converted.getFactoryKey()); - assertNull(converted.getQueueKey()); - assertEquals("1", converted.getData().getString("source")); - assertEquals("__textsecure_group__!abcdef0123456789abcdef0123456789", converted.getData().getString("group_id")); - - new RequestGroupInfoJob.Factory().create(mock(Job.Parameters.class), converted.getData()); - } - - @Test - public void migrate_requestGroupInfoJob_bad() throws Exception { - JobData testData = new JobData("RequestGroupInfoJob", null, new Data.Builder().putString("source", "1") - .build()); - RecipientIdFollowUpJobMigration subject = new RecipientIdFollowUpJobMigration(); - JobData converted = subject.migrate(testData); - - assertEquals("FailingJob", converted.getFactoryKey()); - assertNull(converted.getQueueKey()); - - new FailingJob.Factory().create(mock(Job.Parameters.class), converted.getData()); - } - @Test public void migrate_sendDeliveryReceiptJob_good() throws Exception { JobData testData = new JobData("SendDeliveryReceiptJob", null, new Data.Builder().putString("recipient", "1") diff --git a/app/src/test/java/org/thoughtcrime/securesms/jobmanager/migrations/RecipientIdJobMigrationTest.java b/app/src/test/java/org/thoughtcrime/securesms/jobmanager/migrations/RecipientIdJobMigrationTest.java index af54d778b..53271ea10 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/jobmanager/migrations/RecipientIdJobMigrationTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/jobmanager/migrations/RecipientIdJobMigrationTest.java @@ -19,10 +19,8 @@ import org.thoughtcrime.securesms.jobs.MultiDeviceReadUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceVerifiedUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceViewOnceOpenJob; import org.thoughtcrime.securesms.jobs.PushGroupSendJob; -import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob; import org.thoughtcrime.securesms.jobs.PushMediaSendJob; import org.thoughtcrime.securesms.jobs.PushTextSendJob; -import org.thoughtcrime.securesms.jobs.RequestGroupInfoJob; import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob; import org.thoughtcrime.securesms.jobs.SendDeliveryReceiptJob; import org.thoughtcrime.securesms.jobs.SmsSendJob; @@ -83,24 +81,6 @@ public class RecipientIdJobMigrationTest { new MultiDeviceViewOnceOpenJob.Factory().create(mock(Job.Parameters.class), converted.getData()); } - @Test - public void migrate_requestGroupInfoJob() throws Exception { - JobData testData = new JobData("RequestGroupInfoJob", null, new Data.Builder().putString("source", "+16101234567") - .putString("group_id", "__textsecure_group__!abcdef0123456789abcdef0123456789") - .build()); - mockRecipientResolve("+16101234567", 1); - - RecipientIdJobMigration subject = new RecipientIdJobMigration(mock(Application.class)); - JobData converted = subject.migrate(testData); - - assertEquals("RequestGroupInfoJob", converted.getFactoryKey()); - assertNull(converted.getQueueKey()); - assertEquals("1", converted.getData().getString("source")); - assertEquals("__textsecure_group__!abcdef0123456789abcdef0123456789", converted.getData().getString("group_id")); - - new RequestGroupInfoJob.Factory().create(mock(Job.Parameters.class), converted.getData()); - } - @Test public void migrate_sendDeliveryReceiptJob() throws Exception { JobData testData = new JobData("SendDeliveryReceiptJob", null, new Data.Builder().putString("address", "+16101234567") @@ -180,24 +160,6 @@ public class RecipientIdJobMigrationTest { new PushGroupSendJob.Factory().create(mock(Job.Parameters.class), converted.getData()); } - @Test - public void migrate_pushGroupUpdateJob() throws Exception { - JobData testData = new JobData("PushGroupUpdateJob", null, new Data.Builder().putString("source", "+16101234567") - .putString("group_id", "__textsecure_group__!abcdef0123456789abcdef0123456789") - .build()); - mockRecipientResolve("+16101234567", 1); - - RecipientIdJobMigration subject = new RecipientIdJobMigration(mock(Application.class)); - JobData converted = subject.migrate(testData); - - assertEquals("PushGroupUpdateJob", converted.getFactoryKey()); - assertNull(converted.getQueueKey()); - assertEquals("1", converted.getData().getString("source")); - assertEquals("__textsecure_group__!abcdef0123456789abcdef0123456789", converted.getData().getString("group_id")); - - new PushGroupUpdateJob.Factory().create(mock(Job.Parameters.class), converted.getData()); - } - @Test public void migrate_directoryRefreshJob_null() throws Exception { JobData testData = new JobData("DirectoryRefreshJob", "DirectoryRefreshJob", new Data.Builder().putString("address", null).putBoolean("notify_of_new_users", true).build()); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java index 8bf454186..c8968c716 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java @@ -36,8 +36,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPoin import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; -import org.whispersystems.signalservice.api.messages.SignalServiceGroup; -import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext; import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; import org.whispersystems.signalservice.api.messages.SignalServicePreview; import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage; @@ -102,7 +100,6 @@ import org.whispersystems.signalservice.internal.push.SignalServiceProtos.Attach import org.whispersystems.signalservice.internal.push.SignalServiceProtos.CallMessage; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.Content; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.DataMessage; -import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContextV2; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.NullMessage; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.Preview; @@ -834,14 +831,7 @@ public class SignalServiceMessageSender { } if (message.getGroupContext().isPresent()) { - SignalServiceGroupContext groupContext = message.getGroupContext().get(); - if (groupContext.getGroupV1().isPresent()) { - builder.setGroup(createGroupContent(groupContext.getGroupV1().get())); - } - - if (groupContext.getGroupV2().isPresent()) { - builder.setGroupV2(createGroupContent(groupContext.getGroupV2().get())); - } + builder.setGroupV2(createGroupContent(message.getGroupContext().get())); } if (message.isEndSession()) { @@ -1473,47 +1463,6 @@ public class SignalServiceMessageSender { return builder; } - private GroupContext createGroupContent(SignalServiceGroup group) throws IOException { - GroupContext.Builder builder = GroupContext.newBuilder(); - builder.setId(ByteString.copyFrom(group.getGroupId())); - - if (group.getType() != SignalServiceGroup.Type.DELIVER) { - if (group.getType() == SignalServiceGroup.Type.UPDATE) builder.setType(GroupContext.Type.UPDATE); - else if (group.getType() == SignalServiceGroup.Type.QUIT) builder.setType(GroupContext.Type.QUIT); - else if (group.getType() == SignalServiceGroup.Type.REQUEST_INFO) builder.setType(GroupContext.Type.REQUEST_INFO); - else throw new AssertionError("Unknown type: " + group.getType()); - - if (group.getName().isPresent()) { - builder.setName(group.getName().get()); - } - - if (group.getMembers().isPresent()) { - for (SignalServiceAddress address : group.getMembers().get()) { - if (address.getNumber().isPresent()) { - builder.addMembersE164(address.getNumber().get()); - - GroupContext.Member.Builder memberBuilder = GroupContext.Member.newBuilder(); - memberBuilder.setE164(address.getNumber().get()); - - builder.addMembers(memberBuilder.build()); - } - } - } - - if (group.getAvatar().isPresent()) { - if (group.getAvatar().get().isStream()) { - builder.setAvatar(createAttachmentPointer(group.getAvatar().get().asStream())); - } else { - builder.setAvatar(createAttachmentPointer(group.getAvatar().get().asPointer())); - } - } - } else { - builder.setType(GroupContext.Type.DELIVER); - } - - return builder.build(); - } - private static GroupContextV2 createGroupContent(SignalServiceGroupV2 group) { GroupContextV2.Builder builder = GroupContextV2.newBuilder() .setMasterKey(ByteString.copyFrom(group.getMasterKey().serialize())) diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceContent.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceContent.java index 594f753ec..b8d506720 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceContent.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceContent.java @@ -594,15 +594,8 @@ public final class SignalServiceContent { SignalServiceProtos.DataMessage content) throws UnsupportedDataMessageException, InvalidMessageStructureException { - SignalServiceGroupV2 groupInfoV2 = createGroupV2Info(content); - Optional groupContext; - - try { - groupContext = SignalServiceGroupContext.createOptional(null, groupInfoV2); - } catch (InvalidMessageException e) { - throw new InvalidMessageStructureException(e); - } - + SignalServiceGroupV2 groupInfoV2 = createGroupV2Info(content); + Optional groupContext = Optional.ofNullable(groupInfoV2); List attachments = new LinkedList<>(); boolean endSession = ((content.getFlags() & SignalServiceProtos.DataMessage.Flags.END_SESSION_VALUE ) != 0); @@ -649,7 +642,6 @@ public final class SignalServiceContent { } return new SignalServiceDataMessage(metadata.getTimestamp(), - null, groupInfoV2, attachments, content.hasBody() ? content.getBody() : null, diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java index 82443f640..7659534be 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java @@ -27,7 +27,7 @@ public class SignalServiceDataMessage { private final long timestamp; private final Optional> attachments; private final Optional body; - private final Optional group; + private final Optional group; private final Optional profileKey; private final boolean endSession; private final boolean expirationUpdate; @@ -50,7 +50,6 @@ public class SignalServiceDataMessage { * Construct a SignalServiceDataMessage. * * @param timestamp The sent timestamp. - * @param group The group information (or null if none). * @param groupV2 The group information (or null if none). * @param attachments The attachments (or null if none). * @param body The message contents. @@ -58,7 +57,6 @@ public class SignalServiceDataMessage { * @param expiresInSeconds Number of seconds in which the message should disappear after being seen. */ SignalServiceDataMessage(long timestamp, - SignalServiceGroup group, SignalServiceGroupV2 groupV2, List attachments, String body, @@ -80,12 +78,7 @@ public class SignalServiceDataMessage { StoryContext storyContext, GiftBadge giftBadge) { - try { - this.group = SignalServiceGroupContext.createOptional(group, groupV2); - } catch (InvalidMessageException e) { - throw new AssertionError(e); - } - + this.group = Optional.ofNullable(groupV2); this.timestamp = timestamp; this.body = OptionalUtil.absentIfEmpty(body); this.endSession = endSession; @@ -156,7 +149,7 @@ public class SignalServiceDataMessage { /** * @return The message group context (if any). */ - public Optional getGroupContext() { + public Optional getGroupContext() { return group; } @@ -172,20 +165,13 @@ public class SignalServiceDataMessage { return profileKeyUpdate; } - public boolean isGroupV1Update() { - return group.isPresent() && - group.get().getGroupV1().isPresent() && - group.get().getGroupV1().get().getType() != SignalServiceGroup.Type.DELIVER; - } - public boolean isGroupV2Message() { - return group.isPresent() && - group.get().getGroupV2().isPresent(); + return group.isPresent(); } public boolean isGroupV2Update() { - return isGroupV2Message() && - group.get().getGroupV2().get().hasSignedGroupChange() && + return group.isPresent() && + group.get().hasSignedGroupChange() && !hasRenderableContent(); } @@ -265,8 +251,8 @@ public class SignalServiceDataMessage { public Optional getGroupId() { byte[] groupId = null; - if (getGroupContext().isPresent() && getGroupContext().get().getGroupV2().isPresent()) { - SignalServiceGroupV2 gv2 = getGroupContext().get().getGroupV2().get(); + if (getGroupContext().isPresent() && getGroupContext().isPresent()) { + SignalServiceGroupV2 gv2 = getGroupContext().get(); groupId = GroupSecretParams.deriveFromMasterKey(gv2.getMasterKey()) .getPublicParams() .getGroupIdentifier() @@ -284,7 +270,6 @@ public class SignalServiceDataMessage { private List mentions = new LinkedList<>(); private long timestamp; - private SignalServiceGroup group; private SignalServiceGroupV2 groupV2; private String body; private boolean endSession; @@ -309,18 +294,7 @@ public class SignalServiceDataMessage { return this; } - public Builder asGroupMessage(SignalServiceGroup group) { - if (this.groupV2 != null) { - throw new AssertionError("Can not contain both V1 and V2 group contexts."); - } - this.group = group; - return this; - } - public Builder asGroupMessage(SignalServiceGroupV2 group) { - if (this.group != null) { - throw new AssertionError("Can not contain both V1 and V2 group contexts."); - } this.groupV2 = group; return this; } @@ -440,7 +414,7 @@ public class SignalServiceDataMessage { public SignalServiceDataMessage build() { if (timestamp == 0) timestamp = System.currentTimeMillis(); - return new SignalServiceDataMessage(timestamp, group, groupV2, attachments, body, endSession, + return new SignalServiceDataMessage(timestamp, groupV2, attachments, body, endSession, expiresInSeconds, expirationUpdate, profileKey, profileKeyUpdate, quote, sharedContacts, previews, mentions, sticker, viewOnce, reaction, remoteDelete, diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceGroupContext.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceGroupContext.java deleted file mode 100644 index b3f92b9c3..000000000 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceGroupContext.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.whispersystems.signalservice.api.messages; - -import org.signal.libsignal.protocol.InvalidMessageException; - -import java.util.Optional; - - -public final class SignalServiceGroupContext { - - private final Optional groupV1; - private final Optional groupV2; - - private SignalServiceGroupContext(SignalServiceGroup groupV1) { - this.groupV1 = Optional.of(groupV1); - this.groupV2 = Optional.empty(); - } - - private SignalServiceGroupContext(SignalServiceGroupV2 groupV2) { - this.groupV1 = Optional.empty(); - this.groupV2 = Optional.of(groupV2); - } - - public Optional getGroupV1() { - return groupV1; - } - - public Optional getGroupV2() { - return groupV2; - } - - static Optional createOptional(SignalServiceGroup groupV1, SignalServiceGroupV2 groupV2) - throws InvalidMessageException - { - return Optional.ofNullable(create(groupV1, groupV2)); - } - - public static SignalServiceGroupContext create(SignalServiceGroup groupV1, SignalServiceGroupV2 groupV2) - throws InvalidMessageException - { - if (groupV1 == null && groupV2 == null) { - return null; - } - - if (groupV1 != null && groupV2 != null) { - throw new InvalidMessageException("Message cannot have both V1 and V2 group contexts."); - } - - if (groupV1 != null) { - return new SignalServiceGroupContext(groupV1); - } else { - return new SignalServiceGroupContext(groupV2); - } - } - - public SignalServiceGroup.Type getGroupV1Type() { - if (groupV1.isPresent()) { - return groupV1.get().getType(); - } - return null; - } -} diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageException.java index ad73a24a6..e3b5ec83f 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageException.java @@ -1,7 +1,7 @@ package org.whispersystems.signalservice.internal.push; -import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext; +import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; import java.util.Optional; @@ -12,14 +12,14 @@ import java.util.Optional; */ public abstract class UnsupportedDataMessageException extends Exception { - private final String sender; - private final int senderDevice; - private final Optional group; + private final String sender; + private final int senderDevice; + private final Optional group; protected UnsupportedDataMessageException(String message, String sender, int senderDevice, - Optional group) + Optional group) { super(message); this.sender = sender; @@ -35,7 +35,7 @@ public abstract class UnsupportedDataMessageException extends Exception { return senderDevice; } - public Optional getGroup() { + public Optional getGroup() { return group; } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageProtocolVersionException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageProtocolVersionException.java index d39dff689..402eb960d 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageProtocolVersionException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageProtocolVersionException.java @@ -1,7 +1,7 @@ package org.whispersystems.signalservice.internal.push; -import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext; +import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; import java.util.Optional; @@ -16,7 +16,7 @@ public final class UnsupportedDataMessageProtocolVersionException extends Unsupp int requiredVersion, String sender, int senderDevice, - Optional group) { + Optional group) { super("Required version: " + requiredVersion + ", Our version: " + currentVersion, sender, senderDevice, group); this.requiredVersion = requiredVersion; } diff --git a/libsignal/service/src/main/proto/SignalService.proto b/libsignal/service/src/main/proto/SignalService.proto index d692a6c60..88efdca53 100644 --- a/libsignal/service/src/main/proto/SignalService.proto +++ b/libsignal/service/src/main/proto/SignalService.proto @@ -313,7 +313,7 @@ message DataMessage { optional string body = 1; repeated AttachmentPointer attachments = 2; - optional GroupContext group = 3; + reserved /*groupV1*/ 3; optional GroupContextV2 groupV2 = 15; optional uint32 flags = 4; optional uint32 expireTimer = 5;