diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/di/PlatformDiskModule.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/di/PlatformDiskModule.kt index 0b42bf4aa..2eafefc93 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/di/PlatformDiskModule.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/di/PlatformDiskModule.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.platform.datasource.disk.di +import android.app.Application import android.content.Context import android.content.SharedPreferences import com.x8bit.bitwarden.data.platform.datasource.di.EncryptedPreferences @@ -10,10 +11,13 @@ import com.x8bit.bitwarden.data.platform.datasource.disk.PushDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.PushDiskSourceImpl import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSourceImpl +import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacyAppCenterMigrator +import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacyAppCenterMigratorImpl import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacySecureStorage import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacySecureStorageImpl import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacySecureStorageMigrator import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacySecureStorageMigratorImpl +import com.x8bit.bitwarden.data.platform.repository.SettingsRepository import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -60,6 +64,20 @@ object PlatformDiskModule { encryptedSharedPreferences = encryptedSharedPreferences, ) + @Provides + @Singleton + fun provideLegacyAppCenterMigrator( + application: Application, + settingsRepository: SettingsRepository, + ): LegacyAppCenterMigrator = + LegacyAppCenterMigratorImpl( + settingsRepository = settingsRepository, + appCenterPreferences = application.getSharedPreferences( + "AppCenter", + Context.MODE_PRIVATE, + ), + ) + @Provides @Singleton fun providePushDiskSource( diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/legacy/LegacyAppCenterMigrator.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/legacy/LegacyAppCenterMigrator.kt new file mode 100644 index 000000000..7a03cf51e --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/legacy/LegacyAppCenterMigrator.kt @@ -0,0 +1,12 @@ +package com.x8bit.bitwarden.data.platform.datasource.disk.legacy + +/** + * Provides the ability to migrate from a legacy AppCenter system to this app. + */ +interface LegacyAppCenterMigrator { + /** + * Migrates any data from the legacy AppCenter system to the new app. + * After migration, data will be removed from the legacy system. + */ + fun migrateIfNecessary() +} diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/legacy/LegacyAppCenterMigratorImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/legacy/LegacyAppCenterMigratorImpl.kt new file mode 100644 index 000000000..07cd393c3 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/legacy/LegacyAppCenterMigratorImpl.kt @@ -0,0 +1,25 @@ +package com.x8bit.bitwarden.data.platform.datasource.disk.legacy + +import android.content.SharedPreferences +import androidx.core.content.edit +import com.x8bit.bitwarden.data.platform.repository.SettingsRepository + +private const val LEGACY_ENABLED_CRASHES = "enabled_Crashes" + +/** + * Primary implementation of [LegacyAppCenterMigrator]. + */ +class LegacyAppCenterMigratorImpl( + private val settingsRepository: SettingsRepository, + private val appCenterPreferences: SharedPreferences, +) : LegacyAppCenterMigrator { + override fun migrateIfNecessary() { + // If the data is not present, then we return since there is nothing to migrate. + if (!appCenterPreferences.contains(LEGACY_ENABLED_CRASHES)) return + settingsRepository.isCrashLoggingEnabled = appCenterPreferences.getBoolean( + LEGACY_ENABLED_CRASHES, + true, + ) + appCenterPreferences.edit { clear() } + } +} diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt index c97284996..bc6e34d20 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt @@ -6,6 +6,7 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource import com.x8bit.bitwarden.data.auth.repository.AuthRepository import com.x8bit.bitwarden.data.platform.datasource.disk.PushDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource +import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacyAppCenterMigrator import com.x8bit.bitwarden.data.platform.datasource.network.authenticator.RefreshAuthenticator import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.AuthTokenInterceptor import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.BaseUrlInterceptors @@ -160,8 +161,10 @@ object PlatformManagerModule { @Provides @Singleton fun provideCrashLogsManager( + legacyAppCenterMigrator: LegacyAppCenterMigrator, settingsRepository: SettingsRepository, ): CrashLogsManager = CrashLogsManagerImpl( settingsRepository = settingsRepository, + legacyAppCenterMigrator = legacyAppCenterMigrator, ) } diff --git a/app/src/standard/java/com/x8bit/bitwarden/data/platform/manager/CrashLogsManagerImpl.kt b/app/src/standard/java/com/x8bit/bitwarden/data/platform/manager/CrashLogsManagerImpl.kt index 7659bd143..285905ae4 100644 --- a/app/src/standard/java/com/x8bit/bitwarden/data/platform/manager/CrashLogsManagerImpl.kt +++ b/app/src/standard/java/com/x8bit/bitwarden/data/platform/manager/CrashLogsManagerImpl.kt @@ -2,13 +2,17 @@ package com.x8bit.bitwarden.data.platform.manager import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.ktx.Firebase +import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage +import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacyAppCenterMigrator import com.x8bit.bitwarden.data.platform.repository.SettingsRepository /** * CrashLogsManager implementation for standard flavor builds. */ +@OmitFromCoverage class CrashLogsManagerImpl( private val settingsRepository: SettingsRepository, + legacyAppCenterMigrator: LegacyAppCenterMigrator, ) : CrashLogsManager { override var isEnabled: Boolean @@ -19,6 +23,7 @@ class CrashLogsManagerImpl( } init { + legacyAppCenterMigrator.migrateIfNecessary() isEnabled = settingsRepository.isCrashLoggingEnabled } } diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/disk/legacy/LegacyAppCenterMigratorTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/disk/legacy/LegacyAppCenterMigratorTest.kt new file mode 100644 index 000000000..5592cc66e --- /dev/null +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/disk/legacy/LegacyAppCenterMigratorTest.kt @@ -0,0 +1,59 @@ +package com.x8bit.bitwarden.data.platform.datasource.disk.legacy + +import androidx.core.content.edit +import com.x8bit.bitwarden.data.platform.base.FakeSharedPreferences +import com.x8bit.bitwarden.data.platform.repository.SettingsRepository +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.runs +import io.mockk.verify +import org.junit.jupiter.api.Assertions.assertFalse +import org.junit.jupiter.api.Test + +class LegacyAppCenterMigratorTest { + private val settingsRepository = mockk() + private val fakeSharedPreferences = FakeSharedPreferences() + + private val migrator = LegacyAppCenterMigratorImpl( + settingsRepository = settingsRepository, + appCenterPreferences = fakeSharedPreferences, + ) + + @Test + fun `migrateIfNecessary should do nothing when there is nothing to migrate`() { + migrator.migrateIfNecessary() + + verify(exactly = 0) { + settingsRepository.isCrashLoggingEnabled = any() + } + } + + @Test + fun `migrateIfNecessary should migrate the data when it is present and true`() { + val isEnabled = true + fakeSharedPreferences.edit { putBoolean("enabled_Crashes", isEnabled) } + every { settingsRepository.isCrashLoggingEnabled = isEnabled } just runs + + migrator.migrateIfNecessary() + + verify(exactly = 1) { + settingsRepository.isCrashLoggingEnabled = isEnabled + } + assertFalse(fakeSharedPreferences.contains("enabled_Crashes")) + } + + @Test + fun `migrateIfNecessary should migrate the data when it is present and false`() { + val isEnabled = false + fakeSharedPreferences.edit { putBoolean("enabled_Crashes", isEnabled) } + every { settingsRepository.isCrashLoggingEnabled = isEnabled } just runs + + migrator.migrateIfNecessary() + + verify(exactly = 1) { + settingsRepository.isCrashLoggingEnabled = isEnabled + } + assertFalse(fakeSharedPreferences.contains("enabled_Crashes")) + } +}