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.provider.AutofillCipherProvider
|
||||||
import com.x8bit.bitwarden.data.autofill.util.buildFilledItemOrNull
|
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
|
* The default [FilledDataBuilder]. This converts parsed autofill data into filled data that is
|
||||||
* ready to be loaded into an autofill response.
|
* ready to be loaded into an autofill response.
|
||||||
|
@ -21,7 +37,9 @@ class FilledDataBuilderImpl(
|
||||||
val isVaultLocked = autofillCipherProvider.isVaultLocked()
|
val isVaultLocked = autofillCipherProvider.isVaultLocked()
|
||||||
|
|
||||||
// Subtract one to make sure there is space for the vault item.
|
// 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.
|
// Track the number of inline suggestions that have been added.
|
||||||
var inlineSuggestionsAdded = 0
|
var inlineSuggestionsAdded = 0
|
||||||
|
|
||||||
|
@ -76,7 +94,7 @@ class FilledDataBuilderImpl(
|
||||||
?.getOrLastOrNull(inlineSuggestionsAdded)
|
?.getOrLastOrNull(inlineSuggestionsAdded)
|
||||||
|
|
||||||
return FilledData(
|
return FilledData(
|
||||||
filledPartitions = filledPartitions,
|
filledPartitions = filledPartitions.take(n = MAX_FILLED_PARTITIONS_COUNT),
|
||||||
ignoreAutofillIds = autofillRequest.ignoreAutofillIds,
|
ignoreAutofillIds = autofillRequest.ignoreAutofillIds,
|
||||||
originalPartition = autofillRequest.partition,
|
originalPartition = autofillRequest.partition,
|
||||||
uri = autofillRequest.uri,
|
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 {
|
companion object {
|
||||||
private const val URI: String = "androidapp://com.x8bit.bitwarden"
|
private const val URI: String = "androidapp://com.x8bit.bitwarden"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue