Add GV2 recipient capability.

master
Alan Evans 2020-02-14 12:00:32 -04:00 committed by Greyson Parrelli
parent 82305ce2b3
commit 172a43679d
7 changed files with 74 additions and 8 deletions

View File

@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
import org.whispersystems.signalservice.api.storage.SignalGroupV1Record;
@ -91,6 +92,7 @@ public class RecipientDatabase extends Database {
private static final String UNIDENTIFIED_ACCESS_MODE = "unidentified_access_mode";
private static final String FORCE_SMS_SELECTION = "force_sms_selection";
private static final String UUID_SUPPORTED = "uuid_supported";
private static final String GROUPS_V2_CAPABILITY = "gv2_capability";
private static final String STORAGE_SERVICE_KEY = "storage_service_key";
private static final String DIRTY = "dirty";
private static final String PROFILE_GIVEN_NAME = "signal_profile_name";
@ -110,7 +112,9 @@ public class RecipientDatabase extends Database {
SYSTEM_DISPLAY_NAME, SYSTEM_PHOTO_URI, SYSTEM_PHONE_LABEL, SYSTEM_PHONE_TYPE, SYSTEM_CONTACT_URI,
PROFILE_GIVEN_NAME, PROFILE_FAMILY_NAME, SIGNAL_PROFILE_AVATAR, PROFILE_SHARING, NOTIFICATION_CHANNEL,
UNIDENTIFIED_ACCESS_MODE,
FORCE_SMS_SELECTION, UUID_SUPPORTED, STORAGE_SERVICE_KEY, DIRTY
FORCE_SMS_SELECTION,
UUID_SUPPORTED, GROUPS_V2_CAPABILITY,
STORAGE_SERVICE_KEY, DIRTY
};
private static final String[] RECIPIENT_FULL_PROJECTION = ArrayUtils.concat(
@ -278,6 +282,7 @@ public class RecipientDatabase extends Database {
UNIDENTIFIED_ACCESS_MODE + " INTEGER DEFAULT 0, " +
FORCE_SMS_SELECTION + " INTEGER DEFAULT 0, " +
UUID_SUPPORTED + " INTEGER DEFAULT 0, " +
GROUPS_V2_CAPABILITY + " INTEGER DEFAULT " + Recipient.Capability.UNKNOWN.serialize() + ", " +
STORAGE_SERVICE_KEY + " TEXT UNIQUE DEFAULT NULL, " +
DIRTY + " INTEGER DEFAULT " + DirtyState.CLEAN.getId() + ");";
@ -693,6 +698,7 @@ public class RecipientDatabase extends Database {
int unidentifiedAccessMode = cursor.getInt(cursor.getColumnIndexOrThrow(UNIDENTIFIED_ACCESS_MODE));
boolean forceSmsSelection = cursor.getInt(cursor.getColumnIndexOrThrow(FORCE_SMS_SELECTION)) == 1;
boolean uuidSupported = cursor.getInt(cursor.getColumnIndexOrThrow(UUID_SUPPORTED)) == 1;
int gv2SupportedValue = cursor.getInt(cursor.getColumnIndexOrThrow(GROUPS_V2_CAPABILITY));
String storageKeyRaw = cursor.getString(cursor.getColumnIndexOrThrow(STORAGE_SERVICE_KEY));
String identityKeyRaw = cursor.getString(cursor.getColumnIndexOrThrow(IDENTITY_KEY));
int identityStatusRaw = cursor.getInt(cursor.getColumnIndexOrThrow(IDENTITY_STATUS));
@ -742,7 +748,9 @@ public class RecipientDatabase extends Database {
systemPhoneLabel, systemContactUri,
ProfileName.fromParts(profileGivenName, profileFamilyName), signalProfileAvatar, profileSharing,
notificationChannel, UnidentifiedAccessMode.fromMode(unidentifiedAccessMode),
forceSmsSelection, uuidSupported, InsightsBannerTier.fromId(insightsBannerTier),
forceSmsSelection,
uuidSupported, Recipient.Capability.deserialize(gv2SupportedValue),
InsightsBannerTier.fromId(insightsBannerTier),
storageKey, identityKey, identityStatus);
}
@ -870,9 +878,10 @@ public class RecipientDatabase extends Database {
Recipient.live(id).refresh();
}
public void setUuidSupported(@NonNull RecipientId id, boolean supported) {
ContentValues values = new ContentValues(1);
values.put(UUID_SUPPORTED, supported ? "1" : "0");
public void setCapabilities(@NonNull RecipientId id, @NonNull SignalServiceProfile.Capabilities capabilities) {
ContentValues values = new ContentValues(2);
values.put(UUID_SUPPORTED, capabilities.isUuid() ? "1" : "0");
values.put(GROUPS_V2_CAPABILITY, Recipient.Capability.fromBoolean(capabilities.isGv2()).serialize());
update(id, values);
Recipient.live(id).refresh();
}
@ -1578,6 +1587,7 @@ public class RecipientDatabase extends Database {
private final UnidentifiedAccessMode unidentifiedAccessMode;
private final boolean forceSmsSelection;
private final boolean uuidSupported;
private final Recipient.Capability groupsV2Capability;
private final InsightsBannerTier insightsBannerTier;
private final byte[] storageKey;
private final byte[] identityKey;
@ -1613,6 +1623,7 @@ public class RecipientDatabase extends Database {
@NonNull UnidentifiedAccessMode unidentifiedAccessMode,
boolean forceSmsSelection,
boolean uuidSupported,
Recipient.Capability groupsV2Capability,
@NonNull InsightsBannerTier insightsBannerTier,
@Nullable byte[] storageKey,
@Nullable byte[] identityKey,
@ -1648,6 +1659,7 @@ public class RecipientDatabase extends Database {
this.unidentifiedAccessMode = unidentifiedAccessMode;
this.forceSmsSelection = forceSmsSelection;
this.uuidSupported = uuidSupported;
this.groupsV2Capability = groupsV2Capability;
this.insightsBannerTier = insightsBannerTier;
this.storageKey = storageKey;
this.identityKey = identityKey;
@ -1778,6 +1790,10 @@ public class RecipientDatabase extends Database {
return uuidSupported;
}
public Recipient.Capability getGroupsV2Capability() {
return groupsV2Capability;
}
public @Nullable byte[] getStorageKey() {
return storageKey;
}

View File

@ -113,8 +113,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
private static final int PROFILE_KEY_CREDENTIALS = 48;
private static final int ATTACHMENT_FILE_INDEX = 49;
private static final int STORAGE_SERVICE_ACTIVE = 50;
private static final int GROUPS_V2_RECIPIENT_CAPABILITY = 51;
private static final int DATABASE_VERSION = 50;
private static final int DATABASE_VERSION = 51;
private static final String DATABASE_NAME = "signal.db";
private final Context context;
@ -761,6 +762,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
}
}
if (oldVersion < GROUPS_V2_RECIPIENT_CAPABILITY) {
db.execSQL("ALTER TABLE recipient ADD COLUMN gv2_capability INTEGER DEFAULT 0");
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();

View File

@ -121,7 +121,7 @@ public class RefreshOwnProfileJob extends BaseJob {
return;
}
DatabaseFactory.getRecipientDatabase(context).setUuidSupported(Recipient.self().getId(), capabilities.isUuid());
DatabaseFactory.getRecipientDatabase(context).setCapabilities(Recipient.self().getId(), capabilities);
}
public static final class Factory implements Job.Factory<RefreshOwnProfileJob> {

View File

@ -240,7 +240,7 @@ public class RetrieveProfileJob extends BaseJob {
return;
}
DatabaseFactory.getRecipientDatabase(context).setUuidSupported(recipient.getId(), capabilities.isUuid());
DatabaseFactory.getRecipientDatabase(context).setCapabilities(recipient.getId(), capabilities);
}
public static final class Factory implements Job.Factory<RetrieveProfileJob> {

View File

@ -91,6 +91,7 @@ public class Recipient {
private final UnidentifiedAccessMode unidentifiedAccessMode;
private final boolean forceSmsSelection;
private final boolean uuidSupported;
private final Capability groupsV2Capability;
private final InsightsBannerTier insightsBannerTier;
private final byte[] storageKey;
private final byte[] identityKey;
@ -324,6 +325,7 @@ public class Recipient {
this.unidentifiedAccessMode = UnidentifiedAccessMode.DISABLED;
this.forceSmsSelection = false;
this.uuidSupported = false;
this.groupsV2Capability = Capability.UNKNOWN;
this.storageKey = null;
this.identityKey = null;
this.identityStatus = VerifiedStatus.DEFAULT;
@ -364,6 +366,7 @@ public class Recipient {
this.unidentifiedAccessMode = details.unidentifiedAccessMode;
this.forceSmsSelection = details.forceSmsSelection;
this.uuidSupported = details.uuidSuported;
this.groupsV2Capability = details.groupsV2Capability;
this.storageKey = details.storageKey;
this.identityKey = details.identityKey;
this.identityStatus = details.identityStatus;
@ -687,6 +690,10 @@ public class Recipient {
}
}
public Capability getGroupsV2Capability() {
return groupsV2Capability;
}
public @Nullable byte[] getProfileKey() {
return profileKey;
}
@ -762,6 +769,34 @@ public class Recipient {
return id.equals(recipient.id);
}
public enum Capability {
UNKNOWN(0),
SUPPORTED(1),
NOT_SUPPORTED(-1);
private final int value;
Capability(int value) {
this.value = value;
}
public int serialize() {
return value;
}
public static Capability deserialize(int value) {
switch (value) {
case 1 : return SUPPORTED;
case -1 : return NOT_SUPPORTED;
default : return UNKNOWN;
}
}
public static Capability fromBoolean(boolean supported) {
return supported ? SUPPORTED : NOT_SUPPORTED;
}
}
@Override
public int hashCode() {
return Objects.hash(id);

View File

@ -56,6 +56,7 @@ public class RecipientDetails {
final UnidentifiedAccessMode unidentifiedAccessMode;
final boolean forceSmsSelection;
final boolean uuidSuported;
final Recipient.Capability groupsV2Capability;
final InsightsBannerTier insightsBannerTier;
final byte[] storageKey;
final byte[] identityKey;
@ -100,6 +101,7 @@ public class RecipientDetails {
this.unidentifiedAccessMode = settings.getUnidentifiedAccessMode();
this.forceSmsSelection = settings.isForceSmsSelection();
this.uuidSuported = settings.isUuidSupported();
this.groupsV2Capability = settings.getGroupsV2Capability();
this.insightsBannerTier = settings.getInsightsBannerTier();
this.storageKey = settings.getStorageKey();
this.identityKey = settings.getIdentityKey();
@ -146,6 +148,7 @@ public class RecipientDetails {
this.forceSmsSelection = false;
this.name = null;
this.uuidSuported = false;
this.groupsV2Capability = Recipient.Capability.UNKNOWN;
this.storageKey = null;
this.identityKey = null;
this.identityStatus = VerifiedStatus.DEFAULT;

View File

@ -101,11 +101,18 @@ public class SignalServiceProfile {
@JsonProperty
private boolean uuid;
@JsonProperty
private boolean gv2;
public Capabilities() {}
public boolean isUuid() {
return uuid;
}
public boolean isGv2() {
return gv2;
}
}
public ProfileKeyCredentialResponse getProfileKeyCredentialResponse() {