mirror of
https://github.com/bitwarden/android.git
synced 2025-03-15 10:48:47 +03:00
BIT-1092: Store and expose value for disabling autofill save prompt (#763)
This commit is contained in:
parent
d8ceedd90b
commit
7a416de9c9
9 changed files with 134 additions and 8 deletions
|
@ -106,6 +106,20 @@ interface SettingsDiskSource {
|
|||
*/
|
||||
fun storeDefaultUriMatchType(userId: String, uriMatchType: UriMatchType?)
|
||||
|
||||
/**
|
||||
* Gets the value for whether or not the autofill save prompt should be disabled for the
|
||||
* given [userId].
|
||||
*/
|
||||
fun getAutofillSavePromptDisabled(userId: String): Boolean?
|
||||
|
||||
/**
|
||||
* Stores the given [isAutofillSavePromptDisabled] for the given [userId].
|
||||
*/
|
||||
fun storeAutofillSavePromptDisabled(
|
||||
userId: String,
|
||||
isAutofillSavePromptDisabled: Boolean?,
|
||||
)
|
||||
|
||||
/**
|
||||
* Gets the current state of the pull to refresh feature for the given [userId].
|
||||
*/
|
||||
|
|
|
@ -23,6 +23,7 @@ private const val VAULT_LAST_SYNC_TIME = "$BASE_KEY:vaultLastSyncTime"
|
|||
private const val VAULT_TIMEOUT_ACTION_KEY = "$BASE_KEY:vaultTimeoutAction"
|
||||
private const val VAULT_TIME_IN_MINUTES_KEY = "$BASE_KEY:vaultTimeout"
|
||||
private const val DEFAULT_URI_MATCH_TYPE_KEY = "$BASE_KEY:defaultUriMatch"
|
||||
private const val DISABLE_AUTOFILL_SAVE_PROMPT_KEY = "$BASE_KEY:autofillDisableSavePrompt"
|
||||
private const val DISABLE_ICON_LOADING_KEY = "$BASE_KEY:disableFavicon"
|
||||
private const val APPROVE_PASSWORDLESS_LOGINS_KEY = "$BASE_KEY:approvePasswordlessLogins"
|
||||
|
||||
|
@ -97,6 +98,7 @@ class SettingsDiskSourceImpl(
|
|||
storeVaultTimeoutInMinutes(userId = userId, vaultTimeoutInMinutes = null)
|
||||
storeVaultTimeoutAction(userId = userId, vaultTimeoutAction = null)
|
||||
storeDefaultUriMatchType(userId = userId, uriMatchType = null)
|
||||
storeAutofillSavePromptDisabled(userId = userId, isAutofillSavePromptDisabled = null)
|
||||
storePullToRefreshEnabled(userId = userId, isPullToRefreshEnabled = null)
|
||||
storeInlineAutofillEnabled(userId = userId, isInlineAutofillEnabled = null)
|
||||
storeBlockedAutofillUris(userId = userId, blockedAutofillUris = null)
|
||||
|
@ -175,6 +177,19 @@ class SettingsDiskSourceImpl(
|
|||
)
|
||||
}
|
||||
|
||||
override fun getAutofillSavePromptDisabled(userId: String): Boolean? =
|
||||
getBoolean(key = "${DISABLE_AUTOFILL_SAVE_PROMPT_KEY}_$userId")
|
||||
|
||||
override fun storeAutofillSavePromptDisabled(
|
||||
userId: String,
|
||||
isAutofillSavePromptDisabled: Boolean?,
|
||||
) {
|
||||
putBoolean(
|
||||
key = "${DISABLE_AUTOFILL_SAVE_PROMPT_KEY}_$userId",
|
||||
value = isAutofillSavePromptDisabled,
|
||||
)
|
||||
}
|
||||
|
||||
override fun getPullToRefreshEnabled(userId: String): Boolean? =
|
||||
getBoolean(key = "${PULL_TO_REFRESH_KEY}_$userId")
|
||||
|
||||
|
|
|
@ -75,6 +75,11 @@ interface SettingsRepository {
|
|||
*/
|
||||
var isInlineAutofillEnabled: Boolean
|
||||
|
||||
/**
|
||||
* Whether or not the autofill save prompt is disabled for the current user.
|
||||
*/
|
||||
var isAutofillSavePromptDisabled: Boolean
|
||||
|
||||
/**
|
||||
* A list of blocked autofill URI's for the current user.
|
||||
*/
|
||||
|
|
|
@ -163,6 +163,18 @@ class SettingsRepositoryImpl(
|
|||
)
|
||||
}
|
||||
|
||||
override var isAutofillSavePromptDisabled: Boolean
|
||||
get() = activeUserId
|
||||
?.let { settingsDiskSource.getAutofillSavePromptDisabled(userId = it) }
|
||||
?: false
|
||||
set(value) {
|
||||
val userId = activeUserId ?: return
|
||||
settingsDiskSource.storeAutofillSavePromptDisabled(
|
||||
userId = userId,
|
||||
isAutofillSavePromptDisabled = value,
|
||||
)
|
||||
}
|
||||
|
||||
override var blockedAutofillUris: List<String>
|
||||
get() = activeUserId
|
||||
?.let { settingsDiskSource.getBlockedAutofillUris(userId = it) }
|
||||
|
|
|
@ -29,7 +29,7 @@ class AutoFillViewModel @Inject constructor(
|
|||
) : BaseViewModel<AutoFillState, AutoFillEvent, AutoFillAction>(
|
||||
initialState = savedStateHandle[KEY_STATE]
|
||||
?: AutoFillState(
|
||||
isAskToAddLoginEnabled = false,
|
||||
isAskToAddLoginEnabled = !settingsRepository.isAutofillSavePromptDisabled,
|
||||
isAutoFillServicesEnabled = settingsRepository.isAutofillEnabledStateFlow.value,
|
||||
isCopyTotpAutomaticallyEnabled = false,
|
||||
isUseInlineAutoFillEnabled = settingsRepository.isInlineAutofillEnabled,
|
||||
|
@ -65,8 +65,7 @@ class AutoFillViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun handleAskToAddLoginClick(action: AutoFillAction.AskToAddLoginClick) {
|
||||
// TODO BIT-1092: Persist selection
|
||||
sendEvent(AutoFillEvent.ShowToast("Not yet implemented.".asText()))
|
||||
settingsRepository.isAutofillSavePromptDisabled = !action.isEnabled
|
||||
mutableStateFlow.update { it.copy(isAskToAddLoginEnabled = action.isEnabled) }
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.junit.jupiter.api.Assertions.assertTrue
|
|||
import org.junit.jupiter.api.Test
|
||||
import java.time.Instant
|
||||
|
||||
@Suppress("LargeClass")
|
||||
class SettingsDiskSourceTest {
|
||||
private val fakeSharedPreferences = FakeSharedPreferences()
|
||||
private val json = PlatformNetworkModule.providesJson()
|
||||
|
@ -79,6 +80,10 @@ class SettingsDiskSourceTest {
|
|||
userId = userId,
|
||||
uriMatchType = UriMatchType.REGULAR_EXPRESSION,
|
||||
)
|
||||
settingsDiskSource.storeAutofillSavePromptDisabled(
|
||||
userId = userId,
|
||||
isAutofillSavePromptDisabled = true,
|
||||
)
|
||||
settingsDiskSource.storePullToRefreshEnabled(
|
||||
userId = userId,
|
||||
isPullToRefreshEnabled = true,
|
||||
|
@ -105,6 +110,7 @@ class SettingsDiskSourceTest {
|
|||
assertNull(settingsDiskSource.getVaultTimeoutInMinutes(userId = userId))
|
||||
assertNull(settingsDiskSource.getVaultTimeoutAction(userId = userId))
|
||||
assertNull(settingsDiskSource.getDefaultUriMatchType(userId = userId))
|
||||
assertNull(settingsDiskSource.getAutofillSavePromptDisabled(userId = userId))
|
||||
assertNull(settingsDiskSource.getPullToRefreshEnabled(userId = userId))
|
||||
assertNull(settingsDiskSource.getInlineAutofillEnabled(userId = userId))
|
||||
assertNull(settingsDiskSource.getBlockedAutofillUris(userId = userId))
|
||||
|
@ -445,6 +451,50 @@ class SettingsDiskSourceTest {
|
|||
assertFalse(fakeSharedPreferences.contains(defaultUriMatchTypeKey))
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `getAutofillSavePromptDisabled when values are present should pull from SharedPreferences`() {
|
||||
val disableAutofillSavePromptBaseKey = "bwPreferencesStorage:autofillDisableSavePrompt"
|
||||
val mockUserId = "mockUserId"
|
||||
val disableAutofillSavePromptKey = "${disableAutofillSavePromptBaseKey}_$mockUserId"
|
||||
fakeSharedPreferences
|
||||
.edit {
|
||||
putBoolean(disableAutofillSavePromptKey, true)
|
||||
}
|
||||
assertEquals(true, settingsDiskSource.getAutofillSavePromptDisabled(userId = mockUserId))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getAutofillSavePromptDisabled when values are absent should return null`() {
|
||||
val mockUserId = "mockUserId"
|
||||
assertNull(settingsDiskSource.getAutofillSavePromptDisabled(userId = mockUserId))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `storeAutofillSavePromptDisabled for non-null values should update SharedPreferences`() {
|
||||
val disableAutofillSavePromptBaseKey = "bwPreferencesStorage:autofillDisableSavePrompt"
|
||||
val mockUserId = "mockUserId"
|
||||
val disableAutofillSavePromptKey = "${disableAutofillSavePromptBaseKey}_$mockUserId"
|
||||
settingsDiskSource.storeAutofillSavePromptDisabled(
|
||||
userId = mockUserId,
|
||||
isAutofillSavePromptDisabled = true,
|
||||
)
|
||||
assertTrue(fakeSharedPreferences.getBoolean(disableAutofillSavePromptKey, false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `storeAutofillSavePromptDisabled for null values should clear SharedPreferences`() {
|
||||
val disableAutofillSavePromptBaseKey = "bwPreferencesStorage:autofillDisableSavePrompt"
|
||||
val mockUserId = "mockUserId"
|
||||
val disableAutofillSavePromptKey = "${disableAutofillSavePromptBaseKey}_$mockUserId"
|
||||
fakeSharedPreferences.edit { putBoolean(disableAutofillSavePromptKey, false) }
|
||||
settingsDiskSource.storeAutofillSavePromptDisabled(
|
||||
userId = mockUserId,
|
||||
isAutofillSavePromptDisabled = null,
|
||||
)
|
||||
assertFalse(fakeSharedPreferences.contains(disableAutofillSavePromptKey))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPullToRefreshEnabled when values are present should pull from SharedPreferences`() {
|
||||
val pullToRefreshBaseKey = "bwPreferencesStorage:syncOnRefresh"
|
||||
|
|
|
@ -38,6 +38,7 @@ class FakeSettingsDiskSource : SettingsDiskSource {
|
|||
private val storedVaultTimeoutActions = mutableMapOf<String, VaultTimeoutAction?>()
|
||||
private val storedVaultTimeoutInMinutes = mutableMapOf<String, Int?>()
|
||||
private val storedUriMatchTypes = mutableMapOf<String, UriMatchType?>()
|
||||
private val storedDisableAutofillSavePrompt = mutableMapOf<String, Boolean?>()
|
||||
private val storedPullToRefreshEnabled = mutableMapOf<String, Boolean?>()
|
||||
private val storedInlineAutofillEnabled = mutableMapOf<String, Boolean?>()
|
||||
private val storedBlockedAutofillUris = mutableMapOf<String, List<String>?>()
|
||||
|
@ -76,6 +77,7 @@ class FakeSettingsDiskSource : SettingsDiskSource {
|
|||
storedVaultTimeoutActions.remove(userId)
|
||||
storedVaultTimeoutInMinutes.remove(userId)
|
||||
storedUriMatchTypes.remove(userId)
|
||||
storedDisableAutofillSavePrompt.remove(userId)
|
||||
storedPullToRefreshEnabled.remove(userId)
|
||||
storedInlineAutofillEnabled.remove(userId)
|
||||
storedBlockedAutofillUris.remove(userId)
|
||||
|
@ -136,6 +138,16 @@ class FakeSettingsDiskSource : SettingsDiskSource {
|
|||
storedUriMatchTypes[userId] = uriMatchType
|
||||
}
|
||||
|
||||
override fun getAutofillSavePromptDisabled(userId: String): Boolean? =
|
||||
storedDisableAutofillSavePrompt[userId]
|
||||
|
||||
override fun storeAutofillSavePromptDisabled(
|
||||
userId: String,
|
||||
isAutofillSavePromptDisabled: Boolean?,
|
||||
) {
|
||||
storedDisableAutofillSavePrompt[userId] = isAutofillSavePromptDisabled
|
||||
}
|
||||
|
||||
override fun getPullToRefreshEnabled(userId: String): Boolean? =
|
||||
storedPullToRefreshEnabled[userId]
|
||||
|
||||
|
|
|
@ -443,6 +443,24 @@ class SettingsRepositoryTest {
|
|||
assertTrue(fakeSettingsDiskSource.getInlineAutofillEnabled(userId = userId)!!)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `isAutofillSavePromptDisabled should pull from and update SettingsDiskSource`() {
|
||||
val userId = "userId"
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
assertFalse(settingsRepository.isAutofillSavePromptDisabled)
|
||||
|
||||
// Updates to the disk source change the repository value.
|
||||
fakeSettingsDiskSource.storeAutofillSavePromptDisabled(
|
||||
userId = userId,
|
||||
isAutofillSavePromptDisabled = true,
|
||||
)
|
||||
assertTrue(settingsRepository.isAutofillSavePromptDisabled)
|
||||
|
||||
// Updates to the repository change the disk source value
|
||||
settingsRepository.isAutofillSavePromptDisabled = false
|
||||
assertFalse(fakeSettingsDiskSource.getAutofillSavePromptDisabled(userId = userId)!!)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `blockedAutofillUris should pull from and update SettingsDiskSource`() {
|
||||
val userId = "userId"
|
||||
|
|
|
@ -22,6 +22,8 @@ class AutoFillViewModelTest : BaseViewModelTest() {
|
|||
private val settingsRepository: SettingsRepository = mockk() {
|
||||
every { isInlineAutofillEnabled } returns true
|
||||
every { isInlineAutofillEnabled = any() } just runs
|
||||
every { isAutofillSavePromptDisabled } returns true
|
||||
every { isAutofillSavePromptDisabled = any() } just runs
|
||||
every { defaultUriMatchType } returns UriMatchType.DOMAIN
|
||||
every { defaultUriMatchType = any() } just runs
|
||||
every { isAutofillEnabledStateFlow } returns mutableIsAutofillEnabledStateFlow
|
||||
|
@ -66,16 +68,15 @@ class AutoFillViewModelTest : BaseViewModelTest() {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `on AskToAddLoginClick should emit ShowToast`() = runTest {
|
||||
fun `on AskToAddLoginClick should update the state and save the new value to settings`() {
|
||||
val viewModel = createViewModel()
|
||||
viewModel.eventFlow.test {
|
||||
viewModel.trySendAction(AutoFillAction.AskToAddLoginClick(true))
|
||||
assertEquals(AutoFillEvent.ShowToast("Not yet implemented.".asText()), awaitItem())
|
||||
}
|
||||
viewModel.trySendAction(AutoFillAction.AskToAddLoginClick(true))
|
||||
assertEquals(
|
||||
DEFAULT_STATE.copy(isAskToAddLoginEnabled = true),
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
// The UI enables the value, so the value gets flipped to save it as a "disabled" value.
|
||||
verify { settingsRepository.isAutofillSavePromptDisabled = false }
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Add table
Reference in a new issue