Light refactor of SignalStore.

This commit is contained in:
Greyson Parrelli 2020-06-10 15:24:27 -07:00 committed by Alan Evans
parent e2019579fb
commit 1ce8ac2de6
9 changed files with 206 additions and 118 deletions

View file

@ -12,7 +12,7 @@ import org.whispersystems.signalservice.internal.contacts.entities.TokenResponse
import java.io.IOException;
import java.security.SecureRandom;
public final class KbsValues {
public final class KbsValues extends SignalStoreValues {
public static final String V2_LOCK_ENABLED = "kbs.v2_lock_enabled";
private static final String MASTER_KEY = "kbs.registration_lock_master_key";
@ -21,10 +21,12 @@ public final class KbsValues {
private static final String LOCK_LOCAL_PIN_HASH = "kbs.registration_lock_local_pin_hash";
private static final String LAST_CREATE_FAILED_TIMESTAMP = "kbs.last_create_failed_timestamp";
private final KeyValueStore store;
KbsValues(KeyValueStore store) {
this.store = store;
super(store);
}
@Override
void onFirstEverAppLaunch() {
}
/**
@ -33,13 +35,13 @@ public final class KbsValues {
* Should only be called by {@link org.thoughtcrime.securesms.pin.PinState}
*/
public void clearRegistrationLockAndPin() {
store.beginWrite()
.remove(V2_LOCK_ENABLED)
.remove(TOKEN_RESPONSE)
.remove(LOCK_LOCAL_PIN_HASH)
.remove(PIN)
.remove(LAST_CREATE_FAILED_TIMESTAMP)
.commit();
getStore().beginWrite()
.remove(V2_LOCK_ENABLED)
.remove(TOKEN_RESPONSE)
.remove(LOCK_LOCAL_PIN_HASH)
.remove(PIN)
.remove(LAST_CREATE_FAILED_TIMESTAMP)
.commit();
}
/** Should only be set by {@link org.thoughtcrime.securesms.pin.PinState}. */
@ -52,43 +54,43 @@ public final class KbsValues {
throw new AssertionError(e);
}
store.beginWrite()
.putString(TOKEN_RESPONSE, tokenResponse)
.putBlob(MASTER_KEY, masterKey.serialize())
.putString(LOCK_LOCAL_PIN_HASH, PinHashing.localPinHash(pin))
.putString(PIN, pin)
.putLong(LAST_CREATE_FAILED_TIMESTAMP, -1)
.commit();
getStore().beginWrite()
.putString(TOKEN_RESPONSE, tokenResponse)
.putBlob(MASTER_KEY, masterKey.serialize())
.putString(LOCK_LOCAL_PIN_HASH, PinHashing.localPinHash(pin))
.putString(PIN, pin)
.putLong(LAST_CREATE_FAILED_TIMESTAMP, -1)
.commit();
}
synchronized void setPinIfNotPresent(@NonNull String pin) {
if (store.getString(PIN, null) == null) {
store.beginWrite().putString(PIN, pin).commit();
if (getStore().getString(PIN, null) == null) {
getStore().beginWrite().putString(PIN, pin).commit();
}
}
/** Should only be set by {@link org.thoughtcrime.securesms.pin.PinState}. */
public synchronized void setV2RegistrationLockEnabled(boolean enabled) {
store.beginWrite().putBoolean(V2_LOCK_ENABLED, enabled).apply();
putBoolean(V2_LOCK_ENABLED, enabled);
}
/**
* Whether or not registration lock V2 is enabled.
*/
public synchronized boolean isV2RegistrationLockEnabled() {
return store.getBoolean(V2_LOCK_ENABLED, false);
return getBoolean(V2_LOCK_ENABLED, false);
}
/** Should only be set by {@link org.thoughtcrime.securesms.pin.PinState}. */
public synchronized void onPinCreateFailure() {
store.beginWrite().putLong(LAST_CREATE_FAILED_TIMESTAMP, System.currentTimeMillis()).apply();
putLong(LAST_CREATE_FAILED_TIMESTAMP, System.currentTimeMillis());
}
/**
* Whether or not the last time the user attempted to create a PIN, it failed.
*/
public synchronized boolean lastPinCreateFailed() {
return store.getLong(LAST_CREATE_FAILED_TIMESTAMP, -1) > 0;
return getLong(LAST_CREATE_FAILED_TIMESTAMP, -1) > 0;
}
/**
@ -98,13 +100,13 @@ public final class KbsValues {
* If you only want a key when it's backed up, use {@link #getPinBackedMasterKey()}.
*/
public synchronized @NonNull MasterKey getOrCreateMasterKey() {
byte[] blob = store.getBlob(MASTER_KEY, null);
byte[] blob = getStore().getBlob(MASTER_KEY, null);
if (blob == null) {
store.beginWrite()
.putBlob(MASTER_KEY, MasterKey.createNew(new SecureRandom()).serialize())
.commit();
blob = store.getBlob(MASTER_KEY, null);
getStore().beginWrite()
.putBlob(MASTER_KEY, MasterKey.createNew(new SecureRandom()).serialize())
.commit();
blob = getBlob(MASTER_KEY, null);
}
return new MasterKey(blob);
@ -119,7 +121,7 @@ public final class KbsValues {
}
private synchronized @Nullable MasterKey getMasterKey() {
byte[] blob = store.getBlob(MASTER_KEY, null);
byte[] blob = getBlob(MASTER_KEY, null);
return blob != null ? new MasterKey(blob) : null;
}
@ -133,7 +135,7 @@ public final class KbsValues {
}
public synchronized @Nullable String getLocalPinHash() {
return store.getString(LOCK_LOCAL_PIN_HASH, null);
return getString(LOCK_LOCAL_PIN_HASH, null);
}
public synchronized boolean hasPin() {
@ -141,7 +143,7 @@ public final class KbsValues {
}
public synchronized @Nullable TokenResponse getRegistrationLockTokenResponse() {
String token = store.getString(TOKEN_RESPONSE, null);
String token = getStore().getString(TOKEN_RESPONSE, null);
if (token == null) return null;

View file

@ -12,7 +12,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
/**
* Specifically handles just the UI/UX state around PINs. For actual keys, see {@link KbsValues}.
*/
public final class PinValues {
public final class PinValues extends SignalStoreValues {
private static final String TAG = Log.tag(PinValues.class);
@ -22,20 +22,22 @@ public final class PinValues {
private static final String PIN_STATE = "pin.pin_state";
public static final String PIN_REMINDERS_ENABLED = "pin.pin_reminders_enabled";
private final KeyValueStore store;
PinValues(KeyValueStore store) {
this.store = store;
super(store);
}
@Override
void onFirstEverAppLaunch() {
}
public void onEntrySuccess(@NonNull String pin) {
long nextInterval = SignalPinReminders.getNextInterval(getCurrentInterval());
Log.i(TAG, "onEntrySuccess() nextInterval: " + nextInterval);
store.beginWrite()
.putLong(LAST_SUCCESSFUL_ENTRY, System.currentTimeMillis())
.putLong(NEXT_INTERVAL, nextInterval)
.apply();
getStore().beginWrite()
.putLong(LAST_SUCCESSFUL_ENTRY, System.currentTimeMillis())
.putLong(NEXT_INTERVAL, nextInterval)
.apply();
SignalStore.kbsValues().setPinIfNotPresent(pin);
}
@ -44,10 +46,10 @@ public final class PinValues {
long nextInterval = SignalPinReminders.getPreviousInterval(getCurrentInterval());
Log.i(TAG, "onEntrySuccessWithWrongGuess() nextInterval: " + nextInterval);
store.beginWrite()
.putLong(LAST_SUCCESSFUL_ENTRY, System.currentTimeMillis())
.putLong(NEXT_INTERVAL, nextInterval)
.apply();
getStore().beginWrite()
.putLong(LAST_SUCCESSFUL_ENTRY, System.currentTimeMillis())
.putLong(NEXT_INTERVAL, nextInterval)
.apply();
SignalStore.kbsValues().setPinIfNotPresent(pin);
}
@ -56,61 +58,55 @@ public final class PinValues {
long nextInterval = SignalPinReminders.getPreviousInterval(getCurrentInterval());
Log.i(TAG, "onEntrySkipWithWrongGuess() nextInterval: " + nextInterval);
store.beginWrite()
.putLong(NEXT_INTERVAL, nextInterval)
.apply();
putLong(NEXT_INTERVAL, nextInterval);
}
public void resetPinReminders() {
long nextInterval = SignalPinReminders.INITIAL_INTERVAL;
Log.i(TAG, "resetPinReminders() nextInterval: " + nextInterval, new Throwable());
store.beginWrite()
.putLong(NEXT_INTERVAL, nextInterval)
.putLong(LAST_SUCCESSFUL_ENTRY, System.currentTimeMillis())
.apply();
getStore().beginWrite()
.putLong(NEXT_INTERVAL, nextInterval)
.putLong(LAST_SUCCESSFUL_ENTRY, System.currentTimeMillis())
.apply();
}
public long getCurrentInterval() {
return store.getLong(NEXT_INTERVAL, TextSecurePreferences.getRegistrationLockNextReminderInterval(ApplicationDependencies.getApplication()));
return getLong(NEXT_INTERVAL, TextSecurePreferences.getRegistrationLockNextReminderInterval(ApplicationDependencies.getApplication()));
}
public long getLastSuccessfulEntryTime() {
return store.getLong(LAST_SUCCESSFUL_ENTRY, TextSecurePreferences.getRegistrationLockLastReminderTime(ApplicationDependencies.getApplication()));
return getLong(LAST_SUCCESSFUL_ENTRY, TextSecurePreferences.getRegistrationLockLastReminderTime(ApplicationDependencies.getApplication()));
}
public void setKeyboardType(@NonNull PinKeyboardType keyboardType) {
store.beginWrite()
.putString(KEYBOARD_TYPE, keyboardType.getCode())
.commit();
putString(KEYBOARD_TYPE, keyboardType.getCode());
}
public void setPinRemindersEnabled(boolean enabled) {
store.beginWrite().putBoolean(PIN_REMINDERS_ENABLED, enabled).apply();
putBoolean(PIN_REMINDERS_ENABLED, enabled);
}
public boolean arePinRemindersEnabled() {
return store.getBoolean(PIN_REMINDERS_ENABLED, true);
return getBoolean(PIN_REMINDERS_ENABLED, true);
}
public @NonNull PinKeyboardType getKeyboardType() {
return PinKeyboardType.fromCode(store.getString(KEYBOARD_TYPE, null));
return PinKeyboardType.fromCode(getStore().getString(KEYBOARD_TYPE, null));
}
public void setNextReminderIntervalToAtMost(long maxInterval) {
if (store.getLong(NEXT_INTERVAL, 0) > maxInterval) {
store.beginWrite()
.putLong(NEXT_INTERVAL, maxInterval)
.apply();
if (getStore().getLong(NEXT_INTERVAL, 0) > maxInterval) {
putLong(NEXT_INTERVAL, maxInterval);
}
}
/** Should only be set by {@link org.thoughtcrime.securesms.pin.PinState} */
public void setPinState(@NonNull String pinState) {
store.beginWrite().putString(PIN_STATE, pinState).commit();
getStore().beginWrite().putString(PIN_STATE, pinState).commit();
}
public @Nullable String getPinState() {
return store.getString(PIN_STATE, null);
return getString(PIN_STATE, null);
}
}

View file

@ -3,22 +3,20 @@ package org.thoughtcrime.securesms.keyvalue;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
public final class RegistrationValues {
public final class RegistrationValues extends SignalStoreValues {
private static final String REGISTRATION_COMPLETE = "registration.complete";
private static final String PIN_REQUIRED = "registration.pin_required";
private final KeyValueStore store;
RegistrationValues(@NonNull KeyValueStore store) {
this.store = store;
super(store);
}
public synchronized void onFirstEverAppLaunch() {
store.beginWrite()
.putBoolean(REGISTRATION_COMPLETE, false)
.putBoolean(PIN_REQUIRED, true)
.commit();
getStore().beginWrite()
.putBoolean(REGISTRATION_COMPLETE, false)
.putBoolean(PIN_REQUIRED, true)
.commit();
}
public synchronized void clearRegistrationComplete() {
@ -26,18 +24,18 @@ public final class RegistrationValues {
}
public synchronized void setRegistrationComplete() {
store.beginWrite()
.putBoolean(REGISTRATION_COMPLETE, true)
.commit();
getStore().beginWrite()
.putBoolean(REGISTRATION_COMPLETE, true)
.commit();
}
@CheckResult
public synchronized boolean pinWasRequiredAtRegistration() {
return store.getBoolean(PIN_REQUIRED, false);
return getStore().getBoolean(PIN_REQUIRED, false);
}
@CheckResult
public synchronized boolean isRegistrationComplete() {
return store.getBoolean(REGISTRATION_COMPLETE, true);
return getStore().getBoolean(REGISTRATION_COMPLETE, true);
}
}

View file

@ -1,8 +1,10 @@
package org.thoughtcrime.securesms.keyvalue;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.logging.Log;
public final class RemoteConfigValues {
public final class RemoteConfigValues extends SignalStoreValues {
private static final String TAG = Log.tag(RemoteConfigValues.class);
@ -10,33 +12,35 @@ public final class RemoteConfigValues {
private static final String PENDING_CONFIG = "pending_remote_config";
private static final String LAST_FETCH_TIME = "remote_config_last_fetch_time";
private final KeyValueStore store;
RemoteConfigValues(@NonNull KeyValueStore store) {
super(store);
}
RemoteConfigValues(KeyValueStore store) {
this.store = store;
@Override
void onFirstEverAppLaunch() {
}
public String getCurrentConfig() {
return store.getString(CURRENT_CONFIG, null);
return getString(CURRENT_CONFIG, null);
}
public void setCurrentConfig(String value) {
store.beginWrite().putString(CURRENT_CONFIG, value).apply();
putString(CURRENT_CONFIG, value);
}
public String getPendingConfig() {
return store.getString(PENDING_CONFIG, getCurrentConfig());
return getString(PENDING_CONFIG, getCurrentConfig());
}
public void setPendingConfig(String value) {
store.beginWrite().putString(PENDING_CONFIG, value).apply();
putString(PENDING_CONFIG, value);
}
public long getLastFetchTime() {
return store.getLong(LAST_FETCH_TIME, 0);
return getLong(LAST_FETCH_TIME, 0);
}
public void setLastFetchTime(long time) {
store.beginWrite().putLong(LAST_FETCH_TIME, time).apply();
putLong(LAST_FETCH_TIME, time);
}
}

View file

@ -15,7 +15,27 @@ public final class SignalStore {
private static final String LAST_PREKEY_REFRESH_TIME = "last_prekey_refresh_time";
private static final String MESSAGE_REQUEST_ENABLE_TIME = "message_request_enable_time";
private SignalStore() {}
private static final SignalStore INSTANCE = new SignalStore();
private final KeyValueStore store;
private final KbsValues kbsValues;
private final RegistrationValues registrationValues;
private final PinValues pinValues;
private final RemoteConfigValues remoteConfigValues;
private final StorageServiceValues storageServiceValues;
private final UiHints uiHints;
private final TooltipValues tooltipValues;
private SignalStore() {
this.store = ApplicationDependencies.getKeyValueStore();
this.kbsValues = new KbsValues(store);
this.registrationValues = new RegistrationValues(store);
this.pinValues = new PinValues(store);
this.remoteConfigValues = new RemoteConfigValues(store);
this.storageServiceValues = new StorageServiceValues(store);
this.uiHints = new UiHints(store);
this.tooltipValues = new TooltipValues(store);
}
public static void onFirstEverAppLaunch() {
registrationValues().onFirstEverAppLaunch();
@ -24,31 +44,31 @@ public final class SignalStore {
}
public static @NonNull KbsValues kbsValues() {
return new KbsValues(getStore());
return INSTANCE.kbsValues;
}
public static @NonNull RegistrationValues registrationValues() {
return new RegistrationValues(getStore());
return INSTANCE.registrationValues;
}
public static @NonNull PinValues pinValues() {
return new PinValues(getStore());
return INSTANCE.pinValues;
}
public static @NonNull RemoteConfigValues remoteConfigValues() {
return new RemoteConfigValues(getStore());
return INSTANCE.remoteConfigValues;
}
public static @NonNull StorageServiceValues storageServiceValues() {
return new StorageServiceValues(getStore());
return INSTANCE.storageServiceValues;
}
public static @NonNull UiHints uiHints() {
return new UiHints(getStore());
return INSTANCE.uiHints;
}
public static @NonNull TooltipValues tooltips() {
return new TooltipValues(getStore());
return INSTANCE.tooltipValues;
}
public static @NonNull GroupsV2AuthorizationSignalStoreCache groupsV2AuthorizationCache() {
@ -84,7 +104,7 @@ public final class SignalStore {
}
private static @NonNull KeyValueStore getStore() {
return ApplicationDependencies.getKeyValueStore();
return INSTANCE.store;
}
private static void putBlob(@NonNull String key, byte[] value) {

View file

@ -0,0 +1,66 @@
package org.thoughtcrime.securesms.keyvalue;
import androidx.annotation.NonNull;
abstract class SignalStoreValues {
private final KeyValueStore store;
SignalStoreValues(@NonNull KeyValueStore store) {
this.store = store;
}
@NonNull KeyValueStore getStore() {
return store;
}
abstract void onFirstEverAppLaunch();
String getString(String key, String defaultValue) {
return store.getString(key, defaultValue);
}
int getInteger(String key, int defaultValue) {
return store.getInteger(key, defaultValue);
}
long getLong(String key, long defaultValue) {
return store.getLong(key, defaultValue);
}
boolean getBoolean(String key, boolean defaultValue) {
return store.getBoolean(key, defaultValue);
}
float getFloat(String key, float defaultValue) {
return store.getFloat(key, defaultValue);
}
byte[] getBlob(String key, byte[] defaultValue) {
return store.getBlob(key, defaultValue);
}
void putBlob(@NonNull String key, byte[] value) {
store.beginWrite().putBlob(key, value).apply();
}
void putBoolean(@NonNull String key, boolean value) {
store.beginWrite().putBoolean(key, value).apply();
}
void putFloat(@NonNull String key, float value) {
store.beginWrite().putFloat(key, value).apply();
}
void putInteger(@NonNull String key, int value) {
store.beginWrite().putInteger(key, value).apply();
}
void putLong(@NonNull String key, long value) {
store.beginWrite().putLong(key, value).apply();
}
void putString(@NonNull String key, String value) {
store.beginWrite().putString(key, value).apply();
}
}

View file

@ -8,15 +8,17 @@ import org.whispersystems.signalservice.api.storage.StorageKey;
import java.security.SecureRandom;
public class StorageServiceValues {
public class StorageServiceValues extends SignalStoreValues {
private static final String LAST_SYNC_TIME = "storage.last_sync_time";
private static final String NEEDS_ACCOUNT_RESTORE = "storage.needs_account_restore";
private final KeyValueStore store;
StorageServiceValues(@NonNull KeyValueStore store) {
this.store = store;
super(store);
}
@Override
void onFirstEverAppLaunch() {
}
public synchronized StorageKey getOrCreateStorageKey() {
@ -24,18 +26,18 @@ public class StorageServiceValues {
}
public long getLastSyncTime() {
return store.getLong(LAST_SYNC_TIME, 0);
return getLong(LAST_SYNC_TIME, 0);
}
public void onSyncCompleted() {
store.beginWrite().putLong(LAST_SYNC_TIME, System.currentTimeMillis()).apply();
putLong(LAST_SYNC_TIME, System.currentTimeMillis());
}
public boolean needsAccountRestore() {
return store.getBoolean(NEEDS_ACCOUNT_RESTORE, false);
return getBoolean(NEEDS_ACCOUNT_RESTORE, false);
}
public void setNeedsAccountRestore(boolean value) {
store.beginWrite().putBoolean(NEEDS_ACCOUNT_RESTORE, value).apply();
putBoolean(NEEDS_ACCOUNT_RESTORE, value);
}
}

View file

@ -4,24 +4,23 @@ import androidx.annotation.NonNull;
import org.whispersystems.signalservice.api.storage.StorageKey;
public class TooltipValues {
public class TooltipValues extends SignalStoreValues {
private static final String BLUR_HUD_ICON = "tooltip.blur_hud_icon";
private final KeyValueStore store;
TooltipValues(@NonNull KeyValueStore store) {
this.store = store;
super(store);
}
@Override
public void onFirstEverAppLaunch() {
}
public boolean hasSeenBlurHudIconTooltip() {
return store.getBoolean(BLUR_HUD_ICON, false);
return getBoolean(BLUR_HUD_ICON, false);
}
public void markBlurHudIconTooltipSeen() {
store.beginWrite().putBoolean(BLUR_HUD_ICON, true).apply();
putBoolean(BLUR_HUD_ICON, true);
}
}

View file

@ -1,24 +1,25 @@
package org.thoughtcrime.securesms.keyvalue;
public class UiHints {
import androidx.annotation.NonNull;
public class UiHints extends SignalStoreValues {
private static final String HAS_SEEN_GROUP_SETTINGS_MENU_TOAST = "uihints.has_seen_group_settings_menu_toast";
private final KeyValueStore store;
UiHints(KeyValueStore store) {
this.store = store;
UiHints(@NonNull KeyValueStore store) {
super(store);
}
@Override
void onFirstEverAppLaunch() {
markHasSeenGroupSettingsMenuToast();
}
public void markHasSeenGroupSettingsMenuToast() {
store.beginWrite().putBoolean(HAS_SEEN_GROUP_SETTINGS_MENU_TOAST, true).apply();
putBoolean(HAS_SEEN_GROUP_SETTINGS_MENU_TOAST, true);
}
public boolean hasSeenGroupSettingsMenuToast() {
return store.getBoolean(HAS_SEEN_GROUP_SETTINGS_MENU_TOAST, false);
return getBoolean(HAS_SEEN_GROUP_SETTINGS_MENU_TOAST, false);
}
}