Add storage sync support for linked devices.

fork-5.53.8
Cody Henthorne 2022-01-21 16:19:17 -05:00 zatwierdzone przez Greyson Parrelli
rodzic 4f03c98f60
commit 22c396067d
15 zmienionych plików z 72 dodań i 24 usunięć

Wyświetl plik

@ -103,13 +103,13 @@ class ExpireTimerSettingsFragment : DSLSettingsFragment(
val values: Array<Int> = resources.getIntArray(R.array.ExpireTimerSettingsFragment__values).toTypedArray()
var hasCustomValue = true
labels.zip(values).forEach { (label, value) ->
labels.zip(values).forEach { (label, seconds) ->
radioPref(
title = DSLSettingsText.from(label),
isChecked = state.currentTimer == value,
onClick = { viewModel.select(value) }
isChecked = state.currentTimer == seconds,
onClick = { viewModel.select(seconds) }
)
hasCustomValue = hasCustomValue && state.currentTimer != value
hasCustomValue = hasCustomValue && state.currentTimer != seconds
}
radioPref(

Wyświetl plik

@ -8,10 +8,12 @@ import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.groups.GroupChangeException
import org.thoughtcrime.securesms.groups.GroupManager
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.sms.MessageSender
import org.thoughtcrime.securesms.storage.StorageSyncHelper
import java.io.IOException
private val TAG: String = Log.tag(ExpireTimerSettingsRepository::class.java)
@ -44,6 +46,15 @@ class ExpireTimerSettingsRepository(val context: Context) {
}
}
fun setUniversalExpireTimerSeconds(newExpirationTime: Int, onDone: () -> Unit) {
SignalExecutors.BOUNDED.execute {
SignalStore.settings().universalExpireTimer = newExpirationTime
SignalDatabase.recipients.markNeedsSync(Recipient.self().id)
StorageSyncHelper.scheduleSyncForDataChange()
onDone.invoke()
}
}
@WorkerThread
private fun getThreadId(recipientId: RecipientId): Long {
val threadDatabase: ThreadDatabase = SignalDatabase.threads

Wyświetl plik

@ -45,8 +45,9 @@ class ExpireTimerSettingsViewModel(val config: Config, private val repository: E
} else if (config.forResultMode) {
store.update { it.copy(saveState = ProcessState.Success(userSetTimer)) }
} else {
SignalStore.settings().universalExpireTimer = userSetTimer
store.update { it.copy(saveState = ProcessState.Success(userSetTimer)) }
repository.setUniversalExpireTimerSeconds(userSetTimer) {
store.update { it.copy(saveState = ProcessState.Success(userSetTimer)) }
}
}
}

Wyświetl plik

@ -4,6 +4,7 @@ import android.content.Context;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.IdentityKeyPair;

Wyświetl plik

@ -9,6 +9,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.net.NotPushRegisteredException;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@ -94,6 +95,11 @@ public class MultiDeviceConfigurationUpdateJob extends BaseJob {
return;
}
if (SignalStore.account().isLinkedDevice()) {
Log.i(TAG, "Not primary device, aborting...");
return;
}
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
messageSender.sendSyncMessage(SignalServiceSyncMessage.forConfiguration(new ConfigurationMessage(Optional.of(readReceiptsEnabled),
Optional.of(unidentifiedDeliveryIndicatorsEnabled),

Wyświetl plik

@ -50,7 +50,7 @@ class MultiDeviceContactSyncJob(parameters: Parameters, private val attachmentPo
}
if (SignalStore.account().isPrimaryDevice) {
Log.i(TAG, "Sync jobs are for linked devices only")
Log.i(TAG, "Not linked device, aborting...")
return
}

Wyświetl plik

@ -126,6 +126,11 @@ public class MultiDeviceContactUpdateJob extends BaseJob {
return;
}
if (SignalStore.account().isLinkedDevice()) {
Log.i(TAG, "Not primary device, aborting...");
return;
}
if (recipientId == null) generateFullContactUpdate();
else generateSingleContactUpdate(recipientId);
}

Wyświetl plik

@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.net.NotPushRegisteredException;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
import org.thoughtcrime.securesms.providers.BlobProvider;
@ -82,6 +83,11 @@ public class MultiDeviceGroupUpdateJob extends BaseJob {
return;
}
if (SignalStore.account().isLinkedDevice()) {
Log.i(TAG, "Not primary device, aborting...");
return;
}
ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pipe[0]);
Uri uri = BlobProvider.getInstance()

Wyświetl plik

@ -65,6 +65,11 @@ public class MultiDeviceKeysUpdateJob extends BaseJob {
return;
}
if (SignalStore.account().isLinkedDevice()) {
Log.i(TAG, "Not primary device, aborting...");
return;
}
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
StorageKey storageServiceKey = SignalStore.storageService().getOrCreateStorageKey();

Wyświetl plik

@ -99,7 +99,7 @@ public class RefreshOwnProfileJob extends BaseJob {
return;
}
if (!SignalStore.registrationValues().hasUploadedProfile()) {
if (!SignalStore.registrationValues().hasUploadedProfile() && SignalStore.account().isPrimaryDevice()) {
Log.i(TAG, "Registered but haven't uploaded profile yet.");
return;
}

Wyświetl plik

@ -71,6 +71,11 @@ public class StorageForcePushJob extends BaseJob {
@Override
protected void onRun() throws IOException, RetryLaterException {
if (SignalStore.account().isLinkedDevice()) {
Log.i(TAG, "Only the primary device can force push");
return;
}
StorageKey storageServiceKey = SignalStore.storageService().getOrCreateStorageKey();
SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
RecipientDatabase recipientDatabase = SignalDatabase.recipients();

Wyświetl plik

@ -9,6 +9,7 @@ import com.annimon.stream.Stream;
import net.zetetic.database.sqlcipher.SQLiteDatabase;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.model.RecipientRecord;
import org.thoughtcrime.securesms.database.SignalDatabase;
@ -37,6 +38,9 @@ import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage;
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
@ -47,6 +51,7 @@ import org.whispersystems.signalservice.api.storage.SignalStorageManifest;
import org.whispersystems.signalservice.api.storage.SignalStorageRecord;
import org.whispersystems.signalservice.api.storage.StorageId;
import org.whispersystems.signalservice.api.storage.StorageKey;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
import org.whispersystems.signalservice.internal.storage.protos.ManifestRecord;
import java.io.IOException;
@ -160,7 +165,7 @@ public class StorageSyncJob extends BaseJob {
}
@Override
protected void onRun() throws IOException, RetryLaterException {
protected void onRun() throws IOException, RetryLaterException, UntrustedIdentityException {
if (!SignalStore.kbsValues().hasPin() && !SignalStore.kbsValues().hasOptedOut()) {
Log.i(TAG, "Doesn't have a PIN. Skipping.");
return;
@ -185,12 +190,18 @@ public class StorageSyncJob extends BaseJob {
SignalStore.storageService().onSyncCompleted();
} catch (InvalidKeyException e) {
Log.w(TAG, "Failed to decrypt remote storage! Force-pushing and syncing the storage key to linked devices.", e);
if (SignalStore.account().isPrimaryDevice()) {
Log.w(TAG, "Failed to decrypt remote storage! Force-pushing and syncing the storage key to linked devices.", e);
ApplicationDependencies.getJobManager().startChain(new MultiDeviceKeysUpdateJob())
.then(new StorageForcePushJob())
.then(new MultiDeviceStorageSyncRequestJob())
.enqueue();
ApplicationDependencies.getJobManager().startChain(new MultiDeviceKeysUpdateJob())
.then(new StorageForcePushJob())
.then(new MultiDeviceStorageSyncRequestJob())
.enqueue();
} else {
Log.w(TAG, "Failed to decrypt remote storage! Requesting new keys from primary.", e);
SignalStore.storageService().clearStorageKeyFromPrimary();
ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(SignalServiceSyncMessage.forRequest(RequestMessage.forType(SignalServiceProtos.SyncMessage.Request.Type.KEYS)), UnidentifiedAccessUtil.getAccessForSync(context));
}
}
}
@ -233,7 +244,7 @@ public class StorageSyncJob extends BaseJob {
List<StorageId> localStorageIdsBeforeMerge = getAllLocalStorageIds(context, self);
IdDifferenceResult idDifference = StorageSyncHelper.findIdDifference(remoteManifest.getStorageIds(), localStorageIdsBeforeMerge);
if (idDifference.hasTypeMismatches()) {
if (idDifference.hasTypeMismatches() && SignalStore.account().isPrimaryDevice()) {
Log.w(TAG, "[Remote Sync] Found type mismatches in the ID sets! Scheduling a force push after this sync completes.");
needsForcePush = true;
}
@ -361,7 +372,7 @@ public class StorageSyncJob extends BaseJob {
Log.i(TAG, "No remote writes needed. Still at version: " + remoteManifest.getVersion());
}
if (needsForcePush) {
if (needsForcePush && SignalStore.account().isPrimaryDevice()) {
Log.w(TAG, "Scheduling a force push.");
ApplicationDependencies.getJobManager().add(new StorageForcePushJob());
}

Wyświetl plik

@ -10,6 +10,7 @@ import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData;
import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.mms.SentMediaQuality;
@ -18,7 +19,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.storage.StorageSyncHelper;
import org.thoughtcrime.securesms.util.SingleLiveEvent;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.webrtc.CallBandwidthMode;
import java.util.Arrays;
@ -377,10 +377,6 @@ public final class SettingsValues extends SignalStoreValues {
public void setUniversalExpireTimer(int seconds) {
putInteger(UNIVERSAL_EXPIRE_TIMER, seconds);
SignalExecutors.BOUNDED.execute(() -> {
SignalDatabase.recipients().markNeedsSync(Recipient.self().getId());
StorageSyncHelper.scheduleSyncForDataChange();
});
}
public int getUniversalExpireTimer() {

Wyświetl plik

@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.subscription.Subscriber;
import org.whispersystems.libsignal.util.guava.Optional;
@ -105,8 +106,8 @@ public class AccountRecordProcessor extends DefaultStorageRecordProcessor<Signal
AccountRecord.PhoneNumberSharingMode phoneNumberSharingMode = remote.getPhoneNumberSharingMode();
boolean preferContactAvatars = remote.isPreferContactAvatars();
int universalExpireTimer = remote.getUniversalExpireTimer();
boolean primarySendsSms = local.isPrimarySendsSms();
String e164 = local.getE164();
boolean primarySendsSms = SignalStore.account().isPrimaryDevice() ? local.isPrimarySendsSms() : remote.isPrimarySendsSms();
String e164 = SignalStore.account().isPrimaryDevice() ? local.getE164() : remote.getE164();
List<String> defaultReactions = remote.getDefaultReactions().size() > 0 ? remote.getDefaultReactions() : local.getDefaultReactions();
boolean displayBadgesOnProfile = remote.isDisplayBadgesOnProfile();
boolean subscriptionManuallyCancelled = remote.isSubscriptionManuallyCancelled();

Wyświetl plik

@ -10,7 +10,7 @@ import java.io.Closeable;
*/
public interface SignalServiceDataStore extends SignalProtocolStore, SignalServiceSessionStore, SignalServiceSenderKeyStore {
/**
* @return True if the active account has linked devices, otherwise false.
* @return True if the active account has or is a linked device, otherwise false.
*/
boolean isMultiDevice();