Move plaintext preferences out of TextSecurePreferences.

This commit is contained in:
Greyson Parrelli
2026-09-10 17:10:13 -04:00
committed by Cody Henthorne
parent 98a4fe1069
commit 766f4a4c64
27 changed files with 155 additions and 237 deletions
@@ -12,6 +12,7 @@ import org.thoughtcrime.securesms.jobs.DeleteAbandonedAttachmentsJob;
import org.thoughtcrime.securesms.jobs.EmojiSearchIndexDownloadJob;
import org.thoughtcrime.securesms.jobs.QuoteThumbnailBackfillJob;
import org.thoughtcrime.securesms.jobs.StickerPackDownloadJob;
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.migrations.ApplicationMigrations;
import org.thoughtcrime.securesms.migrations.QuoteThumbnailBackfillMigrationJob;
@@ -34,9 +35,9 @@ public final class AppInitialization {
public static void onFirstEverAppLaunch(@NonNull Context context) {
Log.i(TAG, "onFirstEverAppLaunch()");
TextSecurePreferences.setAppMigrationVersion(context, ApplicationMigrations.CURRENT_VERSION);
PlainTextKeyValueStore.setAppMigrationVersion(ApplicationMigrations.CURRENT_VERSION);
TextSecurePreferences.setJobManagerVersion(context, JobManager.CURRENT_VERSION);
TextSecurePreferences.setLastVersionCode(context, BuildConfig.VERSION_CODE);
PlainTextKeyValueStore.setLastVersionCode(BuildConfig.VERSION_CODE);
TextSecurePreferences.setHasSeenStickerIntroTooltip(context, true);
SignalStore.settings().setPassphraseDisabled(true);
TextSecurePreferences.setReadReceiptsEnabled(context, true);
@@ -80,9 +81,9 @@ public final class AppInitialization {
public static void onRepairFirstEverAppLaunch(@NonNull Context context) {
Log.w(TAG, "onRepairFirstEverAppLaunch()");
TextSecurePreferences.setAppMigrationVersion(context, ApplicationMigrations.CURRENT_VERSION);
PlainTextKeyValueStore.setAppMigrationVersion(ApplicationMigrations.CURRENT_VERSION);
TextSecurePreferences.setJobManagerVersion(context, JobManager.CURRENT_VERSION);
TextSecurePreferences.setLastVersionCode(context, BuildConfig.VERSION_CODE);
PlainTextKeyValueStore.setLastVersionCode(BuildConfig.VERSION_CODE);
TextSecurePreferences.setHasSeenStickerIntroTooltip(context, true);
SignalStore.settings().setPassphraseDisabled(true);
AppDependencies.getMegaphoneRepository().onFirstEverAppLaunch();
@@ -95,6 +95,7 @@ import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
import org.thoughtcrime.securesms.jobs.RetrieveRemoteAnnouncementsJob;
import org.thoughtcrime.securesms.jobs.StoryOnboardingDownloadJob;
import org.thoughtcrime.securesms.keyvalue.KeepMessagesDuration;
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger;
import org.thoughtcrime.securesms.logging.PersistentLogger;
@@ -638,6 +639,7 @@ public class ApplicationContext extends Application implements AppForegroundObse
@Override
protected void attachBaseContext(Context base) {
PlainTextKeyValueStore.init(base);
DynamicLanguageContextWrapper.updateContext(base);
super.attachBaseContext(base);
}
@@ -87,7 +87,7 @@ public abstract class BaseActivity extends AppCompatActivity {
@Override
public void applyOverrideConfiguration(@NonNull Configuration overrideConfiguration) {
DynamicLanguageContextWrapper.prepareOverrideConfiguration(this, overrideConfiguration);
DynamicLanguageContextWrapper.prepareOverrideConfiguration(overrideConfiguration);
super.applyOverrideConfiguration(overrideConfiguration);
}
@@ -200,7 +200,6 @@ class MainActivity :
private const val KEY_STARTING_TAB = "STARTING_TAB"
private const val KEY_DETAIL_LOCATION = "DETAIL_LOCATION"
private const val KEY_EXIT_DETAIL = "EXIT_DETAIL"
const val RESULT_CONFIG_CHANGED = RESULT_FIRST_USER + 901
/** Width the navigation rail occupies inside the list pane. */
private val RAIL_WIDTH = 80.dp
@@ -249,11 +248,7 @@ class MainActivity :
VitalsViewModel(application)
}
private val openSettings: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_CONFIG_CHANGED) {
recreate()
}
}
private val openSettings: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { }
private val toolbarViewModel: MainToolbarViewModel by viewModels()
private val toolbarCallback = ToolbarCallback()
@@ -762,10 +757,6 @@ class MainActivity :
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == MainNavigator.REQUEST_CONFIG_CHANGES && resultCode == RESULT_CONFIG_CHANGED) {
recreate()
}
if (resultCode == RESULT_OK && requestCode == CreateSvrPinActivity.REQUEST_NEW_PIN) {
mainNavigationViewModel.snackbarRegistry.emit(SnackbarState(message = getString(R.string.ConfirmKbsPinFragment__pin_created), hostKey = MainSnackbarHostKey.MainChrome))
mainNavigationViewModel.onEvent(MainNavigationEvents.MegaphoneCompleted(Megaphones.Event.PINS_FOR_ALL))
@@ -65,7 +65,7 @@ public class PassphraseCreateActivity extends PassphraseActivity {
if (SignalStore.account().getPni() != null) {
SignalStore.account().generatePniIdentityKeyIfNecessary();
}
VersionTracker.updateLastSeenVersion(PassphraseCreateActivity.this);
VersionTracker.updateLastSeenVersion();
return null;
}
@@ -12,7 +12,6 @@ import io.reactivex.rxjava3.subjects.Subject
import org.signal.core.util.getParcelableExtraCompat
import org.signal.core.util.logging.Log
import org.signal.donations.InAppPaymentType
import org.thoughtcrime.securesms.MainActivity
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.settings.DSLSettingsActivity
import org.thoughtcrime.securesms.components.settings.app.routes.AppSettingsRoute
@@ -22,8 +21,6 @@ import org.thoughtcrime.securesms.help.HelpFragment
import org.thoughtcrime.securesms.keyvalue.SettingsValues
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.profiles.manage.UsernameEditMode
import org.thoughtcrime.securesms.service.KeyCachingService
import org.thoughtcrime.securesms.util.CachedInflater
import org.thoughtcrime.securesms.util.DynamicTheme
import org.thoughtcrime.securesms.util.Environment
import org.thoughtcrime.securesms.util.SignalE164Util
@@ -31,15 +28,12 @@ import org.thoughtcrime.securesms.util.navigation.safeNavigate
private const val START_ROUTE = "app.settings.args.START_ROUTE"
private const val NOTIFICATION_CATEGORY = "android.intent.category.NOTIFICATION_PREFERENCES"
private const val STATE_WAS_CONFIGURATION_UPDATED = "app.settings.state.configuration.updated"
private const val EXTRA_PERFORM_ACTION_ON_CREATE = "extra_perform_action_on_create"
class AppSettingsActivity : DSLSettingsActivity(), GooglePayComponent {
private val TAG = Log.tag(AppSettingsActivity::class)
private var wasConfigurationUpdated = false
override val googlePayRepository: GooglePayRepository by lazy { GooglePayRepository(this) }
override val googlePayResultPublisher: Subject<GooglePayComponent.GooglePayResult> = PublishSubject.create()
@@ -101,10 +95,6 @@ class AppSettingsActivity : DSLSettingsActivity(), GooglePayComponent {
intent = intent.putExtra(START_ROUTE, AppSettingsRoute.Empty)
if (startingAction == null && savedInstanceState != null) {
wasConfigurationUpdated = savedInstanceState.getBoolean(STATE_WAS_CONFIGURATION_UPDATED)
}
startingAction?.let {
navController.safeNavigate(it)
}
@@ -113,13 +103,6 @@ class AppSettingsActivity : DSLSettingsActivity(), GooglePayComponent {
if (key == SettingsValues.THEME) {
DynamicTheme.setDefaultDayNightMode(this)
recreate()
} else if (key == SettingsValues.LANGUAGE) {
CachedInflater.from(this).clear()
wasConfigurationUpdated = true
recreate()
val intent = Intent(this, KeyCachingService::class.java)
intent.action = KeyCachingService.LOCALE_CHANGE_EVENT
startService(intent)
}
}
@@ -141,17 +124,6 @@ class AppSettingsActivity : DSLSettingsActivity(), GooglePayComponent {
startActivity(intent)
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putBoolean(STATE_WAS_CONFIGURATION_UPDATED, wasConfigurationUpdated)
}
override fun onWillFinish() {
if (wasConfigurationUpdated) {
setResult(MainActivity.RESULT_CONFIG_CHANGED)
}
}
override fun resolveNavGraphId(): Int = R.navigation.app_settings_with_change_number
override fun resolveStartBundle(): Bundle? = null
@@ -8,6 +8,7 @@ import kotlinx.coroutines.flow.update
import org.signal.core.util.AppUtil
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobs.EmojiSearchIndexDownloadJob
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore
import org.thoughtcrime.securesms.keyvalue.SettingsValues.Theme
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.util.SplashScreenUtil
@@ -28,7 +29,7 @@ class AppearanceSettingsViewModel : ViewModel() {
fun setLanguage(language: String) {
store.update { it.copy(language = language) }
SignalStore.settings.language = language
PlainTextKeyValueStore.language = language
EmojiSearchIndexDownloadJob.scheduleImmediately()
AppUtil.restart(AppDependencies.application)
}
@@ -42,7 +43,7 @@ class AppearanceSettingsViewModel : ViewModel() {
return AppearanceSettingsState(
SignalStore.settings.theme,
SignalStore.settings.messageFontSize,
SignalStore.settings.language,
PlainTextKeyValueStore.language,
SignalStore.settings.useCompactNavigationBar
)
}
@@ -7,22 +7,22 @@ package org.thoughtcrime.securesms.crypto
import android.content.Context
import org.signal.core.util.crypto.AttachmentSecretStore
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore
object AppAttachmentSecretStore : AttachmentSecretStore {
override fun getAttachmentUnencryptedSecret(context: Context): String? {
return TextSecurePreferences.getAttachmentUnencryptedSecret(context)
return PlainTextKeyValueStore.attachmentLegacyUnencryptedSecret
}
override fun getAttachmentEncryptedSecret(context: Context): String? {
return TextSecurePreferences.getAttachmentEncryptedSecret(context)
return PlainTextKeyValueStore.attachmentEncryptedSecret
}
override fun setAttachmentEncryptedSecret(context: Context, secret: String) {
TextSecurePreferences.setAttachmentEncryptedSecret(context, secret)
PlainTextKeyValueStore.attachmentEncryptedSecret = secret
}
override fun setAttachmentUnencryptedSecret(context: Context, secret: String?) {
TextSecurePreferences.setAttachmentUnencryptedSecret(context, secret)
PlainTextKeyValueStore.attachmentLegacyUnencryptedSecret = secret
}
}
@@ -6,7 +6,7 @@ import android.content.Context;
import androidx.annotation.NonNull;
import org.signal.core.util.crypto.KeyStoreHelper;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore;
import java.io.IOException;
import java.security.SecureRandom;
@@ -23,7 +23,7 @@ public final class DatabaseSecretProvider {
if (instance == null) {
synchronized (DatabaseSecretProvider.class) {
if (instance == null) {
instance = getOrCreate(context);
instance = getOrCreate();
}
}
}
@@ -34,24 +34,23 @@ public final class DatabaseSecretProvider {
private DatabaseSecretProvider() {
}
private static @NonNull DatabaseSecret getOrCreate(@NonNull Context context) {
String unencryptedSecret = TextSecurePreferences.getDatabaseUnencryptedSecret(context);
String encryptedSecret = TextSecurePreferences.getDatabaseEncryptedSecret(context);
private static @NonNull DatabaseSecret getOrCreate() {
String unencryptedSecret = PlainTextKeyValueStore.getDatabaseLegacyUnencryptedSecret();
String encryptedSecret = PlainTextKeyValueStore.getDatabaseEncryptedSecret();
if (unencryptedSecret != null) return getUnencryptedDatabaseSecret(context, unencryptedSecret);
if (unencryptedSecret != null) return getUnencryptedDatabaseSecret(unencryptedSecret);
else if (encryptedSecret != null) return getEncryptedDatabaseSecret(encryptedSecret);
else return createAndStoreDatabaseSecret(context);
else return createAndStoreDatabaseSecret();
}
private static @NonNull DatabaseSecret getUnencryptedDatabaseSecret(@NonNull Context context, @NonNull String unencryptedSecret)
{
private static @NonNull DatabaseSecret getUnencryptedDatabaseSecret(@NonNull String unencryptedSecret) {
try {
DatabaseSecret databaseSecret = new DatabaseSecret(unencryptedSecret);
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
TextSecurePreferences.setDatabaseUnencryptedSecret(context, null);
PlainTextKeyValueStore.setDatabaseEncryptedSecret(encryptedSecret.serialize());
PlainTextKeyValueStore.setDatabaseLegacyUnencryptedSecret(null);
return databaseSecret;
} catch (IOException e) {
@@ -64,7 +63,7 @@ public final class DatabaseSecretProvider {
return new DatabaseSecret(KeyStoreHelper.unseal(encryptedSecret));
}
private static @NonNull DatabaseSecret createAndStoreDatabaseSecret(@NonNull Context context) {
private static @NonNull DatabaseSecret createAndStoreDatabaseSecret() {
SecureRandom random = new SecureRandom();
byte[] secret = new byte[32];
random.nextBytes(secret);
@@ -72,7 +71,7 @@ public final class DatabaseSecretProvider {
DatabaseSecret databaseSecret = new DatabaseSecret(secret);
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
PlainTextKeyValueStore.setDatabaseEncryptedSecret(encryptedSecret.serialize());
return databaseSecret;
}
@@ -5,7 +5,7 @@ import org.signal.core.util.SqlUtil
import org.signal.core.util.Stopwatch
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.database.SQLiteDatabase
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore
@Suppress("ClassName")
object V168_SingleMessageTableMigration : SignalDatabaseMigration {
@@ -89,7 +89,7 @@ object V168_SingleMessageTableMigration : SignalDatabaseMigration {
stopwatch.stop(TAG)
SignalStore.plaintext.smsMigrationIdOffset = nextMmsId
PlainTextKeyValueStore.smsMigrationIdOffset = nextMmsId
}
private fun copySmsToMms(db: SQLiteDatabase, idOffset: Long) {
@@ -95,7 +95,7 @@ public final class EmojiSearchIndexDownloadJob extends BaseJob {
protected void onRun() throws Exception {
Manifest manifest = downloadManifest();
Locale locale = DynamicLanguageContextWrapper.getUsersSelectedLocale(context);
Locale locale = DynamicLanguageContextWrapper.getUsersSelectedLocale();
String remoteLanguage = findMatchingLanguage(locale, manifest.getLanguages());
if (manifest.getVersion() == SignalStore.emoji().getSearchVersion() &&
@@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.JsonJobData
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.notifications.v2.ConversationId
import org.thoughtcrime.securesms.recipients.Recipient
@@ -405,8 +406,8 @@ class RetrieveRemoteAnnouncementsJob private constructor(private val force: Bool
val potentialNoteUrls = mutableListOf<String>()
if (SignalStore.settings.language != "zz") {
potentialNoteUrls += "$this/${SignalStore.settings.language}.json"
if (PlainTextKeyValueStore.language != "zz") {
potentialNoteUrls += "$this/${PlainTextKeyValueStore.language}.json"
}
for (index in 0 until localeList.size()) {
@@ -12,6 +12,7 @@ import org.thoughtcrime.securesms.database.model.StoryType
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.releasechannel.ReleaseChannel
@@ -168,8 +169,8 @@ class StoryOnboardingDownloadJob private constructor(parameters: Parameters) : B
val potentialOnboardingUrlLanguages = mutableListOf<String>()
if (SignalStore.settings.language != "zz") {
potentialOnboardingUrlLanguages += SignalStore.settings.language
if (PlainTextKeyValueStore.language != "zz") {
potentialOnboardingUrlLanguages += PlainTextKeyValueStore.language
}
for (index in 0 until localeList.size()) {
@@ -0,0 +1,85 @@
package org.thoughtcrime.securesms.keyvalue
import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import org.thoughtcrime.securesms.BuildConfig
/**
* There are some values that you can't store in the normal encrypted [KeyValueStore].
* Usually, it's because the value you're storing is needed to *open* the database that backs [SignalStore],
* or is otherwise related to the state of the database itself. Regardless, this is just a normal
* shared-prefs-backed class.
*/
object PlainTextKeyValueStore {
const val SMS_MIGRATION_ID_OFFSET = "sms_migration_id_offset"
private const val DATABASE_ENCRYPTED_SECRET = "pref_database_encrypted_secret"
private const val DATABASE_UNENCRYPTED_SECRET = "pref_database_unencrypted_secret"
private const val ATTACHMENT_ENCRYPTED_SECRET = "pref_attachment_encrypted_secret"
private const val ATTACHMENT_UNENCRYPTED_SECRET = "pref_attachment_unencrypted_secret"
private const val APP_MIGRATION_VERSION = "pref_app_migration_version"
private const val LAST_VERSION_CODE = "last_version_code"
private const val LANGUAGE = "pref_language"
private lateinit var sharedPrefs: SharedPreferences
/**
* Must be called from [android.app.Application.attachBaseContext] before anything else has a chance to read from
* this store.
*/
@JvmStatic
fun init(context: Context) {
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context)
}
/** Stores the ID offset that was determined during the big migration that moved all SMS messages into the MMS table. */
@JvmStatic
var smsMigrationIdOffset: Long
get() = sharedPrefs.getLong(SMS_MIGRATION_ID_OFFSET, -1)
set(value) = sharedPrefs.edit(commit = true) { putLong(SMS_MIGRATION_ID_OFFSET, value) }
/** The keystore-sealed secret used to open the main database. */
@JvmStatic
var databaseEncryptedSecret: String?
get() = sharedPrefs.getString(DATABASE_ENCRYPTED_SECRET, null)
set(value) = sharedPrefs.edit(commit = true) { putString(DATABASE_ENCRYPTED_SECRET, value) }
/** Legacy plaintext database secret, only present until it's been sealed into [databaseEncryptedSecret]. */
@JvmStatic
var databaseLegacyUnencryptedSecret: String?
get() = sharedPrefs.getString(DATABASE_UNENCRYPTED_SECRET, null)
set(value) = sharedPrefs.edit(commit = true) { putString(DATABASE_UNENCRYPTED_SECRET, value) }
/** The keystore-sealed secret used to decrypt attachments on disk. */
@JvmStatic
var attachmentEncryptedSecret: String?
get() = sharedPrefs.getString(ATTACHMENT_ENCRYPTED_SECRET, null)
set(value) = sharedPrefs.edit(commit = true) { putString(ATTACHMENT_ENCRYPTED_SECRET, value) }
/** Legacy plaintext attachment secret, only present until it's been sealed into [attachmentEncryptedSecret]. */
@JvmStatic
var attachmentLegacyUnencryptedSecret: String?
get() = sharedPrefs.getString(ATTACHMENT_UNENCRYPTED_SECRET, null)
set(value) = sharedPrefs.edit(commit = true) { putString(ATTACHMENT_UNENCRYPTED_SECRET, value) }
/** The last [org.thoughtcrime.securesms.migrations.ApplicationMigrations] version that ran to completion. */
@JvmStatic
var appMigrationVersion: Int
get() = sharedPrefs.getInt(APP_MIGRATION_VERSION, 1)
set(value) = sharedPrefs.edit(commit = true) { putInt(APP_MIGRATION_VERSION, value) }
/** The version code the app was last launched at. */
@JvmStatic
var lastVersionCode: Int
get() = sharedPrefs.getInt(LAST_VERSION_CODE, BuildConfig.VERSION_CODE)
set(value) = sharedPrefs.edit(commit = true) { putInt(LAST_VERSION_CODE, value) }
/** The user's chosen app language, or "zz" to follow the system. */
@JvmStatic
var language: String
get() = sharedPrefs.getString(LANGUAGE, "zz") ?: "zz"
set(value) = sharedPrefs.edit(commit = true) { putString(LANGUAGE, value) }
}
@@ -1,33 +0,0 @@
package org.thoughtcrime.securesms.keyvalue
import android.annotation.SuppressLint
import android.content.Context
import androidx.preference.PreferenceManager
/**
* There are some values that you can't, for whatever reason, store in the normal encrypted [KeyValueStore].
* Usually, it's because the value your storing is _related to_ the database. Regardless, this is just a normal
* shared-prefs-backed class. Do not put anything in here that you wouldn't be comfortable storing in plain text.
*
* A good rule of thumb might be: if you're not comfortable logging it, then you shouldn't be comfortable putting
* it in here.
*/
class PlainTextSharedPrefsDataStore(private val context: Context) {
companion object {
const val SMS_MIGRATION_ID_OFFSET = "sms_migration_id_offset"
}
private val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context)
/**
* Stores the ID offset that was determined during the big migration that moved all SMS messages into the MMS table.
*/
var smsMigrationIdOffset: Long
get() = sharedPrefs.getLong(SMS_MIGRATION_ID_OFFSET, -1)
@SuppressLint("ApplySharedPref")
set(value) {
sharedPrefs.edit().putLong(SMS_MIGRATION_ID_OFFSET, value).commit()
}
}
@@ -37,7 +37,6 @@ class SettingsValues internal constructor(store: KeyValueStore, context: Context
const val THEME = "settings.theme"
const val MESSAGE_FONT_SIZE = "settings.message.font.size"
const val LANGUAGE = "settings.language"
const val PREFER_SYSTEM_EMOJI = "settings.use.system.emoji"
const val ENTER_KEY_SENDS = "settings.enter.key.sends"
const val BACKUPS_ENABLED = "settings.backups.enabled"
@@ -113,7 +112,6 @@ class SettingsValues internal constructor(store: KeyValueStore, context: Context
CALL_DATA_MODE,
THREAD_TRIM_LENGTH,
THREAD_TRIM_ENABLED,
LANGUAGE,
THEME,
MESSAGE_FONT_SIZE,
PREFER_SYSTEM_EMOJI,
@@ -222,13 +220,6 @@ class SettingsValues internal constructor(store: KeyValueStore, context: Context
return possibleQuoteSizes[sizeIndex]
}
var language: String
get() = TextSecurePreferences.getLanguage(AppDependencies.application)
set(value) {
TextSecurePreferences.setLanguage(AppDependencies.application, value)
configurationSettingChanged.postValue(LANGUAGE)
}
var isPreferSystemEmoji: Boolean
get() = getBoolean(PREFER_SYSTEM_EMOJI, TextSecurePreferences.isSystemEmojiPreferred(AppDependencies.application))
set(value) {
@@ -40,8 +40,6 @@ class SignalStore(context: Application, private val store: KeyValueStore) {
val callQualityValues = CallQualityValues(store)
val labsValues = LabsValues(store)
val plainTextValues = PlainTextSharedPrefsDataStore(context)
companion object {
private var instance: SignalStore? = null
@@ -293,9 +291,6 @@ class SignalStore(context: Application, private val store: KeyValueStore) {
val groupsV2AciAuthorizationCache: GroupsV2AuthorizationSignalStoreCache
get() = GroupsV2AuthorizationSignalStoreCache.createAciCache(instance!!.store)
val plaintext: PlainTextSharedPrefsDataStore
get() = instance!!.plainTextValues
fun getPreferenceDataStore(): PreferenceDataStore {
return SignalPreferenceDataStore(instance!!.store)
}
@@ -562,7 +562,7 @@ public final class Megaphones {
!NotificationChannels.getInstance().isMessagesChannelGroupEnabled() ||
!NotificationChannels.getInstance().areNotificationsEnabled();
if (shouldShow) {
Locale locale = DynamicLanguageContextWrapper.getUsersSelectedLocale(context);
Locale locale = DynamicLanguageContextWrapper.getUsersSelectedLocale();
if (!new TranslationDetection(context, locale)
.textExistsInUsersLanguage(R.string.NotificationsMegaphone_turn_on_notifications,
R.string.NotificationsMegaphone_never_miss_a_message,
@@ -13,9 +13,9 @@ import org.greenrobot.eventbus.ThreadMode;
import org.signal.core.util.Util;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.stickers.BlessedPacks;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.VersionTracker;
import java.util.Currency;
@@ -227,20 +227,20 @@ public class ApplicationMigrations {
*/
public static void onApplicationCreate(@NonNull Context context, @NonNull JobManager jobManager) {
if (isLegacyUpdate(context)) {
Log.i(TAG, "Detected the need for a legacy update. Last seen canonical version: " + VersionTracker.getLastSeenVersion(context));
TextSecurePreferences.setAppMigrationVersion(context, 0);
Log.i(TAG, "Detected the need for a legacy update. Last seen canonical version: " + VersionTracker.getLastSeenVersion());
PlainTextKeyValueStore.setAppMigrationVersion(0);
}
if (!isUpdate(context)) { // this returned false
Log.d(TAG, "Not an update. Skipping.");
VersionTracker.updateLastSeenVersion(context);
VersionTracker.updateLastSeenVersion();
return;
} else {
Log.d(TAG, "About to update. Clearing deprecation flag.", true);
SignalStore.misc().setClientDeprecated(false);
}
final int lastSeenVersion = TextSecurePreferences.getAppMigrationVersion(context);
final int lastSeenVersion = PlainTextKeyValueStore.getAppMigrationVersion();
Log.d(TAG, "currentVersion: " + CURRENT_VERSION + ", lastSeenVersion: " + lastSeenVersion);
LinkedHashMap<Integer, MigrationJob> migrationJobs = getMigrationJobs(context, lastSeenVersion);
@@ -285,13 +285,13 @@ public class ApplicationMigrations {
}
Log.i(TAG, "Updating last migration version to " + event.getVersion());
TextSecurePreferences.setAppMigrationVersion(context, event.getVersion());
PlainTextKeyValueStore.setAppMigrationVersion(event.getVersion());
if (event.getVersion() == CURRENT_VERSION) {
Log.i(TAG, "Migration complete. Took " + (System.currentTimeMillis() - startTime) + " ms.");
EventBus.getDefault().unregister(this);
VersionTracker.updateLastSeenVersion(context);
VersionTracker.updateLastSeenVersion();
UI_BLOCKING_MIGRATION_RUNNING.setValue(false);
} else if (event.getVersion() >= uiVersion) {
Log.i(TAG, "Version is >= the UI-blocking version. Posting 'false'.");
@@ -301,8 +301,8 @@ public class ApplicationMigrations {
});
} else {
Log.d(TAG, "No migrations.");
TextSecurePreferences.setAppMigrationVersion(context, CURRENT_VERSION);
VersionTracker.updateLastSeenVersion(context);
PlainTextKeyValueStore.setAppMigrationVersion(CURRENT_VERSION);
VersionTracker.updateLastSeenVersion();
UI_BLOCKING_MIGRATION_RUNNING.setValue(false);
}
}
@@ -328,7 +328,7 @@ public class ApplicationMigrations {
* current version.
*/
public static boolean isUpdate(@NonNull Context context) {
return isLegacyUpdate(context) || TextSecurePreferences.getAppMigrationVersion(context) < CURRENT_VERSION;
return isLegacyUpdate(context) || PlainTextKeyValueStore.getAppMigrationVersion() < CURRENT_VERSION;
}
private static LinkedHashMap<Integer, MigrationJob> getMigrationJobs(@NonNull Context context, int lastSeenVersion) {
@@ -1005,6 +1005,6 @@ public class ApplicationMigrations {
}
private static boolean isLegacyUpdate(@NonNull Context context) {
return VersionTracker.getLastSeenVersion(context) < LEGACY_CANONICAL_VERSION;
return VersionTracker.getLastSeenVersion() < LEGACY_CANONICAL_VERSION;
}
}
@@ -95,7 +95,7 @@ public class LegacyMigrationJob extends MigrationJob {
@Override
void performMigration() throws RetryLaterException {
Log.i(TAG, "Running background upgrade..");
int lastSeenVersion = VersionTracker.getLastSeenVersion(context);
int lastSeenVersion = VersionTracker.getLastSeenVersion();
if (lastSeenVersion < NO_V1_VERSION) {
File v1sessions = new File(context.getFilesDir(), "sessions");
@@ -5,7 +5,7 @@ import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.JsonJobData
import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore
/**
* Updates the data in queued jobs to reflect the new ids SMS messages get assigned during the table merge migration.
@@ -31,7 +31,7 @@ internal class UpdateSmsJobsMigrationJob(
override fun isUiBlocking(): Boolean = false
override fun performMigration() {
val idOffset = SignalStore.plaintext.smsMigrationIdOffset
val idOffset = PlainTextKeyValueStore.smsMigrationIdOffset
if (idOffset < 0) {
Log.w(TAG, "Invalid ID offset of $idOffset -- this shouldn't be possible!")
return
@@ -49,7 +49,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.migrations.ApplicationMigrations;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.signal.core.util.AppForegroundObserver;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.signal.core.util.ServiceUtil;
import java.util.Objects;
@@ -74,9 +73,6 @@ public class KeyCachingService extends Service {
private static final String PASSPHRASE_EXPIRED_EVENT = BuildConfig.APPLICATION_ID + ".service.action.PASSPHRASE_EXPIRED_EVENT";
public static final String CLEAR_KEY_ACTION = BuildConfig.APPLICATION_ID + ".service.action.CLEAR_KEY";
public static final String DISABLE_ACTION = BuildConfig.APPLICATION_ID + ".service.action.DISABLE";
public static final String LOCALE_CHANGE_EVENT = BuildConfig.APPLICATION_ID + ".service.action.LOCALE_CHANGE_EVENT";
private DynamicLanguage dynamicLanguage = new DynamicLanguage();
private final IBinder binder = new KeySetBinder();
@@ -143,7 +139,6 @@ public class KeyCachingService extends Service {
case CLEAR_KEY_ACTION: handleClearKey(); break;
case PASSPHRASE_EXPIRED_EVENT: handleClearKey(); break;
case DISABLE_ACTION: handleDisableService(); break;
case LOCALE_CHANGE_EVENT: handleLocaleChanged(); break;
case LOCK_TOGGLED_EVENT: handleLockToggled(); break;
}
}
@@ -219,11 +214,6 @@ public class KeyCachingService extends Service {
}
}
private void handleLocaleChanged() {
dynamicLanguage.updateServiceLocale(this);
foregroundService();
}
private static void startTimeoutIfAppropriate(@NonNull Context context) {
boolean appVisible = AppForegroundObserver.isForegrounded();
boolean secretSet = KeyCachingService.masterSecret != null;
@@ -5,7 +5,7 @@ import android.app.Service;
import android.content.Context;
import android.content.res.Configuration;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore;
import org.thoughtcrime.securesms.util.dynamiclanguage.LanguageString;
import java.util.Locale;
@@ -46,7 +46,7 @@ public class DynamicLanguage {
}
private static Locale getSelectedLocale(Context context) {
Locale locale = LanguageString.parseLocale(SignalStore.settings().getLanguage());
Locale locale = LanguageString.parseLocale(PlainTextKeyValueStore.getLanguage());
if (locale == null) {
return Locale.getDefault();
} else {
@@ -1,7 +1,7 @@
package org.thoughtcrime.securesms.util
import androidx.core.os.LocaleListCompat
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore
import org.thoughtcrime.securesms.util.dynamiclanguage.LanguageString
import java.util.Locale
@@ -17,7 +17,7 @@ object LocaleUtil {
*/
fun getLocaleDefaults(): List<Locale> {
val locales: MutableList<Locale> = mutableListOf()
val signalLocale: Locale? = LanguageString.parseLocale(SignalStore.settings.language)
val signalLocale: Locale? = LanguageString.parseLocale(PlainTextKeyValueStore.language)
val localeList: LocaleListCompat = LocaleListCompat.getDefault()
if (signalLocale != null) {
@@ -21,7 +21,6 @@ import org.greenrobot.eventbus.EventBus;
import org.signal.core.util.PendingIntentFlags;
import org.signal.core.util.logging.Log;
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.backup.proto.SharedPreference;
import org.thoughtcrime.securesms.backup.v2.BackupRepository;
@@ -52,7 +51,6 @@ public class TextSecurePreferences {
public static final String LANGUAGE_PREF = "pref_language";
public static final String ENABLE_MANUAL_MMS_PREF = "pref_enable_manual_mms";
private static final String LAST_VERSION_CODE_PREF = "last_version_code";
public static final String RINGTONE_PREF = "pref_key_ringtone";
public static final String VIBRATE_PREF = "pref_key_vibrate";
private static final String NOTIFICATION_PREF = "pref_key_enable_notifications";
@@ -94,11 +92,6 @@ public class TextSecurePreferences {
public static final String UNAUTHORIZED_RECEIVED = "pref_unauthorized_received";
private static final String SUCCESSFUL_DIRECTORY_PREF = "pref_successful_directory";
private static final String DATABASE_ENCRYPTED_SECRET = "pref_database_encrypted_secret";
private static final String DATABASE_UNENCRYPTED_SECRET = "pref_database_unencrypted_secret";
private static final String ATTACHMENT_ENCRYPTED_SECRET = "pref_attachment_encrypted_secret";
private static final String ATTACHMENT_UNENCRYPTED_SECRET = "pref_attachment_unencrypted_secret";
public static final String CALL_NOTIFICATIONS_PREF = "pref_call_notifications";
public static final String CALL_RINGTONE_PREF = "pref_call_ringtone";
public static final String CALL_VIBRATE_PREF = "pref_call_vibrate";
@@ -147,8 +140,6 @@ public class TextSecurePreferences {
private static final String JOB_MANAGER_VERSION = "pref_job_manager_version";
private static final String APP_MIGRATION_VERSION = "pref_app_migration_version";
private static final String FIRST_INSTALL_VERSION = "pref_first_install_version";
private static final String HAS_SEEN_SWIPE_TO_REPLY = "pref_has_seen_swipe_to_reply";
@@ -336,38 +327,6 @@ public class TextSecurePreferences {
return getLongPreference(context, BACKUP_TIME, -1);
}
public static void setAttachmentEncryptedSecret(@NonNull Context context, @NonNull String secret) {
setStringPreference(context, ATTACHMENT_ENCRYPTED_SECRET, secret);
}
public static void setAttachmentUnencryptedSecret(@NonNull Context context, @Nullable String secret) {
setStringPreference(context, ATTACHMENT_UNENCRYPTED_SECRET, secret);
}
public static @Nullable String getAttachmentEncryptedSecret(@NonNull Context context) {
return getStringPreference(context, ATTACHMENT_ENCRYPTED_SECRET, null);
}
public static @Nullable String getAttachmentUnencryptedSecret(@NonNull Context context) {
return getStringPreference(context, ATTACHMENT_UNENCRYPTED_SECRET, null);
}
public static void setDatabaseEncryptedSecret(@NonNull Context context, @NonNull String secret) {
setStringPreference(context, DATABASE_ENCRYPTED_SECRET, secret);
}
public static void setDatabaseUnencryptedSecret(@NonNull Context context, @Nullable String secret) {
setStringPreference(context, DATABASE_UNENCRYPTED_SECRET, secret);
}
public static @Nullable String getDatabaseUnencryptedSecret(@NonNull Context context) {
return getStringPreference(context, DATABASE_UNENCRYPTED_SECRET, null);
}
public static @Nullable String getDatabaseEncryptedSecret(@NonNull Context context) {
return getStringPreference(context, DATABASE_ENCRYPTED_SECRET, null);
}
public static void setHasSuccessfullyRetrievedDirectory(Context context, boolean value) {
setBooleanPreference(context, SUCCESSFUL_DIRECTORY_PREF, value);
}
@@ -549,16 +508,6 @@ public class TextSecurePreferences {
return getBooleanPreference(context, ENABLE_MANUAL_MMS_PREF, false);
}
public static int getLastVersionCode(Context context) {
return getIntegerPreference(context, LAST_VERSION_CODE_PREF, BuildConfig.VERSION_CODE);
}
public static void setLastVersionCode(Context context, int versionCode) {
if (!setIntegerPrefrenceBlocking(context, LAST_VERSION_CODE_PREF, versionCode)) {
throw new AssertionError("couldn't write version code to sharedpreferences");
}
}
/**
* @deprecated Use {@link SettingsValues#getTheme()} via {@link org.thoughtcrime.securesms.keyvalue.SignalStore} instead.
*/
@@ -567,22 +516,6 @@ public class TextSecurePreferences {
return getStringPreference(context, THEME_PREF, DynamicTheme.systemThemeAvailable() ? "system" : "light");
}
/**
* @deprecated Use {@link SettingsValues#getLanguage()} via {@link org.thoughtcrime.securesms.keyvalue.SignalStore} instead.
*/
@Deprecated
public static String getLanguage(Context context) {
return getStringPreference(context, LANGUAGE_PREF, "zz");
}
/**
* @deprecated Use {@link SettingsValues#setLanguage(String)} via {@link org.thoughtcrime.securesms.keyvalue.SignalStore} instead.
*/
@Deprecated
public static void setLanguage(Context context, String language) {
getSharedPreferences(context).edit().putString(LANGUAGE_PREF, language).commit();
}
@Deprecated
public static boolean isSmsDeliveryReportsEnabled(Context context) {
return getBooleanPreference(context, SMS_DELIVERY_REPORT_PREF, false);
@@ -786,14 +719,6 @@ public class TextSecurePreferences {
return getIntegerPreference(contex, JOB_MANAGER_VERSION, 1);
}
public static void setAppMigrationVersion(Context context, int version) {
setIntegerPrefrence(context, APP_MIGRATION_VERSION, version);
}
public static int getAppMigrationVersion(Context context) {
return getIntegerPreference(context, APP_MIGRATION_VERSION, 1);
}
public static void setFirstInstallVersion(Context context, int version) {
setIntegerPrefrence(context, FIRST_INSTALL_VERSION, version);
}
@@ -842,10 +767,6 @@ public class TextSecurePreferences {
getSharedPreferences(context).edit().putInt(key, value).apply();
}
private static boolean setIntegerPrefrenceBlocking(Context context, String key, int value) {
return getSharedPreferences(context).edit().putInt(key, value).commit();
}
public static long getLongPreference(Context context, String key, long defaultValue) {
return getSharedPreferences(context).getLong(key, defaultValue);
}
@@ -8,6 +8,7 @@ import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob
import org.thoughtcrime.securesms.jobs.RemoteConfigRefreshJob
import org.thoughtcrime.securesms.jobs.RetrieveRemoteAnnouncementsJob
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore
import org.thoughtcrime.securesms.keyvalue.SignalStore
import java.time.Duration
@@ -15,14 +16,14 @@ object VersionTracker {
private val TAG = Log.tag(VersionTracker::class.java)
@JvmStatic
fun getLastSeenVersion(context: Context): Int {
return TextSecurePreferences.getLastVersionCode(context)
fun getLastSeenVersion(): Int {
return PlainTextKeyValueStore.lastVersionCode
}
@JvmStatic
fun updateLastSeenVersion(context: Context) {
fun updateLastSeenVersion() {
val currentVersionCode = BuildConfig.VERSION_CODE
val lastVersionCode = TextSecurePreferences.getLastVersionCode(context)
val lastVersionCode = PlainTextKeyValueStore.lastVersionCode
if (currentVersionCode != lastVersionCode) {
Log.i(TAG, "Upgraded from $lastVersionCode to $currentVersionCode. Clearing client deprecation.", true)
@@ -34,7 +35,7 @@ object VersionTracker {
LocalMetrics.getInstance().clear()
}
TextSecurePreferences.setLastVersionCode(context, currentVersionCode)
PlainTextKeyValueStore.lastVersionCode = currentVersionCode
}
@JvmStatic
@@ -7,7 +7,7 @@ import android.os.Build;
import androidx.annotation.NonNull;
import androidx.core.os.LocaleListCompat;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.keyvalue.PlainTextKeyValueStore;
import java.util.Locale;
@@ -19,27 +19,27 @@ public final class DynamicLanguageContextWrapper {
private static LocaleListCompat systemLocaleList = LocaleListCompat.getEmptyLocaleList();
public static void prepareOverrideConfiguration(@NonNull Context context, @NonNull Configuration base) {
public static void prepareOverrideConfiguration(@NonNull Configuration base) {
if (Build.VERSION.SDK_INT >= 24) {
systemLocaleList = LocaleListCompat.wrap(base.getLocales());
} else {
systemLocaleList = LocaleListCompat.create(base.locale);
}
Locale newLocale = getUsersSelectedLocale(context);
Locale newLocale = getUsersSelectedLocale();
Locale.setDefault(newLocale);
base.setLocale(newLocale);
}
@SuppressWarnings("deprecated")
public static @NonNull Locale getUsersSelectedLocale(@NonNull Context context) {
String language = TextSecurePreferences.getLanguage(context);
public static @NonNull Locale getUsersSelectedLocale() {
String language = PlainTextKeyValueStore.getLanguage();
return LocaleParser.findBestMatchingLocaleForLanguage(language, systemLocaleList);
}
public static void updateContext(@NonNull Context base) {
Configuration config = base.getResources().getConfiguration();
prepareOverrideConfiguration(base, config);
prepareOverrideConfiguration(config);
}
}