improvement: If there are both WebView and Android fields to Autofill then only fill the WebView's fields

This commit is contained in:
Artem Chepurnoy 2024-03-26 12:32:53 +02:00
parent 7c9e20dd92
commit 8d1f55b867
No known key found for this signature in database
GPG Key ID: FAC37D0CF674043E
1 changed files with 26 additions and 2 deletions

View File

@ -30,6 +30,7 @@ class AutofillStructureParser {
val hint: AutofillHint, val hint: AutofillHint,
val value: String? = null, val value: String? = null,
val reason: String? = null, val reason: String? = null,
val parentWebViewNodeId: Int?,
) { ) {
enum class Accuracy( enum class Accuracy(
val value: Float, val value: Float,
@ -379,7 +380,9 @@ class AutofillStructureParser {
applicationId = appIdCandidate applicationId = appIdCandidate
// Parse view node // Parse view node
val nodeAutofillStructure = parseViewNode(windowNode.rootViewNode) val nodeAutofillStructure = parseViewNode(
node = windowNode.rootViewNode,
)
val nodeAutofillStructureHasItems = nodeAutofillStructure.items val nodeAutofillStructureHasItems = nodeAutofillStructure.items
.any { it.hint != AutofillHint.OFF } .any { it.hint != AutofillHint.OFF }
if (nodeAutofillStructureHasItems) { if (nodeAutofillStructureHasItems) {
@ -394,8 +397,20 @@ class AutofillStructureParser {
val value: String?, val value: String?,
) )
// If there's a WebView then we autofill only the
// items that come from a WebView.
val allowOnlyWebViewItems = autofillStructure?.webView == true
val items = mutableListOf<AutofillStructure2.Item>() val items = mutableListOf<AutofillStructure2.Item>()
autofillStructure?.items.orEmpty() autofillStructure?.items.orEmpty()
.let { list ->
if (allowOnlyWebViewItems) {
return@let list
.filter { it.parentWebViewNodeId != null }
}
list
}
.let { list -> .let { list ->
// We are solving the problem that the app actually detect message fields in // We are solving the problem that the app actually detect message fields in
// Slack/Signal/other apps as username fields. If the accuracy is low and we // Slack/Signal/other apps as username fields. If the accuracy is low and we
@ -519,8 +534,13 @@ class AutofillStructureParser {
private fun parseViewNode( private fun parseViewNode(
node: AssistStructure.ViewNode, node: AssistStructure.ViewNode,
parentWebViewNodeId: Int? = null,
): AutofillStructure { ): AutofillStructure {
var webView = node.className == "android.webkit.WebView" var webView = node.className == "android.webkit.WebView"
val webViewNodeId = node.id
.takeIf { webView }
?: parentWebViewNodeId
var webDomain: String? = node.webDomain?.takeIf { it.isNotEmpty() } var webDomain: String? = node.webDomain?.takeIf { it.isNotEmpty() }
var webScheme: String? = var webScheme: String? =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
@ -556,12 +576,16 @@ class AutofillStructureParser {
value = it.value value = it.value
?: node.autofillValue?.takeIf { it.isText }?.textValue?.toString(), ?: node.autofillValue?.takeIf { it.isText }?.textValue?.toString(),
reason = it.reason, reason = it.reason,
parentWebViewNodeId = webViewNodeId,
) )
} }
} }
// Recursive method to process each node // Recursive method to process each node
for (i in 0 until node.childCount) { for (i in 0 until node.childCount) {
val childStructure = parseViewNode(node.getChildAt(i)) val childStructure = parseViewNode(
node = node.getChildAt(i),
parentWebViewNodeId = webViewNodeId,
)
if (childStructure.webView) { if (childStructure.webView) {
webView = childStructure.webView webView = childStructure.webView
} }