mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Fix autofill for Android app #502
This commit is contained in:
@@ -20,6 +20,7 @@ package com.kunzisoft.keepass.autofill
|
|||||||
|
|
||||||
import android.app.assist.AssistStructure
|
import android.app.assist.AssistStructure
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.text.InputType
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -63,15 +64,17 @@ internal class StructureParser(private val structure: AssistStructure) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun parseViewNode(node: AssistStructure.ViewNode): Boolean {
|
private fun parseViewNode(node: AssistStructure.ViewNode): Boolean {
|
||||||
if (node.autofillId != null) {
|
if (node.autofillId != null
|
||||||
|
&& node.autofillType == View.AUTOFILL_TYPE_TEXT) {
|
||||||
|
// Parse methods
|
||||||
val hints = node.autofillHints
|
val hints = node.autofillHints
|
||||||
if (hints != null && hints.isNotEmpty()) {
|
if (hints != null && hints.isNotEmpty()) {
|
||||||
if (parseNodeByAutofillHint(node))
|
if (parseNodeByAutofillHint(node))
|
||||||
return true
|
return true
|
||||||
} else {
|
} else if (parseNodeByHtmlAttributes(node))
|
||||||
if (parseNodeByHtmlAttributes(node))
|
return true
|
||||||
return true
|
else if (parseNodeByAndroidInput(node))
|
||||||
}
|
return true
|
||||||
}
|
}
|
||||||
// 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) {
|
||||||
@@ -121,15 +124,15 @@ internal class StructureParser(private val structure: AssistStructure) {
|
|||||||
when (pairAttribute.second.toLowerCase(Locale.ENGLISH)) {
|
when (pairAttribute.second.toLowerCase(Locale.ENGLISH)) {
|
||||||
"tel", "email" -> {
|
"tel", "email" -> {
|
||||||
result?.usernameId = autofillId
|
result?.usernameId = autofillId
|
||||||
Log.d(TAG, "Autofill username type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
|
Log.d(TAG, "Autofill username web type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
|
||||||
}
|
}
|
||||||
"text" -> {
|
"text" -> {
|
||||||
usernameCandidate = autofillId
|
usernameCandidate = autofillId
|
||||||
Log.d(TAG, "Autofill type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
|
Log.d(TAG, "Autofill username candidate web type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
|
||||||
}
|
}
|
||||||
"password" -> {
|
"password" -> {
|
||||||
result?.passwordId = autofillId
|
result?.passwordId = autofillId
|
||||||
Log.d(TAG, "Autofill password type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
|
Log.d(TAG, "Autofill password web type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,6 +144,48 @@ internal class StructureParser(private val structure: AssistStructure) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun parseNodeByAndroidInput(node: AssistStructure.ViewNode): Boolean {
|
||||||
|
val autofillId = node.autofillId
|
||||||
|
val inputType = node.inputType
|
||||||
|
if (inputType and InputType.TYPE_CLASS_TEXT != 0) {
|
||||||
|
when {
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS != 0 -> {
|
||||||
|
result?.usernameId = autofillId
|
||||||
|
Log.d(TAG, "Autofill username android type: $inputType")
|
||||||
|
}
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_NORMAL != 0 ||
|
||||||
|
inputType and InputType.TYPE_NUMBER_VARIATION_NORMAL != 0 ||
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_PERSON_NAME != 0 -> {
|
||||||
|
usernameCandidate = autofillId
|
||||||
|
Log.d(TAG, "Autofill username candidate android type: $inputType")
|
||||||
|
}
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_PASSWORD != 0 ||
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD != 0 ||
|
||||||
|
inputType and InputType.TYPE_NUMBER_VARIATION_PASSWORD != 0 -> {
|
||||||
|
result?.passwordId = autofillId
|
||||||
|
Log.d(TAG, "Autofill password android type: $inputType")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT != 0 ||
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_FILTER != 0 ||
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE != 0 ||
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_PHONETIC != 0 ||
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS != 0 ||
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_URI != 0 ||
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT != 0 ||
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS != 0 ||
|
||||||
|
inputType and InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD != 0 -> {
|
||||||
|
// Type not used
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Log.d(TAG, "Autofill unknown android type: $inputType")
|
||||||
|
usernameCandidate = autofillId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
internal class Result {
|
internal class Result {
|
||||||
var usernameId: AutofillId? = null
|
var usernameId: AutofillId? = null
|
||||||
|
|||||||
Reference in New Issue
Block a user