Add routine check to ensure GV2 profiles are up-to-date.

fork-5.53.8
Greyson Parrelli 2022-03-11 09:45:07 -05:00 zatwierdzone przez Cody Henthorne
rodzic c17ba30cfc
commit 3503c60fd1
3 zmienionych plików z 87 dodań i 0 usunięć

Wyświetl plik

@ -53,6 +53,7 @@ import org.thoughtcrime.securesms.jobs.DownloadLatestEmojiDataJob;
import org.thoughtcrime.securesms.jobs.EmojiSearchIndexDownloadJob;
import org.thoughtcrime.securesms.jobs.FcmRefreshJob;
import org.thoughtcrime.securesms.jobs.FontDownloaderJob;
import org.thoughtcrime.securesms.jobs.GroupV2UpdateSelfProfileKeyJob;
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
import org.thoughtcrime.securesms.jobs.ProfileUploadJob;
import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob;
@ -201,6 +202,7 @@ public class ApplicationContext extends MultiDexApplication implements AppForegr
.addPostRender(() -> AndroidTelecomUtil.registerPhoneAccount())
.addPostRender(() -> ApplicationDependencies.getJobManager().add(new FontDownloaderJob()))
.addPostRender(CheckServiceReachabilityJob::enqueueIfNecessary)
.addPostRender(GroupV2UpdateSelfProfileKeyJob::enqueueForGroupsIfNecessary)
.execute();
Log.d(TAG, "onCreate() took " + (System.currentTimeMillis() - startTime) + " ms");

Wyświetl plik

@ -1,8 +1,16 @@
package org.thoughtcrime.securesms.jobs;
import androidx.annotation.AnyThread;
import androidx.annotation.NonNull;
import com.google.protobuf.ByteString;
import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.Log;
import org.signal.storageservice.protos.groups.local.DecryptedMember;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
import org.thoughtcrime.securesms.groups.GroupChangeFailedException;
import org.thoughtcrime.securesms.groups.GroupId;
@ -13,10 +21,17 @@ import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.DecryptionsDrainedConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.groupsv2.NoCredentialForRedemptionTimeException;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
@ -66,6 +81,67 @@ public final class GroupV2UpdateSelfProfileKeyJob extends BaseJob {
groupId);
}
/**
* Updates GV2 groups with the correct profile key if we find any that are out of date. Will run at most once per day.
*/
@AnyThread
public static void enqueueForGroupsIfNecessary() {
if (!SignalStore.account().isRegistered() || SignalStore.account().getAci() == null || !Recipient.self().isRegistered()) {
Log.w(TAG, "Not yet registered!");
return;
}
byte[] rawProfileKey = Recipient.self().getProfileKey();
if (rawProfileKey == null) {
Log.w(TAG, "No profile key set!");
return;
}
ByteString selfProfileKey = ByteString.copyFrom(rawProfileKey);
long timeSinceLastCheck = System.currentTimeMillis() - SignalStore.misc().getLastGv2ProfileCheckTime();
if (timeSinceLastCheck < TimeUnit.DAYS.toMillis(1)) {
Log.d(TAG, "Too soon. Last check was " + timeSinceLastCheck + " ms ago.");
return;
}
Log.i(TAG, "Running routine check.");
SignalStore.misc().setLastGv2ProfileCheckTime(System.currentTimeMillis());
SignalExecutors.BOUNDED.execute(() -> {
boolean foundMismatch = false;
for (GroupId.V2 id : SignalDatabase.groups().getAllGroupV2Ids()) {
Optional<GroupDatabase.GroupRecord> group = SignalDatabase.groups().getGroup(id);
if (!group.isPresent()) {
Log.w(TAG, "Group " + group + " no longer exists?");
continue;
}
ByteString selfUuidBytes = UuidUtil.toByteString(Recipient.self().requireServiceId().uuid());
DecryptedMember selfMember = group.get().requireV2GroupProperties().getDecryptedGroup().getMembersList()
.stream()
.filter(m -> m.getUuid().equals(selfUuidBytes))
.findFirst()
.orElse(null);
if (selfMember != null && !selfMember.getProfileKey().equals(selfProfileKey)) {
Log.w(TAG, "Profile key mismatch for group " + id + " -- enqueueing job");
foundMismatch = true;
ApplicationDependencies.getJobManager().add(GroupV2UpdateSelfProfileKeyJob.withQueueLimits(id));
}
}
if (!foundMismatch) {
Log.i(TAG, "No mismatches found.");
}
});
}
private GroupV2UpdateSelfProfileKeyJob(@NonNull Parameters parameters, @NonNull GroupId.V2 groupId) {
super(parameters);
this.groupId = groupId;

Wyświetl plik

@ -18,6 +18,7 @@ public final class MiscellaneousValues extends SignalStoreValues {
private static final String CHANGE_NUMBER_LOCK = "misc.change_number.lock";
private static final String CENSORSHIP_LAST_CHECK_TIME = "misc.censorship.last_check_time";
private static final String CENSORSHIP_SERVICE_REACHABLE = "misc.censorship.service_reachable";
private static final String LAST_GV2_PROFILE_CHECK_TIME = "misc.last_gv2_profile_check_time";
MiscellaneousValues(@NonNull KeyValueStore store) {
super(store);
@ -128,4 +129,12 @@ public final class MiscellaneousValues extends SignalStoreValues {
public void setServiceReachableWithoutCircumvention(boolean value) {
putBoolean(CENSORSHIP_SERVICE_REACHABLE, value);
}
public long getLastGv2ProfileCheckTime() {
return getLong(LAST_GV2_PROFILE_CHECK_TIME, 0);
}
public void setLastGv2ProfileCheckTime(long value) {
putLong(LAST_GV2_PROFILE_CHECK_TIME, value);
}
}