Only upload your avatar if it's being changed.

New server param means we don't have to upload the avatar if we want to
keep it the same.
fork-5.53.8
Greyson Parrelli 2022-03-14 11:08:17 -04:00 zatwierdzone przez Cody Henthorne
rodzic 87ad4be117
commit b45740884b
4 zmienionych plików z 76 dodań i 31 usunięć

Wyświetl plik

@ -6,20 +6,15 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.google.protobuf.ByteString;
import org.signal.core.util.logging.Log;
import org.signal.storageservice.protos.groups.local.DecryptedMember;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.profiles.ProfileKey;
import org.thoughtcrime.securesms.badges.models.Badge;
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobs.GroupV2UpdateSelfProfileKeyJob;
import org.thoughtcrime.securesms.jobs.MultiDeviceProfileKeyUpdateJob;
@ -44,12 +39,12 @@ import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
import org.whispersystems.signalservice.api.crypto.ProfileCipher;
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
import org.whispersystems.signalservice.api.profiles.AvatarUploadParams;
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.services.ProfileService;
import org.whispersystems.signalservice.api.util.StreamDetails;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.ServiceResponse;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
@ -226,14 +221,12 @@ public final class ProfileUtil {
*/
public static void uploadProfileWithBadges(@NonNull Context context, @NonNull List<Badge> badges) throws IOException {
Log.d(TAG, "uploadProfileWithBadges()");
try (StreamDetails avatar = AvatarHelper.getSelfProfileAvatarStream(context)) {
uploadProfile(Recipient.self().getProfileName(),
Optional.fromNullable(Recipient.self().getAbout()).or(""),
Optional.fromNullable(Recipient.self().getAboutEmoji()).or(""),
getSelfPaymentsAddressProtobuf(),
avatar,
badges);
}
uploadProfile(Recipient.self().getProfileName(),
Optional.fromNullable(Recipient.self().getAbout()).or(""),
Optional.fromNullable(Recipient.self().getAboutEmoji()).or(""),
getSelfPaymentsAddressProtobuf(),
AvatarUploadParams.unchanged(AvatarHelper.hasAvatar(context, Recipient.self().getId())),
badges);
}
/**
@ -248,7 +241,7 @@ public final class ProfileUtil {
Optional.fromNullable(Recipient.self().getAbout()).or(""),
Optional.fromNullable(Recipient.self().getAboutEmoji()).or(""),
getSelfPaymentsAddressProtobuf(),
avatar,
AvatarUploadParams.unchanged(AvatarHelper.hasAvatar(context, Recipient.self().getId())),
Recipient.self().getBadges());
}
}
@ -265,7 +258,7 @@ public final class ProfileUtil {
about,
emoji,
getSelfPaymentsAddressProtobuf(),
avatar,
AvatarUploadParams.unchanged(AvatarHelper.hasAvatar(context, Recipient.self().getId())),
Recipient.self().getBadges());
}
}
@ -291,7 +284,7 @@ public final class ProfileUtil {
Optional.fromNullable(Recipient.self().getAbout()).or(""),
Optional.fromNullable(Recipient.self().getAboutEmoji()).or(""),
getSelfPaymentsAddressProtobuf(),
avatar,
AvatarUploadParams.forAvatar(avatar),
Recipient.self().getBadges());
}
@ -299,7 +292,7 @@ public final class ProfileUtil {
@Nullable String about,
@Nullable String aboutEmoji,
@Nullable SignalServiceProtos.PaymentAddress paymentsAddress,
@Nullable StreamDetails avatar,
@NonNull AvatarUploadParams avatar,
@NonNull List<Badge> badges)
throws IOException
{
@ -312,8 +305,13 @@ public final class ProfileUtil {
Log.d(TAG, "Uploading " + (!Util.isEmpty(about) ? "non-" : "") + "empty about.");
Log.d(TAG, "Uploading " + (!Util.isEmpty(aboutEmoji) ? "non-" : "") + "empty emoji.");
Log.d(TAG, "Uploading " + (paymentsAddress != null ? "non-" : "") + "empty payments address.");
Log.d(TAG, "Uploading " + (avatar != null && avatar.getLength() != 0 ? "non-" : "") + "empty avatar.");
Log.d(TAG, "Uploading " + ((!badgeIds.isEmpty()) ? "non-" : "") + "empty badge list");
Log.d(TAG, "Uploading " + ((!badgeIds.isEmpty()) ? "non-" : "") + "empty badge list.");
if (avatar.keepTheSame) {
Log.d(TAG, "Leaving avatar unchanged. We think we " + (avatar.hasAvatar ? "" : "do not ") + "have one.");
} else {
Log.d(TAG, "Uploading " + (avatar.stream != null && avatar.stream.getLength() != 0 ? "non-" : "") + "empty avatar.");
}
ProfileKey profileKey = ProfileKeyUtil.getSelfProfileKey();
SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
@ -326,7 +324,9 @@ public final class ProfileUtil {
avatar,
badgeIds).orNull();
SignalStore.registrationValues().markHasUploadedProfile();
SignalDatabase.recipients().setProfileAvatar(Recipient.self().getId(), avatarPath);
if (!avatar.keepTheSame) {
SignalDatabase.recipients().setProfileAvatar(Recipient.self().getId(), avatarPath);
}
ApplicationDependencies.getJobManager().add(new RefreshOwnProfileJob());
}

Wyświetl plik

@ -32,6 +32,7 @@ import org.whispersystems.signalservice.api.messages.calls.TurnServerInfo;
import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo;
import org.whispersystems.signalservice.api.messages.multidevice.VerifyDeviceResponse;
import org.whispersystems.signalservice.api.payments.CurrencyConversions;
import org.whispersystems.signalservice.api.profiles.AvatarUploadParams;
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
import org.whispersystems.signalservice.api.profiles.SignalServiceProfileWrite;
import org.whispersystems.signalservice.api.push.ACI;
@ -53,7 +54,6 @@ import org.whispersystems.signalservice.api.storage.StorageId;
import org.whispersystems.signalservice.api.storage.StorageKey;
import org.whispersystems.signalservice.api.storage.StorageManifestKey;
import org.whispersystems.signalservice.api.util.CredentialsProvider;
import org.whispersystems.signalservice.api.util.StreamDetails;
import org.whispersystems.signalservice.internal.ServiceResponse;
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
import org.whispersystems.signalservice.internal.contacts.crypto.ContactDiscoveryCipher;
@ -811,7 +811,7 @@ public class SignalServiceAccountManager {
String about,
String aboutEmoji,
Optional<SignalServiceProtos.PaymentAddress> paymentsAddress,
StreamDetails avatar,
AvatarUploadParams avatar,
List<String> visibleBadgeIds)
throws IOException
{
@ -822,13 +822,12 @@ public class SignalServiceAccountManager {
byte[] ciphertextAbout = profileCipher.encryptString(about, ProfileCipher.getTargetAboutLength(about));
byte[] ciphertextEmoji = profileCipher.encryptString(aboutEmoji, ProfileCipher.EMOJI_PADDED_LENGTH);
byte[] ciphertextMobileCoinAddress = paymentsAddress.transform(address -> profileCipher.encryptWithLength(address.toByteArray(), ProfileCipher.PAYMENTS_ADDRESS_CONTENT_SIZE)).orNull();
boolean hasAvatar = avatar != null;
ProfileAvatarData profileAvatarData = null;
if (hasAvatar) {
profileAvatarData = new ProfileAvatarData(avatar.getStream(),
ProfileCipherOutputStream.getCiphertextLength(avatar.getLength()),
avatar.getContentType(),
if (avatar.stream != null && !avatar.keepTheSame) {
profileAvatarData = new ProfileAvatarData(avatar.stream.getStream(),
ProfileCipherOutputStream.getCiphertextLength(avatar.stream.getLength()),
avatar.stream.getContentType(),
new ProfileCipherOutputStreamFactory(profileKey));
}
@ -837,7 +836,8 @@ public class SignalServiceAccountManager {
ciphertextAbout,
ciphertextEmoji,
ciphertextMobileCoinAddress,
hasAvatar,
avatar.hasAvatar,
avatar.keepTheSame,
profileKey.getCommitment(aci.uuid()).serialize(),
visibleBadgeIds),
profileAvatarData);

Wyświetl plik

@ -0,0 +1,41 @@
package org.whispersystems.signalservice.api.profiles;
import org.whispersystems.signalservice.api.util.StreamDetails;
/**
* A model to represent the attributes of an avatar upload.
*/
public class AvatarUploadParams {
/** Whether or not you should keep the avatar the same on the server. */
public final boolean keepTheSame;
/** Whether or not you want an avatar. */
public final boolean hasAvatar;
/** A stream representing the content of the avatar to be uploaded. */
public final StreamDetails stream;
/**
* Indicates that you want to leave the avatar as it already is on the server.
* @param hasAvatar Whether or not you have an avatar. If true, the avatar you have on the server will remain as it is.
* If this is false, it *will* delete the avatar. Weird to have this with the 'unchanged' bit, I know,
* but this boolean already existed before we added the 'keepTheSame' functionality, so we gotta deal
* with it.
*/
public static AvatarUploadParams unchanged(boolean hasAvatar) {
return new AvatarUploadParams(true, hasAvatar, null);
}
/**
* Indicates that you'd like set the contents of this stream as your avatar. If null, the avatar will be removed.
*/
public static AvatarUploadParams forAvatar(StreamDetails avatarStream) {
return new AvatarUploadParams(false, avatarStream != null, avatarStream);
}
private AvatarUploadParams(boolean keepTheSame, boolean hasAvatar, StreamDetails stream) {
this.keepTheSame = keepTheSame;
this.hasAvatar = hasAvatar;
this.stream = stream;
}
}

Wyświetl plik

@ -25,6 +25,9 @@ public class SignalServiceProfileWrite {
@JsonProperty
private boolean avatar;
@JsonProperty
private boolean sameAvatar;
@JsonProperty
private byte[] commitment;
@ -35,13 +38,14 @@ public class SignalServiceProfileWrite {
public SignalServiceProfileWrite(){
}
public SignalServiceProfileWrite(String version, byte[] name, byte[] about, byte[] aboutEmoji, byte[] paymentAddress, boolean avatar, byte[] commitment, List<String> badgeIds) {
public SignalServiceProfileWrite(String version, byte[] name, byte[] about, byte[] aboutEmoji, byte[] paymentAddress, boolean hasAvatar, boolean sameAvatar, byte[] commitment, List<String> badgeIds) {
this.version = version;
this.name = name;
this.about = about;
this.aboutEmoji = aboutEmoji;
this.paymentAddress = paymentAddress;
this.avatar = avatar;
this.avatar = hasAvatar;
this.sameAvatar = sameAvatar;
this.commitment = commitment;
this.badgeIds = badgeIds;
}