Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.core.content.edit
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.bitwarden.data.datasource.disk.BaseDiskSource
import com.bitwarden.data.datasource.disk.model.FlightRecorderDataSet
import com.bitwarden.data.datasource.disk.FlightRecorderDiskSource
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
import com.x8bit.bitwarden.data.platform.manager.model.AppResumeScreenData
import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType
Expand Down Expand Up @@ -47,7 +47,6 @@ private const val CREATE_ACTION_COUNT = "createActionCount"
private const val SHOULD_SHOW_ADD_LOGIN_COACH_MARK = "shouldShowAddLoginCoachMark"
private const val SHOULD_SHOW_GENERATOR_COACH_MARK = "shouldShowGeneratorCoachMark"
private const val RESUME_SCREEN = "resumeScreen"
private const val FLIGHT_RECORDER_KEY = "flightRecorderData"
private const val IS_DYNAMIC_COLORS_ENABLED = "isDynamicColorsEnabled"
private const val BROWSER_AUTOFILL_DIALOG_RESHOW_TIME = "browserAutofillDialogReshowTime"

Expand All @@ -58,8 +57,10 @@ private const val BROWSER_AUTOFILL_DIALOG_RESHOW_TIME = "browserAutofillDialogRe
class SettingsDiskSourceImpl(
private val sharedPreferences: SharedPreferences,
private val json: Json,
flightRecorderDiskSource: FlightRecorderDiskSource,
) : BaseDiskSource(sharedPreferences = sharedPreferences),
SettingsDiskSource {
SettingsDiskSource,
FlightRecorderDiskSource by flightRecorderDiskSource {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a little torn with this.

On one hand, this centralizes a decent bit of logic but it is a nit cumbersome in the these places.

private val mutableAppLanguageFlow = bufferedMutableSharedFlow<AppLanguage?>(replay = 1)
private val mutableAppThemeFlow = bufferedMutableSharedFlow<AppTheme>(replay = 1)

Expand Down Expand Up @@ -92,8 +93,6 @@ class SettingsDiskSourceImpl(

private val mutableHasUserLoggedInOrCreatedAccountFlow = bufferedMutableSharedFlow<Boolean?>()

private val mutableFlightRecorderDataFlow = bufferedMutableSharedFlow<FlightRecorderDataSet?>()

private val mutableHasSeenAddLoginCoachMarkFlow = bufferedMutableSharedFlow<Boolean?>()

private val mutableHasSeenGeneratorCoachMarkFlow = bufferedMutableSharedFlow<Boolean?>()
Expand Down Expand Up @@ -214,20 +213,6 @@ class SettingsDiskSourceImpl(
get() = mutableHasUserLoggedInOrCreatedAccountFlow
.onSubscription { emit(getBoolean(HAS_USER_LOGGED_IN_OR_CREATED_AN_ACCOUNT_KEY)) }

override var flightRecorderData: FlightRecorderDataSet?
get() = getString(key = FLIGHT_RECORDER_KEY)
?.let { json.decodeFromStringOrNull<FlightRecorderDataSet>(it) }
set(value) {
putString(
key = FLIGHT_RECORDER_KEY,
value = value?.let { json.encodeToString(it) },
)
mutableFlightRecorderDataFlow.tryEmit(value)
}

override val flightRecorderDataFlow: Flow<FlightRecorderDataSet?>
get() = mutableFlightRecorderDataFlow.onSubscription { emit(flightRecorderData) }

override var browserAutofillDialogReshowTime: Instant?
get() = getLong(key = BROWSER_AUTOFILL_DIALOG_RESHOW_TIME)?.let { Instant.ofEpochMilli(it) }
set(value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.Context
import android.content.SharedPreferences
import androidx.room.Room
import com.bitwarden.core.data.manager.dispatcher.DispatcherManager
import com.bitwarden.data.datasource.disk.FlightRecorderDiskSource
import com.bitwarden.data.datasource.disk.di.EncryptedPreferences
import com.bitwarden.data.datasource.disk.di.UnencryptedPreferences
import com.x8bit.bitwarden.data.platform.datasource.disk.EnvironmentDiskSource
Expand Down Expand Up @@ -139,10 +140,12 @@ object PlatformDiskModule {
fun provideSettingsDiskSource(
@UnencryptedPreferences sharedPreferences: SharedPreferences,
json: Json,
flightRecorderDiskSource: FlightRecorderDiskSource,
): SettingsDiskSource =
SettingsDiskSourceImpl(
sharedPreferences = sharedPreferences,
json = json,
flightRecorderDiskSource = flightRecorderDiskSource,
)

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import com.bitwarden.core.data.manager.toast.ToastManagerImpl
import com.bitwarden.cxf.registry.CredentialExchangeRegistry
import com.bitwarden.cxf.registry.dsl.credentialExchangeRegistry
import com.bitwarden.data.manager.NativeLibraryManager
import com.bitwarden.data.manager.flightrecorder.FlightRecorderManager
import com.bitwarden.data.manager.flightrecorder.FlightRecorderWriter
import com.bitwarden.data.repository.ServerConfigRepository
import com.bitwarden.network.BitwardenServiceClient
import com.bitwarden.network.service.EventService
Expand Down Expand Up @@ -106,22 +104,6 @@ object PlatformManagerModule {
application: Application,
): AppStateManager = AppStateManagerImpl(application = application)

@Provides
@Singleton
fun provideFlightRecorderManager(
@ApplicationContext context: Context,
clock: Clock,
dispatcherManager: DispatcherManager,
settingsDiskSource: SettingsDiskSource,
flightRecorderWriter: FlightRecorderWriter,
): FlightRecorderManager = FlightRecorderManager.create(
context = context,
clock = clock,
dispatcherManager = dispatcherManager,
flightRecorderDiskSource = settingsDiskSource,
flightRecorderWriter = flightRecorderWriter,
)

@Provides
@Singleton
fun provideAuthenticatorBridgeProcessor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import com.bitwarden.network.model.OrganizationType
import com.bitwarden.network.model.PolicyTypeJson
import com.bitwarden.network.model.SyncResponseJson
import com.bitwarden.network.model.TrustedDeviceUserDecryptionOptionsJson
import com.bitwarden.network.model.createMockPolicy
import com.bitwarden.network.model.UserDecryptionJson
import com.bitwarden.network.model.UserDecryptionOptionsJson
import com.bitwarden.network.model.createMockPolicy
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountJson
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
import com.x8bit.bitwarden.data.auth.datasource.disk.model.ForcePasswordResetReason
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.service.autofill.FillResponse
import android.service.autofill.SaveInfo
import android.view.View
import android.view.autofill.AutofillId
import com.bitwarden.core.data.util.mockBuilder
import com.x8bit.bitwarden.data.autofill.model.AutofillAppInfo
import com.x8bit.bitwarden.data.autofill.model.AutofillCipher
import com.x8bit.bitwarden.data.autofill.model.AutofillPartition
Expand All @@ -16,7 +17,6 @@ import com.x8bit.bitwarden.data.autofill.model.FilledPartition
import com.x8bit.bitwarden.data.autofill.util.buildDataset
import com.x8bit.bitwarden.data.autofill.util.buildVaultItemDataset
import com.x8bit.bitwarden.data.autofill.util.createAutofillCallbackIntentSender
import com.x8bit.bitwarden.data.util.mockBuilder
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import android.service.autofill.FillRequest
import android.service.autofill.SaveInfo
import android.view.View
import android.view.autofill.AutofillId
import com.bitwarden.core.data.util.mockBuilder
import com.x8bit.bitwarden.data.autofill.model.AutofillPartition
import com.x8bit.bitwarden.data.autofill.model.AutofillView
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.data.util.mockBuilder
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import android.view.autofill.AutofillId
import android.view.autofill.AutofillValue
import android.widget.RemoteViews
import android.widget.inline.InlinePresentationSpec
import com.bitwarden.core.data.util.mockBuilder
import com.x8bit.bitwarden.data.autofill.model.AutofillAppInfo
import com.x8bit.bitwarden.data.autofill.model.AutofillCipher
import com.x8bit.bitwarden.data.autofill.model.AutofillPartition
import com.x8bit.bitwarden.data.autofill.model.AutofillView
import com.x8bit.bitwarden.data.autofill.model.FilledData
import com.x8bit.bitwarden.data.autofill.model.FilledItem
import com.x8bit.bitwarden.data.autofill.model.FilledPartition
import com.x8bit.bitwarden.data.util.mockBuilder
import com.x8bit.bitwarden.ui.autofill.buildVaultItemAutofillRemoteViews
import com.x8bit.bitwarden.ui.autofill.util.createVaultItemInlinePresentationOrNull
import io.mockk.every
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import android.service.autofill.Presentations
import android.view.autofill.AutofillId
import android.view.autofill.AutofillValue
import android.widget.RemoteViews
import com.bitwarden.core.data.util.mockBuilder
import com.x8bit.bitwarden.data.autofill.model.FilledItem
import com.x8bit.bitwarden.data.util.mockBuilder
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import android.service.autofill.InlinePresentation
import android.service.autofill.Presentations
import android.widget.RemoteViews
import android.widget.inline.InlinePresentationSpec
import com.bitwarden.core.data.util.mockBuilder
import com.x8bit.bitwarden.data.autofill.model.AutofillAppInfo
import com.x8bit.bitwarden.data.autofill.model.AutofillCipher
import com.x8bit.bitwarden.data.autofill.model.FilledItem
import com.x8bit.bitwarden.data.autofill.model.FilledPartition
import com.x8bit.bitwarden.data.util.mockBuilder
import com.x8bit.bitwarden.ui.autofill.buildAutofillRemoteViews
import com.x8bit.bitwarden.ui.autofill.util.createCipherInlinePresentationOrNull
import io.mockk.every
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import androidx.credentials.provider.BeginGetPasswordOption
import androidx.credentials.provider.BeginGetPublicKeyCredentialOption
import androidx.credentials.provider.PasswordCredentialEntry
import androidx.credentials.provider.PublicKeyCredentialEntry
import com.bitwarden.core.data.util.mockBuilder
import com.bitwarden.core.util.isBuildVersionAtLeast
import com.bitwarden.fido.Fido2CredentialAutofillView
import com.bitwarden.vault.CipherListView
import com.bitwarden.vault.CipherListViewType
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.credentials.manager.CredentialManagerPendingIntentManager
import com.x8bit.bitwarden.data.util.mockBuilder
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockCipherListView
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockFido2CredentialAutofillView
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.createMockLoginListView
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ import app.cash.turbine.test
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.bitwarden.core.di.CoreModule
import com.bitwarden.data.datasource.disk.base.FakeSharedPreferences
import com.bitwarden.data.datasource.disk.model.FlightRecorderDataSet
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
import com.x8bit.bitwarden.data.platform.manager.model.AppResumeScreenData
import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency
import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType
import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction
import com.x8bit.bitwarden.data.util.assertJsonEquals
import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.Json
import org.junit.jupiter.api.Assertions.assertEquals
Expand All @@ -27,9 +26,10 @@ class SettingsDiskSourceTest {
private val fakeSharedPreferences = FakeSharedPreferences()
private val json = CoreModule.providesJson()

private val settingsDiskSource = SettingsDiskSourceImpl(
private val settingsDiskSource: SettingsDiskSource = SettingsDiskSourceImpl(
sharedPreferences = fakeSharedPreferences,
json = json,
flightRecorderDiskSource = mockk(),
)

@Test
Expand Down Expand Up @@ -85,104 +85,6 @@ class SettingsDiskSourceTest {
)
}

@Test
fun `flightRecorderData should pull from SharedPreferences`() {
val flightRecorderKey = "bwPreferencesStorage:flightRecorderData"
val encodedData = """
{
"data": [
{
"id": "51"
"fileName": "flight_recorder_2025-04-03_14-22-40",
"startTime": 1744059882,
"duration": 3600,
"isActive": false
}
]
}
"""
.trimIndent()
val expected = FlightRecorderDataSet(
data = setOf(
FlightRecorderDataSet.FlightRecorderData(
id = "51",
fileName = "flight_recorder_2025-04-03_14-22-40",
startTimeMs = 1_744_059_882L,
durationMs = 3_600L,
isActive = false,
),
),
)

// Verify initial value is null and disk source matches shared preferences.
assertNull(fakeSharedPreferences.getString(flightRecorderKey, null))
assertNull(settingsDiskSource.flightRecorderData)

// Updating the shared preferences should update disk source.
fakeSharedPreferences.edit { putString(flightRecorderKey, encodedData) }
val actual = settingsDiskSource.flightRecorderData
assertEquals(expected, actual)
}

@Test
fun `flightRecorderDataFlow should react to changes in isFLightRecorderEnabled`() = runTest {
val expected = FlightRecorderDataSet(
data = setOf(
FlightRecorderDataSet.FlightRecorderData(
id = "52",
fileName = "flight_recorder_2025-04-03_14-22-40",
startTimeMs = 1_744_059_882L,
durationMs = 3_600L,
isActive = true,
),
),
)
settingsDiskSource.flightRecorderDataFlow.test {
// The initial values of the Flow and the property are in sync
assertNull(settingsDiskSource.flightRecorderData)
assertNull(awaitItem())

settingsDiskSource.flightRecorderData = expected
assertEquals(expected, awaitItem())

settingsDiskSource.flightRecorderData = null
assertNull(awaitItem())
}
}

@Test
fun `setting flightRecorderData should update SharedPreferences`() {
val flightRecorderKey = "bwPreferencesStorage:flightRecorderData"
val data = FlightRecorderDataSet(
data = setOf(
FlightRecorderDataSet.FlightRecorderData(
id = "53",
fileName = "flight_recorder_2025-04-03_14-22-40",
startTimeMs = 1_744_059_882L,
durationMs = 3_600L,
isActive = true,
),
),
)
val expected = """
{
"data": [
{
"id": "53",
"fileName": "flight_recorder_2025-04-03_14-22-40",
"startTime": 1744059882,
"duration": 3600,
"isActive": true
}
]
}
"""
.trimIndent()
settingsDiskSource.flightRecorderData = data
val actual = fakeSharedPreferences.getString(flightRecorderKey, null)
assertJsonEquals(expected, actual!!)
}

@Test
fun `systemBiometricIntegritySource should pull from SharedPreferences`() {
val biometricIntegritySource = "bwPreferencesStorage:biometricIntegritySource"
Expand Down
Loading
Loading