mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 07:05:35 +03:00
BIT-2446: Limit the number of inline autofill items that can be displayed (#3418)
This commit is contained in:
parent
01b786fcf9
commit
adf7916a4c
2 changed files with 110 additions and 2 deletions
|
@ -10,6 +10,22 @@ import com.x8bit.bitwarden.data.autofill.model.FilledPartition
|
|||
import com.x8bit.bitwarden.data.autofill.provider.AutofillCipherProvider
|
||||
import com.x8bit.bitwarden.data.autofill.util.buildFilledItemOrNull
|
||||
|
||||
/**
|
||||
* The maximum amount of filled partitions the user will see. Viewing the rest will require opening
|
||||
* the vault.
|
||||
*
|
||||
* Note: The vault item is not included in this count.
|
||||
*/
|
||||
private const val MAX_FILLED_PARTITIONS_COUNT: Int = 20
|
||||
|
||||
/**
|
||||
* The maximum amount of inline suggestions the user will see. Viewing the rest will require
|
||||
* opening the vault.
|
||||
*
|
||||
* Note: The vault item is not included in this count.
|
||||
*/
|
||||
private const val MAX_INLINE_SUGGESTION_COUNT: Int = 5
|
||||
|
||||
/**
|
||||
* The default [FilledDataBuilder]. This converts parsed autofill data into filled data that is
|
||||
* ready to be loaded into an autofill response.
|
||||
|
@ -21,7 +37,9 @@ class FilledDataBuilderImpl(
|
|||
val isVaultLocked = autofillCipherProvider.isVaultLocked()
|
||||
|
||||
// Subtract one to make sure there is space for the vault item.
|
||||
val maxCipherInlineSuggestionsCount = autofillRequest.maxInlineSuggestionsCount - 1
|
||||
val maxCipherInlineSuggestionsCount = (autofillRequest.maxInlineSuggestionsCount - 1)
|
||||
.coerceAtMost(maximumValue = MAX_INLINE_SUGGESTION_COUNT)
|
||||
|
||||
// Track the number of inline suggestions that have been added.
|
||||
var inlineSuggestionsAdded = 0
|
||||
|
||||
|
@ -76,7 +94,7 @@ class FilledDataBuilderImpl(
|
|||
?.getOrLastOrNull(inlineSuggestionsAdded)
|
||||
|
||||
return FilledData(
|
||||
filledPartitions = filledPartitions,
|
||||
filledPartitions = filledPartitions.take(n = MAX_FILLED_PARTITIONS_COUNT),
|
||||
ignoreAutofillIds = autofillRequest.ignoreAutofillIds,
|
||||
originalPartition = autofillRequest.partition,
|
||||
uri = autofillRequest.uri,
|
||||
|
|
|
@ -361,6 +361,96 @@ class FilledDataBuilderTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `build should return filled data with hard-coded max count of inline specs and partitions`() =
|
||||
runTest {
|
||||
// Setup
|
||||
val password = "Password"
|
||||
val username = "johnDoe"
|
||||
val autofillCipher = AutofillCipher.Login(
|
||||
cipherId = null,
|
||||
isTotpEnabled = false,
|
||||
name = "Cipher One",
|
||||
password = password,
|
||||
username = username,
|
||||
subtitle = "Subtitle",
|
||||
)
|
||||
val filledItemPassword: FilledItem = mockk()
|
||||
val filledItemUsername: FilledItem = mockk()
|
||||
val autofillViewPassword: AutofillView.Login.Password = mockk {
|
||||
every { buildFilledItemOrNull(password) } returns filledItemPassword
|
||||
}
|
||||
val autofillViewUsername: AutofillView.Login.Username = mockk {
|
||||
every { buildFilledItemOrNull(username) } returns filledItemUsername
|
||||
}
|
||||
val autofillPartition = AutofillPartition.Login(
|
||||
views = listOf(autofillViewPassword, autofillViewUsername),
|
||||
)
|
||||
val inlinePresentationSpec: InlinePresentationSpec = mockk()
|
||||
val autofillRequest = AutofillRequest.Fillable(
|
||||
ignoreAutofillIds = emptyList(),
|
||||
inlinePresentationSpecs = listOf(inlinePresentationSpec),
|
||||
maxInlineSuggestionsCount = 10,
|
||||
packageName = null,
|
||||
partition = autofillPartition,
|
||||
uri = URI,
|
||||
)
|
||||
val filledPartition = FilledPartition(
|
||||
autofillCipher = autofillCipher,
|
||||
filledItems = listOf(filledItemPassword, filledItemUsername),
|
||||
inlinePresentationSpec = inlinePresentationSpec,
|
||||
)
|
||||
val expected = FilledData(
|
||||
// 5 with inline specs, 20 total
|
||||
filledPartitions = listOf(
|
||||
filledPartition,
|
||||
filledPartition.copy(),
|
||||
filledPartition.copy(),
|
||||
filledPartition.copy(),
|
||||
filledPartition.copy(),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
filledPartition.copy(inlinePresentationSpec = null),
|
||||
),
|
||||
ignoreAutofillIds = emptyList(),
|
||||
originalPartition = autofillPartition,
|
||||
uri = URI,
|
||||
vaultItemInlinePresentationSpec = inlinePresentationSpec,
|
||||
isVaultLocked = false,
|
||||
)
|
||||
coEvery {
|
||||
autofillCipherProvider.getLoginAutofillCiphers(uri = URI)
|
||||
} returns List(size = 22) { autofillCipher }
|
||||
|
||||
// Test
|
||||
val actual = filledDataBuilder.build(
|
||||
autofillRequest = autofillRequest,
|
||||
)
|
||||
|
||||
// Verify
|
||||
assertEquals(expected, actual)
|
||||
coVerify(exactly = 1) {
|
||||
autofillCipherProvider.getLoginAutofillCiphers(uri = URI)
|
||||
}
|
||||
verify(exactly = 22) {
|
||||
autofillViewPassword.buildFilledItemOrNull(password)
|
||||
autofillViewUsername.buildFilledItemOrNull(username)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val URI: String = "androidapp://com.x8bit.bitwarden"
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue