mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 15:15:34 +03:00
BIT-1642: Pre-populate the add item screen URI during autofill (#863)
This commit is contained in:
parent
84a983e755
commit
1e64c82e83
4 changed files with 136 additions and 7 deletions
|
@ -7,7 +7,10 @@ import com.bitwarden.core.CipherView
|
||||||
import com.x8bit.bitwarden.R
|
import com.x8bit.bitwarden.R
|
||||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||||
import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult
|
import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult
|
||||||
|
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
||||||
|
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||||
|
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
|
||||||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||||
import com.x8bit.bitwarden.data.platform.repository.util.takeUntilLoaded
|
import com.x8bit.bitwarden.data.platform.repository.util.takeUntilLoaded
|
||||||
import com.x8bit.bitwarden.data.tools.generator.repository.GeneratorRepository
|
import com.x8bit.bitwarden.data.tools.generator.repository.GeneratorRepository
|
||||||
|
@ -27,6 +30,7 @@ import com.x8bit.bitwarden.ui.vault.feature.addedit.model.CustomFieldAction
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.CustomFieldType
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.CustomFieldType
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.UriItem
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.UriItem
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.toCustomField
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.toCustomField
|
||||||
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toDefaultAddTypeContent
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toViewState
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toViewState
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toCipherView
|
import com.x8bit.bitwarden.ui.vault.feature.vault.util.toCipherView
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType
|
import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType
|
||||||
|
@ -59,27 +63,41 @@ private const val KEY_STATE = "state"
|
||||||
* @param savedStateHandle Handles the navigation arguments of this ViewModel.
|
* @param savedStateHandle Handles the navigation arguments of this ViewModel.
|
||||||
*/
|
*/
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
@Suppress("TooManyFunctions", "LargeClass")
|
@Suppress("TooManyFunctions", "LargeClass", "LongParameterList")
|
||||||
class VaultAddEditViewModel @Inject constructor(
|
class VaultAddEditViewModel @Inject constructor(
|
||||||
savedStateHandle: SavedStateHandle,
|
savedStateHandle: SavedStateHandle,
|
||||||
private val authRepository: AuthRepository,
|
private val authRepository: AuthRepository,
|
||||||
private val clipboardManager: BitwardenClipboardManager,
|
private val clipboardManager: BitwardenClipboardManager,
|
||||||
private val vaultRepository: VaultRepository,
|
private val vaultRepository: VaultRepository,
|
||||||
private val generatorRepository: GeneratorRepository,
|
private val generatorRepository: GeneratorRepository,
|
||||||
|
private val specialCircumstanceManager: SpecialCircumstanceManager,
|
||||||
private val resourceManager: ResourceManager,
|
private val resourceManager: ResourceManager,
|
||||||
) : BaseViewModel<VaultAddEditState, VaultAddEditEvent, VaultAddEditAction>(
|
) : BaseViewModel<VaultAddEditState, VaultAddEditEvent, VaultAddEditAction>(
|
||||||
// We load the state from the savedStateHandle for testing purposes.
|
// We load the state from the savedStateHandle for testing purposes.
|
||||||
initialState = savedStateHandle[KEY_STATE]
|
initialState = savedStateHandle[KEY_STATE]
|
||||||
?: run {
|
?: run {
|
||||||
val vaultAddEditType = VaultAddEditArgs(savedStateHandle).vaultAddEditType
|
val vaultAddEditType = VaultAddEditArgs(savedStateHandle).vaultAddEditType
|
||||||
|
|
||||||
|
// Check for autofill data to pre-populate
|
||||||
|
val autofillSelectionData: AutofillSelectionData? =
|
||||||
|
when (val specialCircumstance = specialCircumstanceManager.specialCircumstance) {
|
||||||
|
is SpecialCircumstance.AutofillSelection -> {
|
||||||
|
specialCircumstance.autofillSelectionData
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
val defaultAddTypeContent = autofillSelectionData
|
||||||
|
?.toDefaultAddTypeContent()
|
||||||
|
?: VaultAddEditState.ViewState.Content(
|
||||||
|
common = VaultAddEditState.ViewState.Content.Common(),
|
||||||
|
type = VaultAddEditState.ViewState.Content.ItemType.Login(),
|
||||||
|
)
|
||||||
|
|
||||||
VaultAddEditState(
|
VaultAddEditState(
|
||||||
vaultAddEditType = vaultAddEditType,
|
vaultAddEditType = vaultAddEditType,
|
||||||
viewState = when (vaultAddEditType) {
|
viewState = when (vaultAddEditType) {
|
||||||
VaultAddEditType.AddItem -> VaultAddEditState.ViewState.Content(
|
VaultAddEditType.AddItem -> defaultAddTypeContent
|
||||||
common = VaultAddEditState.ViewState.Content.Common(),
|
|
||||||
type = VaultAddEditState.ViewState.Content.ItemType.Login(),
|
|
||||||
)
|
|
||||||
|
|
||||||
is VaultAddEditType.EditItem -> VaultAddEditState.ViewState.Loading
|
is VaultAddEditType.EditItem -> VaultAddEditState.ViewState.Loading
|
||||||
is VaultAddEditType.CloneItem -> VaultAddEditState.ViewState.Loading
|
is VaultAddEditType.CloneItem -> VaultAddEditState.ViewState.Loading
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.x8bit.bitwarden.ui.vault.feature.addedit.util
|
||||||
|
|
||||||
|
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
||||||
|
import com.x8bit.bitwarden.ui.platform.base.util.toHostOrPathOrNull
|
||||||
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditState
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns pre-filled content that may be used for an "add" type
|
||||||
|
* [VaultAddEditState.ViewState.Content].
|
||||||
|
*/
|
||||||
|
fun AutofillSelectionData.toDefaultAddTypeContent(): VaultAddEditState.ViewState.Content {
|
||||||
|
val uri = this.uri
|
||||||
|
val simpleUri = uri?.toHostOrPathOrNull()
|
||||||
|
val defaultAddType = when (this.type) {
|
||||||
|
AutofillSelectionData.Type.CARD -> {
|
||||||
|
VaultAddEditState.ViewState.Content.ItemType.Card()
|
||||||
|
}
|
||||||
|
|
||||||
|
AutofillSelectionData.Type.LOGIN -> {
|
||||||
|
VaultAddEditState.ViewState.Content.ItemType.Login(
|
||||||
|
uri = uri.orEmpty(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return VaultAddEditState.ViewState.Content(
|
||||||
|
common = VaultAddEditState.ViewState.Content.Common(
|
||||||
|
name = simpleUri.orEmpty(),
|
||||||
|
),
|
||||||
|
type = defaultAddType,
|
||||||
|
)
|
||||||
|
}
|
|
@ -7,7 +7,11 @@ import com.bitwarden.core.UriMatchType
|
||||||
import com.x8bit.bitwarden.R
|
import com.x8bit.bitwarden.R
|
||||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||||
import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult
|
import com.x8bit.bitwarden.data.auth.repository.model.BreachCountResult
|
||||||
|
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
||||||
|
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManager
|
||||||
|
import com.x8bit.bitwarden.data.platform.manager.SpecialCircumstanceManagerImpl
|
||||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||||
|
import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
|
||||||
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
import com.x8bit.bitwarden.data.platform.repository.model.DataState
|
||||||
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
||||||
import com.x8bit.bitwarden.data.tools.generator.repository.GeneratorRepository
|
import com.x8bit.bitwarden.data.tools.generator.repository.GeneratorRepository
|
||||||
|
@ -27,6 +31,7 @@ import com.x8bit.bitwarden.ui.vault.feature.addedit.model.CustomFieldAction
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.CustomFieldType
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.CustomFieldType
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.UriItem
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.UriItem
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.toCustomField
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.model.toCustomField
|
||||||
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toDefaultAddTypeContent
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toViewState
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.util.toViewState
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType
|
import com.x8bit.bitwarden.ui.vault.model.VaultAddEditType
|
||||||
import com.x8bit.bitwarden.ui.vault.model.VaultCardBrand
|
import com.x8bit.bitwarden.ui.vault.model.VaultCardBrand
|
||||||
|
@ -74,6 +79,8 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||||
every { getVaultItemStateFlow(DEFAULT_EDIT_ITEM_ID) } returns mutableVaultItemFlow
|
every { getVaultItemStateFlow(DEFAULT_EDIT_ITEM_ID) } returns mutableVaultItemFlow
|
||||||
every { totpCodeFlow } returns totpTestCodeFlow
|
every { totpCodeFlow } returns totpTestCodeFlow
|
||||||
}
|
}
|
||||||
|
private val specialCircumstanceManager: SpecialCircumstanceManager =
|
||||||
|
SpecialCircumstanceManagerImpl()
|
||||||
|
|
||||||
private val generatorRepository: GeneratorRepository = FakeGeneratorRepository()
|
private val generatorRepository: GeneratorRepository = FakeGeneratorRepository()
|
||||||
|
|
||||||
|
@ -107,7 +114,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `initial add state should be correct`() = runTest {
|
fun `initial add state should be correct when not autofill`() = runTest {
|
||||||
val vaultAddEditType = VaultAddEditType.AddItem
|
val vaultAddEditType = VaultAddEditType.AddItem
|
||||||
val initState = createVaultAddItemState(vaultAddEditType = vaultAddEditType)
|
val initState = createVaultAddItemState(vaultAddEditType = vaultAddEditType)
|
||||||
val viewModel = createAddVaultItemViewModel(
|
val viewModel = createAddVaultItemViewModel(
|
||||||
|
@ -122,6 +129,35 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `initial add state should be correct when autofill`() = runTest {
|
||||||
|
val autofillSelectionData = AutofillSelectionData(
|
||||||
|
type = AutofillSelectionData.Type.LOGIN,
|
||||||
|
uri = "https://www.test.com",
|
||||||
|
)
|
||||||
|
specialCircumstanceManager.specialCircumstance = SpecialCircumstance.AutofillSelection(
|
||||||
|
autofillSelectionData = autofillSelectionData,
|
||||||
|
shouldFinishWhenComplete = true,
|
||||||
|
)
|
||||||
|
val autofillContentState = autofillSelectionData.toDefaultAddTypeContent()
|
||||||
|
val vaultAddEditType = VaultAddEditType.AddItem
|
||||||
|
val initState = createVaultAddItemState(
|
||||||
|
vaultAddEditType = vaultAddEditType,
|
||||||
|
commonContentViewState = autofillContentState.common,
|
||||||
|
typeContentViewState = autofillContentState.type,
|
||||||
|
)
|
||||||
|
val viewModel = createAddVaultItemViewModel(
|
||||||
|
savedStateHandle = createSavedStateHandleWithState(
|
||||||
|
state = initState,
|
||||||
|
vaultAddEditType = vaultAddEditType,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
assertEquals(initState, viewModel.stateFlow.value)
|
||||||
|
verify(exactly = 0) {
|
||||||
|
vaultRepository.getVaultItemStateFlow(DEFAULT_EDIT_ITEM_ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `initial edit state should be correct`() = runTest {
|
fun `initial edit state should be correct`() = runTest {
|
||||||
val vaultAddEditType = VaultAddEditType.EditItem(DEFAULT_EDIT_ITEM_ID)
|
val vaultAddEditType = VaultAddEditType.EditItem(DEFAULT_EDIT_ITEM_ID)
|
||||||
|
@ -1430,6 +1466,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||||
clipboardManager = clipboardManager,
|
clipboardManager = clipboardManager,
|
||||||
vaultRepository = vaultRepository,
|
vaultRepository = vaultRepository,
|
||||||
generatorRepository = generatorRepository,
|
generatorRepository = generatorRepository,
|
||||||
|
specialCircumstanceManager = specialCircumstanceManager,
|
||||||
resourceManager = resourceManager,
|
resourceManager = resourceManager,
|
||||||
authRepository = authRepository,
|
authRepository = authRepository,
|
||||||
)
|
)
|
||||||
|
@ -1950,6 +1987,7 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||||
clipboardManager = bitwardenClipboardManager,
|
clipboardManager = bitwardenClipboardManager,
|
||||||
vaultRepository = vaultRepo,
|
vaultRepository = vaultRepo,
|
||||||
generatorRepository = generatorRepo,
|
generatorRepository = generatorRepo,
|
||||||
|
specialCircumstanceManager = specialCircumstanceManager,
|
||||||
resourceManager = bitwardenResourceManager,
|
resourceManager = bitwardenResourceManager,
|
||||||
authRepository = authRepository,
|
authRepository = authRepository,
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.x8bit.bitwarden.ui.vault.feature.addedit.util
|
||||||
|
|
||||||
|
import com.x8bit.bitwarden.data.autofill.model.AutofillSelectionData
|
||||||
|
import com.x8bit.bitwarden.ui.vault.feature.addedit.VaultAddEditState
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class AutofillSelectionDataExtensionsTest {
|
||||||
|
@Test
|
||||||
|
fun `toDefaultAddTypeContent for a Card type should return the correct Content`() {
|
||||||
|
assertEquals(
|
||||||
|
VaultAddEditState.ViewState.Content(
|
||||||
|
common = VaultAddEditState.ViewState.Content.Common(),
|
||||||
|
type = VaultAddEditState.ViewState.Content.ItemType.Card(),
|
||||||
|
),
|
||||||
|
AutofillSelectionData(
|
||||||
|
type = AutofillSelectionData.Type.CARD,
|
||||||
|
uri = null,
|
||||||
|
)
|
||||||
|
.toDefaultAddTypeContent(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `toDefaultAddTypeContent for a Login type should return the correct Content`() {
|
||||||
|
assertEquals(
|
||||||
|
VaultAddEditState.ViewState.Content(
|
||||||
|
common = VaultAddEditState.ViewState.Content.Common(
|
||||||
|
name = "www.test.com",
|
||||||
|
),
|
||||||
|
type = VaultAddEditState.ViewState.Content.ItemType.Login(
|
||||||
|
uri = "https://www.test.com",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AutofillSelectionData(
|
||||||
|
type = AutofillSelectionData.Type.LOGIN,
|
||||||
|
uri = "https://www.test.com",
|
||||||
|
)
|
||||||
|
.toDefaultAddTypeContent(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue