Remove versioned profiles feature flag.
parent
99ff0c1e3c
commit
96e888a4f5
|
@ -31,6 +31,7 @@ import org.thoughtcrime.securesms.migrations.LegacyMigrationJob;
|
|||
import org.thoughtcrime.securesms.migrations.MigrationCompleteJob;
|
||||
import org.thoughtcrime.securesms.migrations.PassingMigrationJob;
|
||||
import org.thoughtcrime.securesms.migrations.PinReminderMigrationJob;
|
||||
import org.thoughtcrime.securesms.migrations.ProfileMigrationJob;
|
||||
import org.thoughtcrime.securesms.migrations.RecipientSearchMigrationJob;
|
||||
import org.thoughtcrime.securesms.migrations.RegistrationPinV2MigrationJob;
|
||||
import org.thoughtcrime.securesms.migrations.StickerAdditionMigrationJob;
|
||||
|
@ -134,6 +135,7 @@ public final class JobManagerFactories {
|
|||
put(StorageCapabilityMigrationJob.KEY, new StorageCapabilityMigrationJob.Factory());
|
||||
put(StorageServiceMigrationJob.KEY, new StorageServiceMigrationJob.Factory());
|
||||
put(UuidMigrationJob.KEY, new UuidMigrationJob.Factory());
|
||||
put(ProfileMigrationJob.KEY, new ProfileMigrationJob.Factory());
|
||||
|
||||
// Dead jobs
|
||||
put(FailingJob.KEY, new FailingJob.Factory());
|
||||
|
|
|
@ -14,12 +14,7 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
|||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||
import org.thoughtcrime.securesms.profiles.ProfileName;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.thoughtcrime.securesms.util.ProfileUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
|
||||
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
|
||||
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||
|
||||
public final class ProfileUploadJob extends BaseJob {
|
||||
|
@ -52,15 +47,10 @@ public final class ProfileUploadJob extends BaseJob {
|
|||
protected void onRun() throws Exception {
|
||||
ProfileKey profileKey = ProfileKeyUtil.getSelfProfileKey();
|
||||
ProfileName profileName = Recipient.self().getProfileName();
|
||||
String avatarPath = null;
|
||||
String avatarPath;
|
||||
|
||||
try (StreamDetails avatar = AvatarHelper.getSelfProfileAvatarStream(context)) {
|
||||
if (FeatureFlags.versionedProfiles()) {
|
||||
avatarPath = accountManager.setVersionedProfile(Recipient.self().getUuid().get(), profileKey, profileName.serialize(), avatar).orNull();
|
||||
} else {
|
||||
accountManager.setProfileName(profileKey, profileName.serialize());
|
||||
avatarPath = accountManager.setProfileAvatar(profileKey, avatar).orNull();
|
||||
}
|
||||
avatarPath = accountManager.setVersionedProfile(Recipient.self().getUuid().get(), profileKey, profileName.serialize(), avatar).orNull();
|
||||
}
|
||||
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileAvatar(Recipient.self().getId(), avatarPath);
|
||||
|
@ -85,11 +75,10 @@ public final class ProfileUploadJob extends BaseJob {
|
|||
public void onFailure() {
|
||||
}
|
||||
|
||||
public static class Factory implements Job.Factory {
|
||||
public static class Factory implements Job.Factory<ProfileUploadJob> {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Job create(@NonNull Parameters parameters, @NonNull Data data) {
|
||||
public @NonNull ProfileUploadJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
||||
return new ProfileUploadJob(parameters);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
|||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.profiles.ProfileName;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.thoughtcrime.securesms.util.ProfileUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
@ -93,7 +92,7 @@ public class RefreshOwnProfileJob extends BaseJob {
|
|||
}
|
||||
|
||||
private static SignalServiceProfile.RequestType getRequestType(@NonNull Recipient recipient) {
|
||||
return FeatureFlags.versionedProfiles() && !recipient.hasProfileKeyCredential()
|
||||
return !recipient.hasProfileKeyCredential()
|
||||
? SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL
|
||||
: SignalServiceProfile.RequestType.PROFILE;
|
||||
}
|
||||
|
|
|
@ -307,7 +307,7 @@ public class RetrieveProfileJob extends BaseJob {
|
|||
}
|
||||
|
||||
private static SignalServiceProfile.RequestType getRequestType(@NonNull Recipient recipient) {
|
||||
return FeatureFlags.versionedProfiles() && !recipient.hasProfileKeyCredential()
|
||||
return !recipient.hasProfileKeyCredential()
|
||||
? SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL
|
||||
: SignalServiceProfile.RequestType.PROFILE;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import org.thoughtcrime.securesms.jobmanager.Job;
|
|||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||
|
@ -57,16 +56,11 @@ public class RotateProfileKeyJob extends BaseJob {
|
|||
recipientDatabase.setProfileKey(self.getId(), profileKey);
|
||||
|
||||
try (StreamDetails avatarStream = AvatarHelper.getSelfProfileAvatarStream(context)) {
|
||||
if (FeatureFlags.versionedProfiles()) {
|
||||
accountManager.setVersionedProfile(self.getUuid().get(),
|
||||
profileKey,
|
||||
Recipient.self().getProfileName().serialize(),
|
||||
avatarStream);
|
||||
} else {
|
||||
accountManager.setProfileName(profileKey, Recipient.self().getProfileName().serialize());
|
||||
accountManager.setProfileAvatar(profileKey, avatarStream);
|
||||
}
|
||||
}
|
||||
accountManager.setVersionedProfile(self.getUuid().get(),
|
||||
profileKey,
|
||||
Recipient.self().getProfileName().serialize(),
|
||||
avatarStream);
|
||||
}
|
||||
|
||||
ApplicationDependencies.getJobManager().add(new RefreshAttributesJob());
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ public class ApplicationMigrations {
|
|||
|
||||
private static final int LEGACY_CANONICAL_VERSION = 455;
|
||||
|
||||
public static final int CURRENT_VERSION = 15;
|
||||
public static final int CURRENT_VERSION = 16;
|
||||
|
||||
private static final class Version {
|
||||
static final int LEGACY = 1;
|
||||
|
@ -53,10 +53,11 @@ public class ApplicationMigrations {
|
|||
//static final int TEST_ARGON2 = 9;
|
||||
static final int SWOON_STICKERS = 10;
|
||||
static final int STORAGE_SERVICE = 11;
|
||||
static final int STORAGE_KEY_ROTATE = 12;
|
||||
//static final int STORAGE_KEY_ROTATE = 12;
|
||||
static final int REMOVE_AVATAR_ID = 13;
|
||||
static final int STORAGE_CAPABILITY = 14;
|
||||
static final int PIN_REMINDER = 15;
|
||||
static final int VERSIONED_PROFILE = 16;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -231,6 +232,10 @@ public class ApplicationMigrations {
|
|||
jobs.put(Version.PIN_REMINDER, new PinReminderMigrationJob());
|
||||
}
|
||||
|
||||
if (lastSeenVersion < Version.VERSIONED_PROFILE) {
|
||||
jobs.put(Version.VERSIONED_PROFILE, new ProfileMigrationJob());
|
||||
}
|
||||
|
||||
return jobs;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package org.thoughtcrime.securesms.migrations;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobs.ProfileUploadJob;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
|
||||
/**
|
||||
* Schedules a re-upload of the users profile.
|
||||
*/
|
||||
public final class ProfileMigrationJob extends MigrationJob {
|
||||
|
||||
private static final String TAG = Log.tag(ProfileMigrationJob.class);
|
||||
|
||||
public static final String KEY = "ProfileMigrationJob";
|
||||
|
||||
ProfileMigrationJob() {
|
||||
this(new Parameters.Builder().build());
|
||||
}
|
||||
|
||||
private ProfileMigrationJob(@NonNull Parameters parameters) {
|
||||
super(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUiBlocking() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String getFactoryKey() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performMigration() {
|
||||
Log.i(TAG, "Scheduling profile upload job");
|
||||
ApplicationDependencies.getJobManager().add(new ProfileUploadJob());
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean shouldRetry(@NonNull Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class Factory implements Job.Factory<ProfileMigrationJob> {
|
||||
@Override
|
||||
public @NonNull ProfileMigrationJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
||||
return new ProfileMigrationJob(parameters);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,6 @@ import com.google.android.collect.Sets;
|
|||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.jobs.ProfileUploadJob;
|
||||
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
|
||||
import org.thoughtcrime.securesms.jobs.RefreshOwnProfileJob;
|
||||
import org.thoughtcrime.securesms.jobs.RemoteConfigRefreshJob;
|
||||
|
@ -55,8 +54,6 @@ public final class FeatureFlags {
|
|||
private static final String REMOTE_DELETE = "android.remoteDelete";
|
||||
private static final String PROFILE_FOR_CALLING = "android.profileForCalling.2";
|
||||
private static final String CALLING_PIP = "android.callingPip";
|
||||
private static final String VERSIONED_PROFILES_1 = "android.versionedProfiles";
|
||||
private static final String VERSIONED_PROFILES_2 = "android.versionedProfiles.2";
|
||||
private static final String GROUPS_V2 = "android.groupsv2";
|
||||
private static final String GROUPS_V2_CREATE = "android.groupsv2.create";
|
||||
private static final String GROUPS_V2_CAPACITY = "android.groupsv2.capacity";
|
||||
|
@ -73,8 +70,6 @@ public final class FeatureFlags {
|
|||
REMOTE_DELETE,
|
||||
PROFILE_FOR_CALLING,
|
||||
CALLING_PIP,
|
||||
VERSIONED_PROFILES_1,
|
||||
VERSIONED_PROFILES_2,
|
||||
GROUPS_V2,
|
||||
GROUPS_V2_CREATE,
|
||||
GROUPS_V2_CAPACITY,
|
||||
|
@ -106,8 +101,6 @@ public final class FeatureFlags {
|
|||
* Flags in this set will stay true forever once they receive a true value from a remote config.
|
||||
*/
|
||||
private static final Set<String> STICKY = Sets.newHashSet(
|
||||
VERSIONED_PROFILES_1,
|
||||
VERSIONED_PROFILES_2,
|
||||
GROUPS_V2
|
||||
);
|
||||
|
||||
|
@ -123,11 +116,6 @@ public final class FeatureFlags {
|
|||
* desired test state.
|
||||
*/
|
||||
private static final Map<String, OnFlagChange> FLAG_CHANGE_LISTENERS = new HashMap<String, OnFlagChange>() {{
|
||||
put(VERSIONED_PROFILES_2, (change) -> {
|
||||
if (change == Change.ENABLED) {
|
||||
ApplicationDependencies.getJobManager().add(new ProfileUploadJob());
|
||||
}
|
||||
});
|
||||
put(GROUPS_V2, (change) -> {
|
||||
if (change == Change.ENABLED) {
|
||||
ApplicationDependencies.getJobManager().startChain(new RefreshAttributesJob())
|
||||
|
@ -214,15 +202,9 @@ public final class FeatureFlags {
|
|||
return getBoolean(CALLING_PIP, false);
|
||||
}
|
||||
|
||||
/** Read and write versioned profile information. */
|
||||
public static boolean versionedProfiles() {
|
||||
return getBoolean(VERSIONED_PROFILES_1, false) ||
|
||||
getBoolean(VERSIONED_PROFILES_2, false);
|
||||
}
|
||||
|
||||
/** Groups v2 send and receive. */
|
||||
public static boolean groupsV2() {
|
||||
return versionedProfiles() && getBoolean(GROUPS_V2, false);
|
||||
return getBoolean(GROUPS_V2, false);
|
||||
}
|
||||
|
||||
/** Groups v2 send and receive. */
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package org.whispersystems.signalservice;
|
||||
|
||||
/**
|
||||
* A location for constants that allows us to turn features on and off at the service level during development.
|
||||
* After a feature has been launched, the flag should be removed.
|
||||
*/
|
||||
public final class FeatureFlags {
|
||||
|
||||
/** Prevent usage of non-versioned profile endpoints. */
|
||||
public static final boolean DISALLOW_OLD_PROFILE_SETTING = false;
|
||||
}
|
|
@ -20,7 +20,6 @@ import org.whispersystems.libsignal.logging.Log;
|
|||
import org.whispersystems.libsignal.state.PreKeyRecord;
|
||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.FeatureFlags;
|
||||
import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
|
||||
import org.whispersystems.signalservice.api.crypto.ProfileCipher;
|
||||
import org.whispersystems.signalservice.api.crypto.ProfileCipherOutputStream;
|
||||
|
@ -629,39 +628,6 @@ public class SignalServiceAccountManager {
|
|||
return this.pushServiceSocket.getTurnServerInfo();
|
||||
}
|
||||
|
||||
public void setProfileName(ProfileKey key, String name)
|
||||
throws IOException
|
||||
{
|
||||
if (FeatureFlags.DISALLOW_OLD_PROFILE_SETTING) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
if (name == null) name = "";
|
||||
|
||||
String ciphertextName = Base64.encodeBytesWithoutPadding(new ProfileCipher(key).encryptName(name.getBytes(StandardCharsets.UTF_8), ProfileCipher.NAME_PADDED_LENGTH));
|
||||
|
||||
this.pushServiceSocket.setProfileName(ciphertextName);
|
||||
}
|
||||
|
||||
public Optional<String> setProfileAvatar(ProfileKey key, StreamDetails avatar)
|
||||
throws IOException
|
||||
{
|
||||
if (FeatureFlags.DISALLOW_OLD_PROFILE_SETTING) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
ProfileAvatarData profileAvatarData = null;
|
||||
|
||||
if (avatar != null) {
|
||||
profileAvatarData = new ProfileAvatarData(avatar.getStream(),
|
||||
ProfileCipherOutputStream.getCiphertextLength(avatar.getLength()),
|
||||
avatar.getContentType(),
|
||||
new ProfileCipherOutputStreamFactory(key));
|
||||
}
|
||||
|
||||
return this.pushServiceSocket.setProfileAvatar(profileAvatarData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The avatar URL path, if one was written.
|
||||
*/
|
||||
|
|
|
@ -10,7 +10,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
|||
import org.signal.zkgroup.InvalidInputException;
|
||||
import org.signal.zkgroup.profiles.ProfileKeyCredentialResponse;
|
||||
import org.whispersystems.libsignal.logging.Log;
|
||||
import org.whispersystems.signalservice.FeatureFlags;
|
||||
import org.whispersystems.signalservice.internal.util.JsonUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.whispersystems.libsignal.state.PreKeyRecord;
|
|||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.FeatureFlags;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
|
||||
import org.whispersystems.signalservice.api.groupsv2.CredentialResponse;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString;
|
||||
|
@ -691,45 +690,6 @@ public class PushServiceSocket {
|
|||
}
|
||||
}
|
||||
|
||||
public void setProfileName(String name) throws NonSuccessfulResponseCodeException, PushNetworkException {
|
||||
if (FeatureFlags.DISALLOW_OLD_PROFILE_SETTING) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
makeServiceRequest(String.format(PROFILE_PATH, "name/" + (name == null ? "" : URLEncoder.encode(name))), "PUT", "");
|
||||
}
|
||||
|
||||
public Optional<String> setProfileAvatar(ProfileAvatarData profileAvatar)
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException
|
||||
{
|
||||
if (FeatureFlags.DISALLOW_OLD_PROFILE_SETTING) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
String response = makeServiceRequest(String.format(PROFILE_PATH, "form/avatar"), "GET", null);
|
||||
ProfileAvatarUploadAttributes formAttributes;
|
||||
|
||||
try {
|
||||
formAttributes = JsonUtil.fromJson(response, ProfileAvatarUploadAttributes.class);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
throw new NonSuccessfulResponseCodeException("Unable to parse entity");
|
||||
}
|
||||
|
||||
if (profileAvatar != null) {
|
||||
uploadToCdn0(AVATAR_UPLOAD_PATH, formAttributes.getAcl(), formAttributes.getKey(),
|
||||
formAttributes.getPolicy(), formAttributes.getAlgorithm(),
|
||||
formAttributes.getCredential(), formAttributes.getDate(),
|
||||
formAttributes.getSignature(), profileAvatar.getData(),
|
||||
profileAvatar.getContentType(), profileAvatar.getDataLength(),
|
||||
profileAvatar.getOutputStreamFactory(), null, null);
|
||||
|
||||
return Optional.of(formAttributes.getKey());
|
||||
}
|
||||
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The avatar URL path, if one was written.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue