Add support for AutoCompleteTextView as an input field (#3435)

This commit is contained in:
David Perez 2024-07-10 11:40:46 -05:00 committed by GitHub
parent 0cdae9bccf
commit 4f3d42264d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 34 additions and 9 deletions

View file

@ -2,14 +2,10 @@ package com.x8bit.bitwarden.data.autofill.util
import android.app.assist.AssistStructure import android.app.assist.AssistStructure
import android.view.View import android.view.View
import android.widget.EditText
import com.x8bit.bitwarden.data.autofill.model.AutofillView import com.x8bit.bitwarden.data.autofill.model.AutofillView
import com.x8bit.bitwarden.ui.platform.base.util.orNullIfBlank import com.x8bit.bitwarden.ui.platform.base.util.orNullIfBlank
/**
* The class name of the android edit text field.
*/
private const val ANDROID_EDIT_TEXT_CLASS_NAME: String = "android.widget.EditText"
/** /**
* The default web URI scheme. * The default web URI scheme.
*/ */
@ -59,7 +55,18 @@ private val SUPPORTED_VIEW_HINTS: List<String> = listOf(
* Whether this [AssistStructure.ViewNode] represents an input field. * Whether this [AssistStructure.ViewNode] represents an input field.
*/ */
private val AssistStructure.ViewNode.isInputField: Boolean private val AssistStructure.ViewNode.isInputField: Boolean
get() = className == ANDROID_EDIT_TEXT_CLASS_NAME || htmlInfo.isInputField get() {
val isEditText = className
?.let {
try {
Class.forName(it)
} catch (e: ClassNotFoundException) {
null
}
}
?.let { EditText::class.java.isAssignableFrom(it) } == true
return isEditText || htmlInfo.isInputField
}
/** /**
* Attempt to convert this [AssistStructure.ViewNode] into an [AutofillView]. If the view node * Attempt to convert this [AssistStructure.ViewNode] into an [AutofillView]. If the view node

View file

@ -177,13 +177,32 @@ class ViewNodeExtensionsTest {
@Suppress("MaxLineLength") @Suppress("MaxLineLength")
@Test @Test
fun `toAutofillView should return AutofillView Login Username when is android text field and is isUsernameField`() { fun `toAutofillView should return AutofillView Login Username when is EditText and isUsernameField`() {
// Setup // Setup
val expected = AutofillView.Login.Username( val expected = AutofillView.Login.Username(
data = autofillViewData, data = autofillViewData,
) )
setupUnsupportedInputFieldViewNode() setupUnsupportedInputFieldViewNode()
every { viewNode.className } returns ANDROID_EDIT_TEXT_CLASS_NAME every { viewNode.className } returns "android.widget.EditText"
every { any<Int>().isPasswordInputType } returns false
every { any<Int>().isUsernameInputType } returns true
// Test
val actual = viewNode.toAutofillView()
// Verify
assertEquals(expected, actual)
}
@Suppress("MaxLineLength")
@Test
fun `toAutofillView should return AutofillView Login Username when is EditText subclass and isUsernameField`() {
// Setup
val expected = AutofillView.Login.Username(
data = autofillViewData,
)
setupUnsupportedInputFieldViewNode()
every { viewNode.className } returns "android.widget.AutoCompleteTextView"
every { any<Int>().isPasswordInputType } returns false every { any<Int>().isPasswordInputType } returns false
every { any<Int>().isUsernameInputType } returns true every { any<Int>().isUsernameInputType } returns true
@ -532,7 +551,6 @@ private val AUTOFILL_OPTIONS_LIST: List<String> = listOf(
AUTOFILL_OPTION_TWO, AUTOFILL_OPTION_TWO,
) )
private const val AUTOFILL_TYPE: Int = View.AUTOFILL_TYPE_LIST private const val AUTOFILL_TYPE: Int = View.AUTOFILL_TYPE_LIST
private const val ANDROID_EDIT_TEXT_CLASS_NAME: String = "android.widget.EditText"
private val IGNORED_RAW_HINTS: List<String> = listOf( private val IGNORED_RAW_HINTS: List<String> = listOf(
"search", "search",
"find", "find",