Switch MMS groups to use the group database infrastructure

Eliminate the concept of 'Recipients' (plural). There is now just
a 'Recipient', which contains an Address that is either an individual
or a group ID.

MMS groups now exist as part of the group database, just like push
groups.

// FREEBIE
This commit is contained in:
Moxie Marlinspike
2017-08-01 08:56:00 -07:00
parent 81682e0302
commit 375207f073
106 changed files with 1587 additions and 2192 deletions

View File

@@ -24,7 +24,7 @@ import org.thoughtcrime.securesms.database.TextSecureDirectory;
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.push.AccountManagerFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.sms.IncomingJoinedMessage;
import org.thoughtcrime.securesms.util.DirectoryHelper.UserCapabilities.Capability;
import org.whispersystems.libsignal.util.guava.Optional;
@@ -123,12 +123,12 @@ public class DirectoryHelper {
public static UserCapabilities refreshDirectoryFor(@NonNull Context context,
@Nullable MasterSecret masterSecret,
@NonNull Recipients recipients)
@NonNull Recipient recipient)
throws IOException
{
TextSecureDirectory directory = TextSecureDirectory.getInstance(context);
SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context);
String number = recipients.getPrimaryRecipient().getAddress().serialize();
String number = recipient.getAddress().serialize();
Optional<ContactTokenDetails> details = accountManager.getContact(number);
if (details.isPresent()) {
@@ -156,10 +156,10 @@ public class DirectoryHelper {
}
public static @NonNull UserCapabilities getUserCapabilities(@NonNull Context context,
@Nullable Recipients recipients)
@Nullable Recipient recipient)
{
try {
if (recipients == null) {
if (recipient == null) {
return UserCapabilities.UNSUPPORTED;
}
@@ -167,15 +167,15 @@ public class DirectoryHelper {
return UserCapabilities.UNSUPPORTED;
}
if (!recipients.isSingleRecipient()) {
if (recipient.isMmsGroupRecipient()) {
return UserCapabilities.UNSUPPORTED;
}
if (recipients.isGroupRecipient()) {
if (recipient.isPushGroupRecipient()) {
return new UserCapabilities(Capability.SUPPORTED, Capability.UNSUPPORTED, Capability.UNSUPPORTED);
}
final Address address = recipients.getPrimaryRecipient().getAddress();
final Address address = recipient.getAddress();
boolean secureText = TextSecureDirectory.getInstance(context).isSecureTextSupported(address);

View File

@@ -9,7 +9,7 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import java.io.IOException;
import java.util.LinkedList;
@@ -19,11 +19,12 @@ import static org.whispersystems.signalservice.internal.push.SignalServiceProtos
public class GroupUtil {
private static final String ENCODED_GROUP_PREFIX = "__textsecure_group__!";
private static final String ENCODED_SIGNAL_GROUP_PREFIX = "__textsecure_group__!";
private static final String ENCODED_MMS_GROUP_PREFIX = "__signal_mms_group__!";
private static final String TAG = GroupUtil.class.getSimpleName();
public static String getEncodedId(byte[] groupId) {
return ENCODED_GROUP_PREFIX + Hex.toStringCondensed(groupId);
public static String getEncodedId(byte[] groupId, boolean mms) {
return mms ? ENCODED_MMS_GROUP_PREFIX : ENCODED_SIGNAL_GROUP_PREFIX + Hex.toStringCondensed(groupId);
}
public static byte[] getDecodedId(String groupId) throws IOException {
@@ -35,7 +36,11 @@ public class GroupUtil {
}
public static boolean isEncodedGroup(@NonNull String groupId) {
return groupId.startsWith(ENCODED_GROUP_PREFIX);
return groupId.startsWith(ENCODED_SIGNAL_GROUP_PREFIX) || groupId.startsWith(ENCODED_MMS_GROUP_PREFIX);
}
public static boolean isMmsGroup(@NonNull String groupId) {
return groupId.startsWith(ENCODED_MMS_GROUP_PREFIX);
}
public static @NonNull GroupDescription getDescription(@NonNull Context context, @Nullable String encodedGroup) {
@@ -56,7 +61,7 @@ public class GroupUtil {
@NonNull private final Context context;
@Nullable private final GroupContext groupContext;
@Nullable private final Recipients members;
@Nullable private final List<Recipient> members;
public GroupDescription(@NonNull Context context, @Nullable GroupContext groupContext) {
this.context = context.getApplicationContext();
@@ -65,13 +70,11 @@ public class GroupUtil {
if (groupContext == null || groupContext.getMembersList().isEmpty()) {
this.members = null;
} else {
List<Address> adddresses = new LinkedList<>();
this.members = new LinkedList<>();
for (String member : groupContext.getMembersList()) {
adddresses.add(Address.fromExternal(context, member));
this.members.add(RecipientFactory.getRecipientFor(context, Address.fromExternal(context, member), true));
}
this.members = RecipientFactory.getRecipientsFor(context, adddresses.toArray(new Address[0]), true);
}
}
@@ -88,7 +91,7 @@ public class GroupUtil {
if (members != null) {
description.append("\n");
description.append(context.getResources().getQuantityString(R.plurals.GroupUtil_joined_the_group,
members.getRecipientsList().size(), members.toShortString()));
members.size(), toString(members)));
}
if (title != null && !title.trim().isEmpty()) {
@@ -100,10 +103,25 @@ public class GroupUtil {
return description.toString();
}
public void addListener(Recipients.RecipientsModifiedListener listener) {
public void addListener(RecipientModifiedListener listener) {
if (this.members != null) {
this.members.addListener(listener);
for (Recipient member : this.members) {
member.addListener(listener);
}
}
}
private String toString(List<Recipient> recipients) {
String result = "";
for (int i=0;i<recipients.size();i++) {
result += recipients.get(i).toShortString();
if (i != recipients.size() -1 )
result += ", ";
}
return result;
}
}
}

View File

@@ -22,7 +22,6 @@ import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.sms.IncomingIdentityDefaultMessage;
import org.thoughtcrime.securesms.sms.IncomingIdentityUpdateMessage;
import org.thoughtcrime.securesms.sms.IncomingIdentityVerifiedMessage;
@@ -75,13 +74,12 @@ public class IdentityUtil {
long time = System.currentTimeMillis();
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
Recipients recipients = RecipientFactory.getRecipientsFor(context, recipient, true);
GroupDatabase.Reader reader = groupDatabase.getGroups();
GroupDatabase.GroupRecord groupRecord;
while ((groupRecord = reader.getNext()) != null) {
if (groupRecord.getMembers().contains(recipient.getAddress()) && groupRecord.isActive()) {
if (groupRecord.getMembers().contains(recipient.getAddress()) && groupRecord.isActive() && !groupRecord.isMms()) {
SignalServiceGroup group = new SignalServiceGroup(groupRecord.getId());
if (remote) {
@@ -92,12 +90,12 @@ public class IdentityUtil {
smsDatabase.insertMessageInbox(incoming);
} else {
Recipients groupRecipients = RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromSerialized(GroupUtil.getEncodedId(group.getGroupId()))}, true);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipients);
Recipient groupRecipient = RecipientFactory.getRecipientFor(context, Address.fromSerialized(GroupUtil.getEncodedId(group.getGroupId(), false)), true);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
OutgoingTextMessage outgoing ;
if (verified) outgoing = new OutgoingIdentityVerifiedMessage(recipients);
else outgoing = new OutgoingIdentityDefaultMessage(recipients);
if (verified) outgoing = new OutgoingIdentityVerifiedMessage(recipient);
else outgoing = new OutgoingIdentityDefaultMessage(recipient);
DatabaseFactory.getEncryptingSmsDatabase(context).insertMessageOutbox(masterSecret, threadId, outgoing, false, time, null);
}
@@ -114,10 +112,10 @@ public class IdentityUtil {
} else {
OutgoingTextMessage outgoing;
if (verified) outgoing = new OutgoingIdentityVerifiedMessage(recipients);
else outgoing = new OutgoingIdentityDefaultMessage(recipients);
if (verified) outgoing = new OutgoingIdentityVerifiedMessage(recipient);
else outgoing = new OutgoingIdentityDefaultMessage(recipient);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
Log.w(TAG, "Inserting verified outbox...");
DatabaseFactory.getEncryptingSmsDatabase(context)