From 96e888a4f5cea4b8f1097f415b767f215e78258b Mon Sep 17 00:00:00 2001 From: Alan Evans Date: Tue, 7 Jul 2020 12:00:29 -0300 Subject: [PATCH] Remove versioned profiles feature flag. --- .../securesms/jobs/JobManagerFactories.java | 2 + .../securesms/jobs/ProfileUploadJob.java | 19 ++----- .../securesms/jobs/RefreshOwnProfileJob.java | 3 +- .../securesms/jobs/RetrieveProfileJob.java | 2 +- .../securesms/jobs/RotateProfileKeyJob.java | 16 ++---- .../migrations/ApplicationMigrations.java | 9 ++- .../migrations/ProfileMigrationJob.java | 55 +++++++++++++++++++ .../securesms/util/FeatureFlags.java | 20 +------ .../signalservice/FeatureFlags.java | 11 ---- .../api/SignalServiceAccountManager.java | 34 ------------ .../api/profiles/SignalServiceProfile.java | 1 - .../internal/push/PushServiceSocket.java | 40 -------------- 12 files changed, 76 insertions(+), 136 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/migrations/ProfileMigrationJob.java delete mode 100644 libsignal/service/src/main/java/org/whispersystems/signalservice/FeatureFlags.java 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 f10fe4de42..a5674d14ec 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java @@ -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()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ProfileUploadJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/ProfileUploadJob.java index d531872c96..c62e3362c3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ProfileUploadJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ProfileUploadJob.java @@ -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 { - @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); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshOwnProfileJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshOwnProfileJob.java index 7827480d29..92a972fa3c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshOwnProfileJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshOwnProfileJob.java @@ -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; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java index 653bf8ab9f..388b195a89 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java @@ -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; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RotateProfileKeyJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RotateProfileKeyJob.java index a6312e2529..fc7117e80a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RotateProfileKeyJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RotateProfileKeyJob.java @@ -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()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java index b25df7692c..1ce47b72ed 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java +++ b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java @@ -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; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/migrations/ProfileMigrationJob.java b/app/src/main/java/org/thoughtcrime/securesms/migrations/ProfileMigrationJob.java new file mode 100644 index 0000000000..b2fc63a72c --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/migrations/ProfileMigrationJob.java @@ -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 { + @Override + public @NonNull ProfileMigrationJob create(@NonNull Parameters parameters, @NonNull Data data) { + return new ProfileMigrationJob(parameters); + } + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java index 23810ec5b6..918444ed74 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java @@ -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 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 FLAG_CHANGE_LISTENERS = new HashMap() {{ - 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. */ diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/FeatureFlags.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/FeatureFlags.java deleted file mode 100644 index f324922f1d..0000000000 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/FeatureFlags.java +++ /dev/null @@ -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; -} diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java index 0111e53f28..b51dd46055 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java @@ -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 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. */ diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/profiles/SignalServiceProfile.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/profiles/SignalServiceProfile.java index 9f87fd9fea..93ee98a8f6 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/profiles/SignalServiceProfile.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/profiles/SignalServiceProfile.java @@ -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; diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java index 03424cabe2..c7133e10e2 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java @@ -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 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. */