Add the ability to have separate ACI and PNI protocol stores.

This commit is contained in:
Greyson Parrelli
2022-01-26 16:22:19 -05:00
committed by Cody Henthorne
parent dd7a2834bc
commit 33f4bb0000
33 changed files with 204 additions and 188 deletions
@@ -40,7 +40,7 @@ public class UntrustedSendDialog extends AlertDialog.Builder implements DialogIn
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
final TextSecureIdentityKeyStore identityStore = ApplicationDependencies.getIdentityStore(); final TextSecureIdentityKeyStore identityStore = ApplicationDependencies.getProtocolStore().aci().identities();
SimpleTask.run(() -> { SimpleTask.run(() -> {
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) { try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
@@ -43,9 +43,9 @@ public class UnverifiedSendDialog extends AlertDialog.Builder implements DialogI
SimpleTask.run(() -> { SimpleTask.run(() -> {
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) { try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
for (IdentityRecord identityRecord : untrustedRecords) { for (IdentityRecord identityRecord : untrustedRecords) {
ApplicationDependencies.getIdentityStore().setVerified(identityRecord.getRecipientId(), ApplicationDependencies.getProtocolStore().aci().identities().setVerified(identityRecord.getRecipientId(),
identityRecord.getIdentityKey(), identityRecord.getIdentityKey(),
IdentityDatabase.VerifiedStatus.DEFAULT); IdentityDatabase.VerifiedStatus.DEFAULT);
} }
} }
return null; return null;
@@ -65,7 +65,7 @@ class ConversationSettingsRepository(
fun getIdentity(recipientId: RecipientId, consumer: (IdentityRecord?) -> Unit) { fun getIdentity(recipientId: RecipientId, consumer: (IdentityRecord?) -> Unit) {
SignalExecutors.BOUNDED.execute { SignalExecutors.BOUNDED.execute {
consumer(ApplicationDependencies.getIdentityStore().getIdentityRecord(recipientId).orNull()) consumer(ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecord(recipientId).orNull())
} }
} }
@@ -35,7 +35,7 @@ class WebRtcCallRepository {
recipients = Collections.singletonList(recipient); recipients = Collections.singletonList(recipient);
} }
consumer.accept(ApplicationDependencies.getIdentityStore().getIdentityRecords(recipients)); consumer.accept(ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecords(recipients));
}); });
} }
} }
@@ -1685,7 +1685,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
.setView(R.layout.safety_number_changed_learn_more_dialog) .setView(R.layout.safety_number_changed_learn_more_dialog)
.setPositiveButton(R.string.ConversationFragment_verify, (d, w) -> { .setPositiveButton(R.string.ConversationFragment_verify, (d, w) -> {
SimpleTask.run(getLifecycle(), () -> { SimpleTask.run(getLifecycle(), () -> {
return ApplicationDependencies.getIdentityStore().getIdentityRecord(recipient.getId()); return ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecord(recipient.getId());
}, identityRecord -> { }, identityRecord -> {
if (identityRecord.isPresent()) { if (identityRecord.isPresent()) {
startActivity(VerifyIdentityActivity.newIntent(requireContext(), identityRecord.get())); startActivity(VerifyIdentityActivity.newIntent(requireContext(), identityRecord.get()));
@@ -1949,7 +1949,7 @@ public class ConversationParentFragment extends Fragment
} }
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
IdentityRecordList identityRecordList = ApplicationDependencies.getIdentityStore().getIdentityRecords(recipients); IdentityRecordList identityRecordList = ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecords(recipients);
Log.i(TAG, String.format(Locale.US, "Loaded %d identities in %d ms", recipients.size(), System.currentTimeMillis() - startTime)); Log.i(TAG, String.format(Locale.US, "Loaded %d identities in %d ms", recipients.size(), System.currentTimeMillis() - startTime));
@@ -3934,9 +3934,9 @@ public class ConversationParentFragment extends Fragment
SimpleTask.run(() -> { SimpleTask.run(() -> {
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) { try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
for (IdentityRecord identityRecord : unverifiedIdentities) { for (IdentityRecord identityRecord : unverifiedIdentities) {
ApplicationDependencies.getIdentityStore().setVerified(identityRecord.getRecipientId(), ApplicationDependencies.getProtocolStore().aci().identities().setVerified(identityRecord.getRecipientId(),
identityRecord.getIdentityKey(), identityRecord.getIdentityKey(),
VerifiedStatus.DEFAULT); VerifiedStatus.DEFAULT);
} }
} }
return null; return null;
@@ -30,7 +30,7 @@ class MultiselectForwardRepository(context: Context) {
fun checkForBadIdentityRecords(shareContacts: List<ShareContact>, consumer: Consumer<List<IdentityRecord>>) { fun checkForBadIdentityRecords(shareContacts: List<ShareContact>, consumer: Consumer<List<IdentityRecord>>) {
SignalExecutors.BOUNDED.execute { SignalExecutors.BOUNDED.execute {
val recipients: List<Recipient> = shareContacts.map { Recipient.resolved(it.recipientId.get()) } val recipients: List<Recipient> = shareContacts.map { Recipient.resolved(it.recipientId.get()) }
val identityRecordList: IdentityRecordList = ApplicationDependencies.getIdentityStore().getIdentityRecords(recipients) val identityRecordList: IdentityRecordList = ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecords(recipients)
consumer.accept(identityRecordList.untrustedRecords) consumer.accept(identityRecordList.untrustedRecords)
} }
@@ -68,7 +68,7 @@ final class SafetyNumberChangeRepository {
List<Recipient> recipients = Stream.of(recipientIds).map(Recipient::resolved).toList(); List<Recipient> recipients = Stream.of(recipientIds).map(Recipient::resolved).toList();
List<ChangedRecipient> changedRecipients = Stream.of(ApplicationDependencies.getIdentityStore().getIdentityRecords(recipients).getIdentityRecords()) List<ChangedRecipient> changedRecipients = Stream.of(ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecords(recipients).getIdentityRecords())
.map(record -> new ChangedRecipient(Recipient.resolved(record.getRecipientId()), record)) .map(record -> new ChangedRecipient(Recipient.resolved(record.getRecipientId()), record))
.toList(); .toList();
@@ -96,7 +96,7 @@ final class SafetyNumberChangeRepository {
@WorkerThread @WorkerThread
private TrustAndVerifyResult trustOrVerifyChangedRecipientsInternal(@NonNull List<ChangedRecipient> changedRecipients) { private TrustAndVerifyResult trustOrVerifyChangedRecipientsInternal(@NonNull List<ChangedRecipient> changedRecipients) {
TextSecureIdentityKeyStore identityStore = ApplicationDependencies.getIdentityStore(); TextSecureIdentityKeyStore identityStore = ApplicationDependencies.getProtocolStore().aci().identities();
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) { try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
for (ChangedRecipient changedRecipient : changedRecipients) { for (ChangedRecipient changedRecipient : changedRecipients) {
@@ -104,9 +104,9 @@ final class SafetyNumberChangeRepository {
if (changedRecipient.isUnverified()) { if (changedRecipient.isUnverified()) {
Log.d(TAG, "Setting " + identityRecord.getRecipientId() + " as verified"); Log.d(TAG, "Setting " + identityRecord.getRecipientId() + " as verified");
ApplicationDependencies.getIdentityStore().setVerified(identityRecord.getRecipientId(), ApplicationDependencies.getProtocolStore().aci().identities().setVerified(identityRecord.getRecipientId(),
identityRecord.getIdentityKey(), identityRecord.getIdentityKey(),
IdentityDatabase.VerifiedStatus.DEFAULT); IdentityDatabase.VerifiedStatus.DEFAULT);
} else { } else {
Log.d(TAG, "Setting " + identityRecord.getRecipientId() + " as approved"); Log.d(TAG, "Setting " + identityRecord.getRecipientId() + " as approved");
identityStore.setApproval(identityRecord.getRecipientId(), true); identityStore.setApproval(identityRecord.getRecipientId(), true);
@@ -129,7 +129,7 @@ final class SafetyNumberChangeRepository {
SignalProtocolAddress mismatchAddress = new SignalProtocolAddress(changedRecipient.getRecipient().requireServiceId(), SignalServiceAddress.DEFAULT_DEVICE_ID); SignalProtocolAddress mismatchAddress = new SignalProtocolAddress(changedRecipient.getRecipient().requireServiceId(), SignalServiceAddress.DEFAULT_DEVICE_ID);
Log.d(TAG, "Saving identity for: " + changedRecipient.getRecipient().getId() + " " + changedRecipient.getIdentityRecord().getIdentityKey().hashCode()); Log.d(TAG, "Saving identity for: " + changedRecipient.getRecipient().getId() + " " + changedRecipient.getIdentityRecord().getIdentityKey().hashCode());
TextSecureIdentityKeyStore.SaveResult result = ApplicationDependencies.getIdentityStore().saveIdentity(mismatchAddress, changedRecipient.getIdentityRecord().getIdentityKey(), true); TextSecureIdentityKeyStore.SaveResult result = ApplicationDependencies.getProtocolStore().aci().identities().saveIdentity(mismatchAddress, changedRecipient.getIdentityRecord().getIdentityKey(), true);
Log.d(TAG, "Saving identity result: " + result); Log.d(TAG, "Saving identity result: " + result);
if (result == TextSecureIdentityKeyStore.SaveResult.NO_CHANGE) { if (result == TextSecureIdentityKeyStore.SaveResult.NO_CHANGE) {
@@ -44,7 +44,7 @@ public class PreKeyUtil {
private static final int BATCH_SIZE = 100; private static final int BATCH_SIZE = 100;
public synchronized static List<PreKeyRecord> generatePreKeys(Context context) { public synchronized static List<PreKeyRecord> generatePreKeys(Context context) {
PreKeyStore preKeyStore = ApplicationDependencies.getPreKeyStore(); PreKeyStore preKeyStore = ApplicationDependencies.getProtocolStore().aci();
List<PreKeyRecord> records = new LinkedList<>(); List<PreKeyRecord> records = new LinkedList<>();
int preKeyIdOffset = TextSecurePreferences.getNextPreKeyId(context); int preKeyIdOffset = TextSecurePreferences.getNextPreKeyId(context);
@@ -64,7 +64,7 @@ public class PreKeyUtil {
public synchronized static SignedPreKeyRecord generateSignedPreKey(Context context, IdentityKeyPair identityKeyPair, boolean active) { public synchronized static SignedPreKeyRecord generateSignedPreKey(Context context, IdentityKeyPair identityKeyPair, boolean active) {
try { try {
SignedPreKeyStore signedPreKeyStore = ApplicationDependencies.getPreKeyStore(); SignedPreKeyStore signedPreKeyStore = ApplicationDependencies.getProtocolStore().aci();
int signedPreKeyId = TextSecurePreferences.getNextSignedPreKeyId(context); int signedPreKeyId = TextSecurePreferences.getNextSignedPreKeyId(context);
ECKeyPair keyPair = Curve.generateKeyPair(); ECKeyPair keyPair = Curve.generateKeyPair();
byte[] signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize()); byte[] signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());
@@ -22,7 +22,7 @@ public final class SenderKeyUtil {
*/ */
public static void rotateOurKey(@NonNull Context context, @NonNull DistributionId distributionId) { public static void rotateOurKey(@NonNull Context context, @NonNull DistributionId distributionId) {
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) { try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
ApplicationDependencies.getSenderKeyStore().deleteAllFor(Recipient.self().requireServiceId(), distributionId); ApplicationDependencies.getProtocolStore().aci().senderKeys().deleteAllFor(Recipient.self().requireServiceId(), distributionId);
SignalDatabase.senderKeyShared().deleteAllFor(distributionId); SignalDatabase.senderKeyShared().deleteAllFor(distributionId);
} }
} }
@@ -40,7 +40,7 @@ public final class SenderKeyUtil {
*/ */
public static void clearAllState(@NonNull Context context) { public static void clearAllState(@NonNull Context context) {
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) { try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
ApplicationDependencies.getSenderKeyStore().deleteAll(); ApplicationDependencies.getProtocolStore().aci().senderKeys().deleteAll();
SignalDatabase.senderKeyShared().deleteAll(); SignalDatabase.senderKeyShared().deleteAll();
} }
} }
@@ -15,24 +15,24 @@ public class SessionUtil {
public static boolean hasSession(@NonNull RecipientId id) { public static boolean hasSession(@NonNull RecipientId id) {
SignalProtocolAddress axolotlAddress = new SignalProtocolAddress(Recipient.resolved(id).requireServiceId(), SignalServiceAddress.DEFAULT_DEVICE_ID); SignalProtocolAddress axolotlAddress = new SignalProtocolAddress(Recipient.resolved(id).requireServiceId(), SignalServiceAddress.DEFAULT_DEVICE_ID);
return ApplicationDependencies.getSessionStore().containsSession(axolotlAddress); return ApplicationDependencies.getProtocolStore().aci().containsSession(axolotlAddress);
} }
public static void archiveSiblingSessions(SignalProtocolAddress address) { public static void archiveSiblingSessions(SignalProtocolAddress address) {
ApplicationDependencies.getSessionStore().archiveSiblingSessions(address); ApplicationDependencies.getProtocolStore().aci().sessions().archiveSiblingSessions(address);
} }
public static void archiveAllSessions() { public static void archiveAllSessions() {
ApplicationDependencies.getSessionStore().archiveAllSessions(); ApplicationDependencies.getProtocolStore().aci().sessions().archiveAllSessions();
} }
public static void archiveSession(RecipientId recipientId, int deviceId) { public static void archiveSession(RecipientId recipientId, int deviceId) {
ApplicationDependencies.getSessionStore().archiveSession(recipientId, deviceId); ApplicationDependencies.getProtocolStore().aci().sessions().archiveSession(recipientId, deviceId);
} }
public static boolean ratchetKeyMatches(@NonNull Recipient recipient, int deviceId, @NonNull ECPublicKey ratchetKey) { public static boolean ratchetKeyMatches(@NonNull Recipient recipient, int deviceId, @NonNull ECPublicKey ratchetKey) {
SignalProtocolAddress address = new SignalProtocolAddress(recipient.resolve().requireServiceId(), deviceId); SignalProtocolAddress address = new SignalProtocolAddress(recipient.resolve().requireServiceId(), deviceId);
SessionRecord session = ApplicationDependencies.getSessionStore().loadSession(address); SessionRecord session = ApplicationDependencies.getProtocolStore().aci().loadSession(address);
return session.currentRatchetKeyMatches(ratchetKey); return session.currentRatchetKeyMatches(ratchetKey);
} }
@@ -2,9 +2,9 @@ package org.thoughtcrime.securesms.crypto.storage;
import android.content.Context; import android.content.Context;
import org.thoughtcrime.securesms.database.SignalDatabase; import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.IdentityKeyPair;
@@ -12,14 +12,10 @@ import org.whispersystems.libsignal.InvalidKeyIdException;
import org.whispersystems.libsignal.NoSessionException; import org.whispersystems.libsignal.NoSessionException;
import org.whispersystems.libsignal.SignalProtocolAddress; import org.whispersystems.libsignal.SignalProtocolAddress;
import org.whispersystems.libsignal.groups.state.SenderKeyRecord; import org.whispersystems.libsignal.groups.state.SenderKeyRecord;
import org.whispersystems.libsignal.state.IdentityKeyStore;
import org.whispersystems.libsignal.state.PreKeyRecord; import org.whispersystems.libsignal.state.PreKeyRecord;
import org.whispersystems.libsignal.state.PreKeyStore;
import org.whispersystems.libsignal.state.SessionRecord; import org.whispersystems.libsignal.state.SessionRecord;
import org.whispersystems.libsignal.state.SignedPreKeyRecord; import org.whispersystems.libsignal.state.SignedPreKeyRecord;
import org.whispersystems.libsignal.state.SignedPreKeyStore; import org.whispersystems.signalservice.api.SignalServiceAccountDataStore;
import org.whispersystems.signalservice.api.SignalServiceDataStore;
import org.whispersystems.signalservice.api.SignalServiceSessionStore;
import org.whispersystems.signalservice.api.push.DistributionId; import org.whispersystems.signalservice.api.push.DistributionId;
import java.util.Collection; import java.util.Collection;
@@ -27,22 +23,32 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
public class SignalProtocolStoreImpl implements SignalServiceDataStore { public class SignalServiceAccountDataStoreImpl implements SignalServiceAccountDataStore {
private final Context context; private final Context context;
private final PreKeyStore preKeyStore; private final TextSecurePreKeyStore preKeyStore;
private final SignedPreKeyStore signedPreKeyStore; private final TextSecurePreKeyStore signedPreKeyStore;
private final IdentityKeyStore identityKeyStore; private final TextSecureIdentityKeyStore identityKeyStore;
private final SignalServiceSessionStore sessionStore; private final TextSecureSessionStore sessionStore;
private final SignalSenderKeyStore senderKeyStore; private final SignalSenderKeyStore senderKeyStore;
public SignalProtocolStoreImpl(Context context) { public SignalServiceAccountDataStoreImpl(@NonNull Context context,
@NonNull TextSecurePreKeyStore preKeyStore,
@NonNull TextSecureIdentityKeyStore identityKeyStore,
@NonNull TextSecureSessionStore sessionStore,
@NonNull SignalSenderKeyStore senderKeyStore)
{
this.context = context; this.context = context;
this.preKeyStore = ApplicationDependencies.getPreKeyStore(); this.preKeyStore = preKeyStore;
this.signedPreKeyStore = ApplicationDependencies.getPreKeyStore(); this.signedPreKeyStore = preKeyStore;
this.identityKeyStore = ApplicationDependencies.getIdentityStore(); this.identityKeyStore = identityKeyStore;
this.sessionStore = ApplicationDependencies.getSessionStore(); this.sessionStore = sessionStore;
this.senderKeyStore = ApplicationDependencies.getSenderKeyStore(); this.senderKeyStore = senderKeyStore;
}
@Override
public boolean isMultiDevice() {
return TextSecurePreferences.isMultiDevice(context);
} }
@Override @Override
@@ -185,17 +191,20 @@ public class SignalProtocolStoreImpl implements SignalServiceDataStore {
senderKeyStore.clearSenderKeySharedWith(addresses); senderKeyStore.clearSenderKeySharedWith(addresses);
} }
@Override public @NonNull TextSecureIdentityKeyStore identities() {
public boolean isMultiDevice() { return identityKeyStore;
return TextSecurePreferences.isMultiDevice(context);
} }
@Override public @NonNull TextSecurePreKeyStore preKeys() {
public Transaction beginTransaction() { return preKeyStore;
SignalDatabase.getRawDatabase().beginTransaction();
return () -> {
SignalDatabase.getRawDatabase().setTransactionSuccessful();
SignalDatabase.getRawDatabase().endTransaction();
};
} }
public @NonNull TextSecureSessionStore sessions() {
return sessionStore;
}
public @NonNull SignalSenderKeyStore senderKeys() {
return senderKeyStore;
}
} }
@@ -0,0 +1,52 @@
package org.thoughtcrime.securesms.crypto.storage;
import android.content.Context;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.SignalServiceDataStore;
import org.whispersystems.signalservice.api.push.AccountIdentifier;
public final class SignalServiceDataStoreImpl implements SignalServiceDataStore {
private final Context context;
private final SignalServiceAccountDataStoreImpl aciStore;
private final SignalServiceAccountDataStoreImpl pniStore;
public SignalServiceDataStoreImpl(@NonNull Context context,
@NonNull SignalServiceAccountDataStoreImpl aciStore,
@NonNull SignalServiceAccountDataStoreImpl pniStore)
{
this.context = context;
this.aciStore = aciStore;
this.pniStore = pniStore;
}
@Override
public SignalServiceAccountDataStoreImpl get(@NonNull AccountIdentifier accountIdentifier) {
if (accountIdentifier.equals(SignalStore.account().getAci())) {
return aciStore;
} else if (accountIdentifier.equals(SignalStore.account().getPni())) {
return pniStore;
} else {
throw new IllegalArgumentException("No matching store found for " + accountIdentifier);
}
}
@Override
public SignalServiceAccountDataStoreImpl aci() {
return aciStore;
}
@Override
public SignalServiceAccountDataStoreImpl pni() {
return pniStore;
}
@Override
public boolean isMultiDevice() {
return TextSecurePreferences.isMultiDevice(context);
}
}
@@ -186,7 +186,7 @@ public class IdentityDatabase extends Database {
EventBus.getDefault().post(record.get()); EventBus.getDefault().post(record.get());
} }
ApplicationDependencies.getIdentityStore().invalidate(addressName); ApplicationDependencies.getProtocolStore().aci().identities().invalidate(addressName);
} }
if (hadEntry && !keyMatches) { if (hadEntry && !keyMatches) {
@@ -789,7 +789,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
fun applyStorageSyncContactUpdate(update: StorageRecordUpdate<SignalContactRecord>) { fun applyStorageSyncContactUpdate(update: StorageRecordUpdate<SignalContactRecord>) {
val db = writableDatabase val db = writableDatabase
val identityStore = ApplicationDependencies.getIdentityStore() val identityStore = ApplicationDependencies.getProtocolStore().aci().identities()
val values = getValuesForStorageContact(update.new, false) val values = getValuesForStorageContact(update.new, false)
try { try {
@@ -2525,7 +2525,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) :
val e164Record = getRecord(byE164) val e164Record = getRecord(byE164)
// Identities // Identities
ApplicationDependencies.getIdentityStore().delete(e164Record.e164!!) ApplicationDependencies.getProtocolStore().aci().identities().delete(e164Record.e164!!)
// Group Receipts // Group Receipts
val groupReceiptValues = ContentValues() val groupReceiptValues = ContentValues()
@@ -11,10 +11,7 @@ import org.signal.zkgroup.receipts.ClientZkReceiptOperations;
import org.thoughtcrime.securesms.KbsEnclave; import org.thoughtcrime.securesms.KbsEnclave;
import org.thoughtcrime.securesms.components.TypingStatusRepository; import org.thoughtcrime.securesms.components.TypingStatusRepository;
import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.crypto.storage.SignalSenderKeyStore; import org.thoughtcrime.securesms.crypto.storage.SignalServiceDataStoreImpl;
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
import org.thoughtcrime.securesms.crypto.storage.TextSecurePreKeyStore;
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
import org.thoughtcrime.securesms.database.DatabaseObserver; import org.thoughtcrime.securesms.database.DatabaseObserver;
import org.thoughtcrime.securesms.database.PendingRetryReceiptCache; import org.thoughtcrime.securesms.database.PendingRetryReceiptCache;
import org.thoughtcrime.securesms.groups.GroupsV2Authorization; import org.thoughtcrime.securesms.groups.GroupsV2Authorization;
@@ -101,10 +98,7 @@ public class ApplicationDependencies {
private static volatile PendingRetryReceiptCache pendingRetryReceiptCache; private static volatile PendingRetryReceiptCache pendingRetryReceiptCache;
private static volatile SignalWebSocket signalWebSocket; private static volatile SignalWebSocket signalWebSocket;
private static volatile MessageNotifier messageNotifier; private static volatile MessageNotifier messageNotifier;
private static volatile TextSecureIdentityKeyStore identityStore; private static volatile SignalServiceDataStoreImpl protocolStore;
private static volatile TextSecureSessionStore sessionStore;
private static volatile TextSecurePreKeyStore preKeyStore;
private static volatile SignalSenderKeyStore senderKeyStore;
private static volatile GiphyMp4Cache giphyMp4Cache; private static volatile GiphyMp4Cache giphyMp4Cache;
private static volatile SimpleExoPlayerPool exoPlayerPool; private static volatile SimpleExoPlayerPool exoPlayerPool;
private static volatile AudioManagerCompat audioManagerCompat; private static volatile AudioManagerCompat audioManagerCompat;
@@ -525,48 +519,16 @@ public class ApplicationDependencies {
return signalWebSocket; return signalWebSocket;
} }
public static @NonNull TextSecureIdentityKeyStore getIdentityStore() { public static @NonNull SignalServiceDataStoreImpl getProtocolStore() {
if (identityStore == null) { if (protocolStore == null) {
synchronized (LOCK) { synchronized (LOCK) {
if (identityStore == null) { if (protocolStore == null) {
identityStore = provider.provideIdentityStore(); protocolStore = provider.provideProtocolStore();
} }
} }
} }
return identityStore;
}
public static @NonNull TextSecureSessionStore getSessionStore() { return protocolStore;
if (sessionStore == null) {
synchronized (LOCK) {
if (sessionStore == null) {
sessionStore = provider.provideSessionStore();
}
}
}
return sessionStore;
}
public static @NonNull TextSecurePreKeyStore getPreKeyStore() {
if (preKeyStore == null) {
synchronized (LOCK) {
if (preKeyStore == null) {
preKeyStore = provider.providePreKeyStore();
}
}
}
return preKeyStore;
}
public static @NonNull SignalSenderKeyStore getSenderKeyStore() {
if (senderKeyStore == null) {
synchronized (LOCK) {
if (senderKeyStore == null) {
senderKeyStore = provider.provideSenderKeyStore();
}
}
}
return senderKeyStore;
} }
public static @NonNull GiphyMp4Cache getGiphyMp4Cache() { public static @NonNull GiphyMp4Cache getGiphyMp4Cache() {
@@ -663,10 +625,7 @@ public class ApplicationDependencies {
@NonNull PendingRetryReceiptManager providePendingRetryReceiptManager(); @NonNull PendingRetryReceiptManager providePendingRetryReceiptManager();
@NonNull PendingRetryReceiptCache providePendingRetryReceiptCache(); @NonNull PendingRetryReceiptCache providePendingRetryReceiptCache();
@NonNull SignalWebSocket provideSignalWebSocket(); @NonNull SignalWebSocket provideSignalWebSocket();
@NonNull TextSecureIdentityKeyStore provideIdentityStore(); @NonNull SignalServiceDataStoreImpl provideProtocolStore();
@NonNull TextSecureSessionStore provideSessionStore();
@NonNull TextSecurePreKeyStore providePreKeyStore();
@NonNull SignalSenderKeyStore provideSenderKeyStore();
@NonNull GiphyMp4Cache provideGiphyMp4Cache(); @NonNull GiphyMp4Cache provideGiphyMp4Cache();
@NonNull SimpleExoPlayerPool provideExoPlayerPool(); @NonNull SimpleExoPlayerPool provideExoPlayerPool();
@NonNull AudioManagerCompat provideAndroidCallAudioManager(); @NonNull AudioManagerCompat provideAndroidCallAudioManager();
@@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.dependencies; package org.thoughtcrime.securesms.dependencies;
import android.app.Application; import android.app.Application;
import android.content.Context;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
@@ -14,7 +13,8 @@ import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.components.TypingStatusRepository; import org.thoughtcrime.securesms.components.TypingStatusRepository;
import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock; import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl; import org.thoughtcrime.securesms.crypto.storage.SignalServiceDataStoreImpl;
import org.thoughtcrime.securesms.crypto.storage.SignalServiceAccountDataStoreImpl;
import org.thoughtcrime.securesms.crypto.storage.SignalSenderKeyStore; import org.thoughtcrime.securesms.crypto.storage.SignalSenderKeyStore;
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore; import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
import org.thoughtcrime.securesms.crypto.storage.TextSecurePreKeyStore; import org.thoughtcrime.securesms.crypto.storage.TextSecurePreKeyStore;
@@ -116,7 +116,7 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr
public @NonNull SignalServiceMessageSender provideSignalServiceMessageSender(@NonNull SignalWebSocket signalWebSocket) { public @NonNull SignalServiceMessageSender provideSignalServiceMessageSender(@NonNull SignalWebSocket signalWebSocket) {
return new SignalServiceMessageSender(provideSignalServiceNetworkAccess().getConfiguration(), return new SignalServiceMessageSender(provideSignalServiceNetworkAccess().getConfiguration(),
new DynamicCredentialsProvider(), new DynamicCredentialsProvider(),
new SignalProtocolStoreImpl(context), provideProtocolStore(),
ReentrantSessionLock.INSTANCE, ReentrantSessionLock.INSTANCE,
BuildConfig.SIGNAL_AGENT, BuildConfig.SIGNAL_AGENT,
signalWebSocket, signalWebSocket,
@@ -274,23 +274,13 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr
} }
@Override @Override
public @NonNull TextSecureIdentityKeyStore provideIdentityStore() { public @NonNull SignalServiceDataStoreImpl provideProtocolStore() {
return new TextSecureIdentityKeyStore(context); SignalServiceAccountDataStoreImpl aci = new SignalServiceAccountDataStoreImpl(context,
} new TextSecurePreKeyStore(context),
new TextSecureIdentityKeyStore(context),
@Override new TextSecureSessionStore(context),
public @NonNull TextSecureSessionStore provideSessionStore() { new SignalSenderKeyStore(context));
return new TextSecureSessionStore(context); return new SignalServiceDataStoreImpl(context, aci, aci);
}
@Override
public @NonNull TextSecurePreKeyStore providePreKeyStore() {
return new TextSecurePreKeyStore(context);
}
@Override
public @NonNull SignalSenderKeyStore provideSenderKeyStore() {
return new SignalSenderKeyStore(context);
} }
@Override @Override
@@ -4,7 +4,7 @@ import androidx.annotation.NonNull;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.crypto.PreKeyUtil; import org.thoughtcrime.securesms.crypto.PreKeyUtil;
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.Job;
import org.whispersystems.libsignal.InvalidKeyIdException; import org.whispersystems.libsignal.InvalidKeyIdException;
@@ -55,7 +55,7 @@ public class CleanPreKeysJob extends BaseJob {
Log.i(TAG, "Cleaning prekeys..."); Log.i(TAG, "Cleaning prekeys...");
int activeSignedPreKeyId = PreKeyUtil.getActiveSignedPreKeyId(context); int activeSignedPreKeyId = PreKeyUtil.getActiveSignedPreKeyId(context);
SignedPreKeyStore signedPreKeyStore = new SignalProtocolStoreImpl(context); SignedPreKeyStore signedPreKeyStore = ApplicationDependencies.getProtocolStore().aci();
if (activeSignedPreKeyId < 0) return; if (activeSignedPreKeyId < 0) return;
@@ -102,7 +102,7 @@ class MultiDeviceContactSyncJob(parameters: Parameters, private val attachmentPo
else -> VerifiedStatus.DEFAULT else -> VerifiedStatus.DEFAULT
} }
ApplicationDependencies.getIdentityStore().saveIdentityWithoutSideEffects( ApplicationDependencies.getProtocolStore().aci().identities().saveIdentityWithoutSideEffects(
recipient.id, recipient.id,
contact.verified.get().identityKey, contact.verified.get().identityKey,
verifiedStatus, verifiedStatus,
@@ -149,7 +149,7 @@ public class MultiDeviceContactUpdateJob extends BaseJob {
return; return;
} }
Optional<IdentityRecord> identityRecord = ApplicationDependencies.getIdentityStore().getIdentityRecord(recipient.getId()); Optional<IdentityRecord> identityRecord = ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecord(recipient.getId());
Optional<VerifiedMessage> verifiedMessage = getVerifiedMessage(recipient, identityRecord); Optional<VerifiedMessage> verifiedMessage = getVerifiedMessage(recipient, identityRecord);
Map<RecipientId, Integer> inboxPositions = SignalDatabase.threads().getInboxPositions(); Map<RecipientId, Integer> inboxPositions = SignalDatabase.threads().getInboxPositions();
Set<RecipientId> archived = SignalDatabase.threads().getArchivedRecipients(); Set<RecipientId> archived = SignalDatabase.threads().getArchivedRecipients();
@@ -208,7 +208,7 @@ public class MultiDeviceContactUpdateJob extends BaseJob {
Set<RecipientId> archived = SignalDatabase.threads().getArchivedRecipients(); Set<RecipientId> archived = SignalDatabase.threads().getArchivedRecipients();
for (Recipient recipient : recipients) { for (Recipient recipient : recipients) {
Optional<IdentityRecord> identity = ApplicationDependencies.getIdentityStore().getIdentityRecord(recipient.getId()); Optional<IdentityRecord> identity = ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecord(recipient.getId());
Optional<VerifiedMessage> verified = getVerifiedMessage(recipient, identity); Optional<VerifiedMessage> verified = getVerifiedMessage(recipient, identity);
Optional<String> name = Optional.fromNullable(recipient.isSystemContact() ? recipient.getDisplayName(context) : recipient.getGroupName(context)); Optional<String> name = Optional.fromNullable(recipient.isSystemContact() ? recipient.getDisplayName(context) : recipient.getGroupName(context));
Optional<ProfileKey> profileKey = ProfileKeyUtil.profileKeyOptional(recipient.getProfileKey()); Optional<ProfileKey> profileKey = ProfileKeyUtil.profileKeyOptional(recipient.getProfileKey());
@@ -161,7 +161,7 @@ public class ResendMessageJob extends BaseJob {
.map(device -> new SignalProtocolAddress(recipient.requireServiceId(), device)) .map(device -> new SignalProtocolAddress(recipient.requireServiceId(), device))
.collect(Collectors.toList()); .collect(Collectors.toList());
ApplicationDependencies.getSenderKeyStore().markSenderKeySharedWith(distributionId, addresses); ApplicationDependencies.getProtocolStore().aci().markSenderKeySharedWith(distributionId, addresses);
} }
} }
@@ -386,7 +386,7 @@ public class RetrieveProfileJob extends BaseJob {
IdentityKey identityKey = new IdentityKey(Base64.decode(identityKeyValue), 0); IdentityKey identityKey = new IdentityKey(Base64.decode(identityKeyValue), 0);
if (!ApplicationDependencies.getIdentityStore().getIdentityRecord(recipient.getId()).isPresent()) { if (!ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecord(recipient.getId()).isPresent()) {
Log.w(TAG, "Still first use..."); Log.w(TAG, "Still first use...");
return; return;
} }
@@ -110,7 +110,7 @@ public final class SenderKeyDistributionSendJob extends BaseJob {
.map(device -> new SignalProtocolAddress(recipient.requireServiceId(), device)) .map(device -> new SignalProtocolAddress(recipient.requireServiceId(), device))
.collect(Collectors.toList()); .collect(Collectors.toList());
ApplicationDependencies.getSenderKeyStore().markSenderKeySharedWith(distributionId, addresses); ApplicationDependencies.getProtocolStore().aci().markSenderKeySharedWith(distributionId, addresses);
} }
} }
@@ -561,7 +561,7 @@ public final class MessageContentProcessor {
database.markAsMissedCall(smsMessageId.get(), message.getType() == OfferMessage.Type.VIDEO_CALL); database.markAsMissedCall(smsMessageId.get(), message.getType() == OfferMessage.Type.VIDEO_CALL);
} else { } else {
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId(), new CallId(message.getId())); RemotePeer remotePeer = new RemotePeer(senderRecipient.getId(), new CallId(message.getId()));
byte[] remoteIdentityKey = ApplicationDependencies.getIdentityStore().getIdentityRecord(senderRecipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull(); byte[] remoteIdentityKey = ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecord(senderRecipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull();
ApplicationDependencies.getSignalCallManager() ApplicationDependencies.getSignalCallManager()
.receivedOffer(new WebRtcData.CallMetadata(remotePeer, content.getSenderDevice()), .receivedOffer(new WebRtcData.CallMetadata(remotePeer, content.getSenderDevice()),
@@ -579,7 +579,7 @@ public final class MessageContentProcessor {
{ {
log(String.valueOf(content), "handleCallAnswerMessage..."); log(String.valueOf(content), "handleCallAnswerMessage...");
RemotePeer remotePeer = new RemotePeer(senderRecipient.getId(), new CallId(message.getId())); RemotePeer remotePeer = new RemotePeer(senderRecipient.getId(), new CallId(message.getId()));
byte[] remoteIdentityKey = ApplicationDependencies.getIdentityStore().getIdentityRecord(senderRecipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull(); byte[] remoteIdentityKey = ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecord(senderRecipient.getId()).transform(record -> record.getIdentityKey().serialize()).orNull();
ApplicationDependencies.getSignalCallManager() ApplicationDependencies.getSignalCallManager()
.receivedAnswer(new WebRtcData.CallMetadata(remotePeer, content.getSenderDevice()), .receivedAnswer(new WebRtcData.CallMetadata(remotePeer, content.getSenderDevice()),
@@ -707,7 +707,7 @@ public final class MessageContentProcessor {
} }
if (insertResult.isPresent()) { if (insertResult.isPresent()) {
ApplicationDependencies.getSessionStore().deleteAllSessions(content.getSender().getIdentifier()); ApplicationDependencies.getProtocolStore().aci().deleteAllSessions(content.getSender().getIdentifier());
SecurityEvent.broadcastSecurityUpdateEvent(context); SecurityEvent.broadcastSecurityUpdateEvent(context);
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId()); ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
@@ -731,7 +731,7 @@ public final class MessageContentProcessor {
long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(recipient); long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(recipient);
if (!recipient.isGroup()) { if (!recipient.isGroup()) {
ApplicationDependencies.getSessionStore().deleteAllSessions(recipient.requireServiceId()); ApplicationDependencies.getProtocolStore().aci().deleteAllSessions(recipient.requireServiceId());
SecurityEvent.broadcastSecurityUpdateEvent(context); SecurityEvent.broadcastSecurityUpdateEvent(context);
@@ -25,7 +25,6 @@ import org.signal.libsignal.metadata.SelfSendException;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock; import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.BadGroupIdException; import org.thoughtcrime.securesms.groups.BadGroupIdException;
@@ -77,7 +76,7 @@ public final class MessageDecryptionUtil {
* caller. * caller.
*/ */
public static @NonNull DecryptionResult decrypt(@NonNull Context context, @NonNull SignalServiceEnvelope envelope) { public static @NonNull DecryptionResult decrypt(@NonNull Context context, @NonNull SignalServiceEnvelope envelope) {
SignalProtocolStore axolotlStore = new SignalProtocolStoreImpl(context); SignalProtocolStore axolotlStore = ApplicationDependencies.getProtocolStore().aci();
SignalServiceAddress localAddress = new SignalServiceAddress(Recipient.self().requireAci(), Recipient.self().requireE164()); SignalServiceAddress localAddress = new SignalServiceAddress(Recipient.self().requireAci(), Recipient.self().requireE164());
SignalServiceCipher cipher = new SignalServiceCipher(localAddress, SignalStore.account().getDeviceId(), axolotlStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator()); SignalServiceCipher cipher = new SignalServiceCipher(localAddress, SignalStore.account().getDeviceId(), axolotlStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator());
List<Job> jobs = new LinkedList<>(); List<Job> jobs = new LinkedList<>();
@@ -54,7 +54,7 @@ final class RecipientDialogRepository {
void getIdentity(@NonNull Consumer<IdentityRecord> callback) { void getIdentity(@NonNull Consumer<IdentityRecord> callback) {
SignalExecutors.BOUNDED.execute( SignalExecutors.BOUNDED.execute(
() -> callback.accept(ApplicationDependencies.getIdentityStore().getIdentityRecord(recipientId).orNull())); () -> callback.accept(ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecord(recipientId).orNull()));
} }
void getRecipient(@NonNull RecipientCallback recipientCallback) { void getRecipient(@NonNull RecipientCallback recipientCallback) {
@@ -161,7 +161,7 @@ public final class RegistrationRepository {
SignalStore.account().setFcmToken(registrationData.getFcmToken()); SignalStore.account().setFcmToken(registrationData.getFcmToken());
SignalStore.account().setFcmEnabled(registrationData.isFcm()); SignalStore.account().setFcmEnabled(registrationData.isFcm());
ApplicationDependencies.getIdentityStore() ApplicationDependencies.getProtocolStore().aci().identities()
.saveIdentityWithoutSideEffects(selfId, .saveIdentityWithoutSideEffects(selfId,
identityKey.getPublicKey(), identityKey.getPublicKey(),
IdentityDatabase.VerifiedStatus.VERIFIED, IdentityDatabase.VerifiedStatus.VERIFIED,
@@ -52,7 +52,7 @@ public final class IdentityUtil {
final RecipientId recipientId = recipient.getId(); final RecipientId recipientId = recipient.getId();
SimpleTask.run(SignalExecutors.BOUNDED, SimpleTask.run(SignalExecutors.BOUNDED,
() -> ApplicationDependencies.getIdentityStore().getIdentityRecord(recipientId), () -> ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecord(recipientId),
future::set); future::set);
return future; return future;
@@ -144,10 +144,10 @@ public final class IdentityUtil {
public static void saveIdentity(String user, IdentityKey identityKey) { public static void saveIdentity(String user, IdentityKey identityKey) {
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) { try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
SessionStore sessionStore = ApplicationDependencies.getSessionStore(); SessionStore sessionStore = ApplicationDependencies.getProtocolStore().aci();
SignalProtocolAddress address = new SignalProtocolAddress(user, SignalServiceAddress.DEFAULT_DEVICE_ID); SignalProtocolAddress address = new SignalProtocolAddress(user, SignalServiceAddress.DEFAULT_DEVICE_ID);
if (ApplicationDependencies.getIdentityStore().saveIdentity(address, identityKey)) { if (ApplicationDependencies.getProtocolStore().aci().identities().saveIdentity(address, identityKey)) {
if (sessionStore.containsSession(address)) { if (sessionStore.containsSession(address)) {
SessionRecord sessionRecord = sessionStore.loadSession(address); SessionRecord sessionRecord = sessionStore.loadSession(address);
sessionRecord.archiveCurrentState(); sessionRecord.archiveCurrentState();
@@ -160,7 +160,7 @@ public final class IdentityUtil {
public static void processVerifiedMessage(Context context, VerifiedMessage verifiedMessage) { public static void processVerifiedMessage(Context context, VerifiedMessage verifiedMessage) {
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) { try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
TextSecureIdentityKeyStore identityStore = ApplicationDependencies.getIdentityStore(); TextSecureIdentityKeyStore identityStore = ApplicationDependencies.getProtocolStore().aci().identities();
Recipient recipient = Recipient.externalPush(context, verifiedMessage.getDestination()); Recipient recipient = Recipient.externalPush(context, verifiedMessage.getDestination());
Optional<IdentityRecord> identityRecord = identityStore.getIdentityRecord(recipient.getId()); Optional<IdentityRecord> identityRecord = identityStore.getIdentityRecord(recipient.getId());
@@ -541,7 +541,7 @@ public class VerifyDisplayFragment extends Fragment implements ViewTreeObserver.
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) { try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
if (verified) { if (verified) {
Log.i(TAG, "Saving identity: " + recipientId); Log.i(TAG, "Saving identity: " + recipientId);
ApplicationDependencies.getIdentityStore() ApplicationDependencies.getProtocolStore().aci().identities()
.saveIdentityWithoutSideEffects(recipientId, .saveIdentityWithoutSideEffects(recipientId,
remoteIdentity, remoteIdentity,
IdentityDatabase.VerifiedStatus.VERIFIED, IdentityDatabase.VerifiedStatus.VERIFIED,
@@ -549,7 +549,7 @@ public class VerifyDisplayFragment extends Fragment implements ViewTreeObserver.
System.currentTimeMillis(), System.currentTimeMillis(),
true); true);
} else { } else {
ApplicationDependencies.getIdentityStore().setVerified(recipientId, remoteIdentity, IdentityDatabase.VerifiedStatus.DEFAULT); ApplicationDependencies.getProtocolStore().aci().identities().setVerified(recipientId, remoteIdentity, IdentityDatabase.VerifiedStatus.DEFAULT);
} }
ApplicationDependencies.getJobManager() ApplicationDependencies.getJobManager()
@@ -7,6 +7,7 @@ import org.signal.zkgroup.receipts.ClientZkReceiptOperations;
import org.thoughtcrime.securesms.components.TypingStatusRepository; import org.thoughtcrime.securesms.components.TypingStatusRepository;
import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.crypto.storage.SignalSenderKeyStore; import org.thoughtcrime.securesms.crypto.storage.SignalSenderKeyStore;
import org.thoughtcrime.securesms.crypto.storage.SignalServiceDataStoreImpl;
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore; import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
import org.thoughtcrime.securesms.crypto.storage.TextSecurePreKeyStore; import org.thoughtcrime.securesms.crypto.storage.TextSecurePreKeyStore;
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore; import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
@@ -179,22 +180,7 @@ public class MockApplicationDependencyProvider implements ApplicationDependencie
} }
@Override @Override
public @NonNull TextSecureIdentityKeyStore provideIdentityStore() { public @NonNull SignalServiceDataStoreImpl provideProtocolStore() {
return null;
}
@Override
public @NonNull TextSecureSessionStore provideSessionStore() {
return null;
}
@Override
public @NonNull TextSecurePreKeyStore providePreKeyStore() {
return null;
}
@Override
public @NonNull SignalSenderKeyStore provideSenderKeyStore() {
return null; return null;
} }
@@ -0,0 +1,16 @@
package org.whispersystems.signalservice.api;
import org.whispersystems.libsignal.state.SignalProtocolStore;
import java.io.Closeable;
/**
* And extension of the normal protocol store interface that has additional methods that are needed
* in the service layer, but not the protocol layer.
*/
public interface SignalServiceAccountDataStore extends SignalProtocolStore, SignalServiceSessionStore, SignalServiceSenderKeyStore {
/**
* @return True if the user has linked devices, otherwise false.
*/
boolean isMultiDevice();
}
@@ -1,25 +1,30 @@
package org.whispersystems.signalservice.api; package org.whispersystems.signalservice.api;
import org.whispersystems.libsignal.state.SignalProtocolStore; import org.whispersystems.signalservice.api.push.AccountIdentifier;
import java.io.Closeable;
/** /**
* And extension of the normal protocol store interface that has additional methods that are needed * And extension of the normal protocol store interface that has additional methods that are needed
* in the service layer, but not the protocol layer. * in the service layer, but not the protocol layer.
*/ */
public interface SignalServiceDataStore extends SignalProtocolStore, SignalServiceSessionStore, SignalServiceSenderKeyStore { public interface SignalServiceDataStore {
/** /**
* @return True if the active account has or is a linked device, otherwise false. * @return A {@link SignalServiceAccountDataStore} for the specified account.
*/
SignalServiceAccountDataStore get(AccountIdentifier accountIdentifier);
/**
* @return A {@link SignalServiceAccountDataStore} for the ACI account.
*/
SignalServiceAccountDataStore aci();
/**
* @return A {@link SignalServiceAccountDataStore} for the PNI account.
*/
SignalServiceAccountDataStore pni();
/**
* @return True if the user has linked devices, otherwise false.
*/ */
boolean isMultiDevice(); boolean isMultiDevice();
/**
* @return Begins a transaction to improve the performance of multiple storage operations happening in a row.
*/
Transaction beginTransaction();
interface Transaction extends Closeable {
void close();
}
} }
@@ -148,12 +148,12 @@ public class SignalServiceMessageSender {
private static final int RETRY_COUNT = 4; private static final int RETRY_COUNT = 4;
private final PushServiceSocket socket; private final PushServiceSocket socket;
private final SignalServiceDataStore store; private final SignalServiceAccountDataStore store;
private final SignalSessionLock sessionLock; private final SignalSessionLock sessionLock;
private final SignalServiceAddress localAddress; private final SignalServiceAddress localAddress;
private final int localDeviceId; private final int localDeviceId;
private final Optional<EventListener> eventListener; private final Optional<EventListener> eventListener;
private final AttachmentService attachmentService; private final AttachmentService attachmentService;
private final MessagingService messagingService; private final MessagingService messagingService;
@@ -174,7 +174,7 @@ public class SignalServiceMessageSender {
boolean automaticNetworkRetry) boolean automaticNetworkRetry)
{ {
this.socket = new PushServiceSocket(urls, credentialsProvider, signalAgent, clientZkProfileOperations, automaticNetworkRetry); this.socket = new PushServiceSocket(urls, credentialsProvider, signalAgent, clientZkProfileOperations, automaticNetworkRetry);
this.store = store; this.store = store.aci();
this.sessionLock = sessionLock; this.sessionLock = sessionLock;
this.localAddress = new SignalServiceAddress(credentialsProvider.getAci(), credentialsProvider.getE164()); this.localAddress = new SignalServiceAddress(credentialsProvider.getAci(), credentialsProvider.getE164());
this.localDeviceId = credentialsProvider.getDeviceId(); this.localDeviceId = credentialsProvider.getDeviceId();