Register username and password in entry

This commit is contained in:
J-Jamet
2020-10-12 14:24:52 +02:00
parent 193ef74e63
commit 7047bcbb1e
11 changed files with 190 additions and 113 deletions

View File

@@ -36,6 +36,7 @@ import com.kunzisoft.keepass.autofill.AutofillHelper
import com.kunzisoft.keepass.autofill.KeeAutofillService
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.search.SearchHelper
import com.kunzisoft.keepass.model.RegisterInfo
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.settings.PreferencesUtil
@@ -44,12 +45,6 @@ class AutofillLauncherActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Build search param
val searchInfo = SearchInfo().apply {
applicationId = intent.getStringExtra(KEY_SEARCH_APPLICATION_ID)
webDomain = intent.getStringExtra(KEY_SEARCH_DOMAIN)
}
// Retrieve selection mode
EntrySelectionHelper.retrieveSpecialModeFromIntent(intent).let { specialMode ->
when (specialMode) {
@@ -59,6 +54,11 @@ class AutofillLauncherActivity : AppCompatActivity() {
finish()
}
SpecialMode.SELECTION -> {
// Build search param
val searchInfo = SearchInfo().apply {
applicationId = intent.getStringExtra(KEY_SEARCH_APPLICATION_ID)
webDomain = intent.getStringExtra(KEY_SEARCH_DOMAIN)
}
// Pass extra for Autofill (EXTRA_ASSIST_STRUCTURE)
val assistStructure = AutofillHelper.retrieveAssistStructure(intent)
@@ -100,6 +100,9 @@ class AutofillLauncherActivity : AppCompatActivity() {
}
}
SpecialMode.REGISTRATION -> {
// To register info
val registerInfo = intent.getParcelableExtra<RegisterInfo>(KEY_REGISTER_INFO)
val searchInfo = SearchInfo(registerInfo?.searchInfo)
if (!KeeAutofillService.autofillAllowedFor(searchInfo.applicationId,
PreferencesUtil.applicationIdBlocklist(this))
|| !KeeAutofillService.autofillAllowedFor(searchInfo.webDomain,
@@ -114,17 +117,17 @@ class AutofillLauncherActivity : AppCompatActivity() {
{ _ ->
// Show the database UI to select the entry
GroupActivity.launchForRegistration(this,
searchInfo)
registerInfo)
},
{
// Show the database UI to select the entry
GroupActivity.launchForRegistration(this,
searchInfo)
registerInfo)
},
{
// If database not open
FileDatabaseSelectActivity.launchForRegistration(this,
searchInfo)
registerInfo)
}
)
}
@@ -146,6 +149,8 @@ class AutofillLauncherActivity : AppCompatActivity() {
private const val KEY_SEARCH_APPLICATION_ID = "KEY_SEARCH_APPLICATION_ID"
private const val KEY_SEARCH_DOMAIN = "KEY_SEARCH_DOMAIN"
private const val KEY_REGISTER_INFO = "KEY_REGISTER_INFO"
fun getAuthIntentSenderForResponse(context: Context,
searchInfo: SearchInfo? = null): IntentSender {
return PendingIntent.getActivity(context, 0,
@@ -160,13 +165,10 @@ class AutofillLauncherActivity : AppCompatActivity() {
}
fun launchForRegistration(context: Context,
searchInfo: SearchInfo? = null) {
registerInfo: RegisterInfo) {
val intent = Intent(context, AutofillLauncherActivity::class.java)
EntrySelectionHelper.addSpecialModeInIntent(intent, SpecialMode.REGISTRATION)
searchInfo?.let {
intent.putExtra(KEY_SEARCH_APPLICATION_ID, it.applicationId)
intent.putExtra(KEY_SEARCH_DOMAIN, it.webDomain)
}
intent.putExtra(KEY_REGISTER_INFO, registerInfo)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
}

View File

@@ -45,7 +45,6 @@ import com.kunzisoft.keepass.activities.dialogs.*
import com.kunzisoft.keepass.activities.dialogs.FileTooBigDialogFragment.Companion.MAX_WARNING_BINARY_FILE
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.activities.helpers.SelectFileHelper
import com.kunzisoft.keepass.activities.helpers.SpecialMode
import com.kunzisoft.keepass.activities.lock.LockingActivity
import com.kunzisoft.keepass.database.element.*
import com.kunzisoft.keepass.database.element.icon.IconImage
@@ -176,17 +175,24 @@ class EntryEditActivity : LockingActivity(),
}
// Retrieve data from registration
tempEntryInfo?.customFields
val searchInfo = EntrySelectionHelper.retrieveSearchInfoFromIntent(intent)
searchInfo?.webDomain?.let { webDomain ->
tempEntryInfo?.addUniqueField(Field(EntryInfo.WEB_DOMAIN_FIELD_NAME,
ProtectedString(false, webDomain))
)
} ?: run {
searchInfo?.applicationId?.let { applicationId ->
tempEntryInfo?.addUniqueField(Field(EntryInfo.APPLICATION_ID_FIELD_NAME,
ProtectedString(false, applicationId))
val registerInfo = EntrySelectionHelper.retrieveRegisterInfoFromIntent(intent)
registerInfo?.username?.let {
tempEntryInfo?.username = it
}
registerInfo?.password?.let {
tempEntryInfo?.password = it
}
registerInfo?.searchInfo?.let { searchInfo ->
searchInfo.webDomain?.let { webDomain ->
tempEntryInfo?.addUniqueField(Field(EntryInfo.WEB_DOMAIN_FIELD_NAME,
ProtectedString(false, webDomain))
)
} ?: run {
searchInfo.applicationId?.let { applicationId ->
tempEntryInfo?.addUniqueField(Field(EntryInfo.APPLICATION_ID_FIELD_NAME,
ProtectedString(false, applicationId))
)
}
}
}
@@ -774,14 +780,13 @@ class EntryEditActivity : LockingActivity(),
*/
fun launchForRegistration(context: Context,
entry: Entry,
searchInfo: SearchInfo? = null) {
registerInfo: RegisterInfo? = null) {
if (TimeoutHelper.checkTimeAndLockIfTimeout(context)) {
val intent = Intent(context, EntryEditActivity::class.java)
intent.putExtra(KEY_ENTRY, entry.nodeId)
EntrySelectionHelper.startActivityForSpecialModeResult(context,
EntrySelectionHelper.startActivityForRegistrationModeResult(context,
intent,
SpecialMode.REGISTRATION,
searchInfo)
registerInfo)
}
}
@@ -790,14 +795,13 @@ class EntryEditActivity : LockingActivity(),
*/
fun launchForRegistration(context: Context,
group: Group,
searchInfo: SearchInfo? = null) {
registerInfo: RegisterInfo? = null) {
if (TimeoutHelper.checkTimeAndLockIfTimeout(context)) {
val intent = Intent(context, EntryEditActivity::class.java)
intent.putExtra(KEY_PARENT, group.nodeId)
EntrySelectionHelper.startActivityForSpecialModeResult(context,
EntrySelectionHelper.startActivityForRegistrationModeResult(context,
intent,
SpecialMode.REGISTRATION,
searchInfo)
registerInfo)
}
}
}

View File

@@ -53,6 +53,7 @@ import com.kunzisoft.keepass.autofill.AutofillHelper
import com.kunzisoft.keepass.database.action.ProgressDatabaseTaskProvider
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.education.FileDatabaseSelectActivityEducation
import com.kunzisoft.keepass.model.RegisterInfo
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_TASK
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_URI_KEY
@@ -503,9 +504,8 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
fun launchForEntrySelectionResult(activity: Activity,
searchInfo: SearchInfo? = null) {
EntrySelectionHelper.startActivityForSpecialModeResult(activity,
EntrySelectionHelper.startActivityForSelectionModeResult(activity,
Intent(activity, FileDatabaseSelectActivity::class.java),
SpecialMode.SELECTION,
searchInfo)
}
@@ -531,11 +531,10 @@ class FileDatabaseSelectActivity : SpecialModeActivity(),
* -------------------------
*/
fun launchForRegistration(context: Context,
searchInfo: SearchInfo? = null) {
EntrySelectionHelper.startActivityForSpecialModeResult(context,
registerInfo: RegisterInfo? = null) {
EntrySelectionHelper.startActivityForRegistrationModeResult(context,
Intent(context, FileDatabaseSelectActivity::class.java),
SpecialMode.REGISTRATION,
searchInfo)
registerInfo)
}
}
}

View File

@@ -66,6 +66,7 @@ import com.kunzisoft.keepass.database.element.node.NodeId
import com.kunzisoft.keepass.database.element.node.Type
import com.kunzisoft.keepass.education.GroupActivityEducation
import com.kunzisoft.keepass.icons.assignDatabaseIcon
import com.kunzisoft.keepass.model.RegisterInfo
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.model.getSearchString
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_COPY_NODES_TASK
@@ -1050,7 +1051,7 @@ class GroupActivity : LockingActivity(),
// Else in root, lock if needed
else {
intent.removeExtra(AUTO_SEARCH_KEY)
EntrySelectionHelper.removeSearchInfoFromIntent(intent)
EntrySelectionHelper.removeInfoFromIntent(intent)
if (PreferencesUtil.isLockDatabaseWhenBackButtonOnRootClicked(this)) {
lockAndExit()
super.onBackPressed()
@@ -1131,9 +1132,8 @@ class GroupActivity : LockingActivity(),
readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(context)) {
checkTimeAndBuildIntent(context, null, readOnly) { intent ->
intent.putExtra(AUTO_SEARCH_KEY, autoSearch)
EntrySelectionHelper.startActivityForSpecialModeResult(context,
EntrySelectionHelper.startActivityForSelectionModeResult(context,
intent,
SpecialMode.SELECTION,
searchInfo)
}
}
@@ -1164,13 +1164,12 @@ class GroupActivity : LockingActivity(),
* -------------------------
*/
fun launchForRegistration(context: Context,
searchInfo: SearchInfo? = null) {
registerInfo: RegisterInfo? = null) {
checkTimeAndBuildIntent(context, null, false) { intent ->
intent.putExtra(AUTO_SEARCH_KEY, false)
EntrySelectionHelper.startActivityForSpecialModeResult(context,
EntrySelectionHelper.startActivityForRegistrationModeResult(context,
intent,
SpecialMode.REGISTRATION,
searchInfo)
registerInfo)
}
}
}

View File

@@ -58,6 +58,7 @@ import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException
import com.kunzisoft.keepass.database.search.SearchHelper
import com.kunzisoft.keepass.education.PasswordActivityEducation
import com.kunzisoft.keepass.model.RegisterInfo
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.CIPHER_ENTITY_KEY
@@ -356,19 +357,19 @@ open class PasswordActivity : SpecialModeActivity() {
)
}
},
{ searchInfo ->
{ registerInfo ->
SearchHelper.checkAutoSearchInfo(this,
Database.getInstance(),
searchInfo,
registerInfo?.searchInfo,
{ _ ->
// No auto search, it's a registration
GroupActivity.launchForRegistration(this,
searchInfo)
registerInfo)
},
{
// Here no search info found, disable auto search
GroupActivity.launchForRegistration(this@PasswordActivity,
searchInfo)
registerInfo)
},
{
// Simply close if database not opened, normally not happened
@@ -855,10 +856,9 @@ open class PasswordActivity : SpecialModeActivity() {
keyFile: Uri?,
searchInfo: SearchInfo?) {
buildAndLaunchIntent(activity, databaseFile, keyFile) { intent ->
EntrySelectionHelper.startActivityForSpecialModeResult(
EntrySelectionHelper.startActivityForSelectionModeResult(
activity,
intent,
SpecialMode.SELECTION,
searchInfo)
}
}
@@ -897,13 +897,12 @@ open class PasswordActivity : SpecialModeActivity() {
fun launchForRegistration(activity: Activity,
databaseFile: Uri,
keyFile: Uri?,
searchInfo: SearchInfo?) {
registerInfo: RegisterInfo?) {
buildAndLaunchIntent(activity, databaseFile, keyFile) { intent ->
EntrySelectionHelper.startActivityForSpecialModeResult(
EntrySelectionHelper.startActivityForRegistrationModeResult(
activity,
intent,
SpecialMode.REGISTRATION,
searchInfo)
registerInfo)
}
}
}

View File

@@ -24,6 +24,7 @@ import android.content.Context
import android.content.Intent
import android.os.Build
import com.kunzisoft.keepass.autofill.AutofillHelper
import com.kunzisoft.keepass.model.RegisterInfo
import com.kunzisoft.keepass.model.SearchInfo
import java.io.Serializable
@@ -32,15 +33,23 @@ object EntrySelectionHelper {
private const val KEY_SPECIAL_MODE = "com.kunzisoft.keepass.extra.SPECIAL_MODE"
private const val KEY_TYPE_MODE = "com.kunzisoft.keepass.extra.TYPE_MODE"
private const val KEY_SEARCH_INFO = "com.kunzisoft.keepass.extra.SEARCH_INFO"
private const val KEY_REGISTER_INFO = "com.kunzisoft.keepass.extra.REGISTER_INFO"
fun startActivityForSpecialModeResult(context: Context,
intent: Intent,
specialMode: SpecialMode,
searchInfo: SearchInfo?) {
addSpecialModeInIntent(intent, specialMode)
fun startActivityForSelectionModeResult(context: Context,
intent: Intent,
searchInfo: SearchInfo?) {
addSpecialModeInIntent(intent, SpecialMode.SELECTION)
addSearchInfoInIntent(intent, searchInfo)
context.startActivity(intent)
}
fun startActivityForRegistrationModeResult(context: Context,
intent: Intent,
registerInfo: RegisterInfo?) {
addSpecialModeInIntent(intent, SpecialMode.REGISTRATION)
// At the moment, only autofill for registration
addTypeModeInIntent(intent, TypeMode.AUTOFILL)
addSearchInfoInIntent(intent, searchInfo)
addRegisterInfoInIntent(intent, registerInfo)
context.startActivity(intent)
}
@@ -54,8 +63,19 @@ object EntrySelectionHelper {
return intent.getParcelableExtra(KEY_SEARCH_INFO)
}
fun removeSearchInfoFromIntent(intent: Intent) {
fun addRegisterInfoInIntent(intent: Intent, registerInfo: RegisterInfo?) {
registerInfo?.let {
intent.putExtra(KEY_REGISTER_INFO, it)
}
}
fun retrieveRegisterInfoFromIntent(intent: Intent): RegisterInfo? {
return intent.getParcelableExtra(KEY_REGISTER_INFO)
}
fun removeInfoFromIntent(intent: Intent) {
intent.removeExtra(KEY_SEARCH_INFO)
intent.removeExtra(KEY_REGISTER_INFO)
}
fun addSpecialModeInIntent(intent: Intent, specialMode: SpecialMode) {
@@ -93,14 +113,14 @@ object EntrySelectionHelper {
keyboardSelectionAction: (searchInfo: SearchInfo?) -> Unit,
autofillSelectionAction: (searchInfo: SearchInfo?,
assistStructure: AssistStructure?) -> Unit,
registrationAction: (searchInfo: SearchInfo?) -> Unit) {
registrationAction: (registerInfo: RegisterInfo?) -> Unit) {
val searchInfo: SearchInfo? = retrieveSearchInfoFromIntent(intent)
when (retrieveSpecialModeFromIntent(intent)) {
SpecialMode.DEFAULT -> {
defaultAction.invoke(searchInfo)
defaultAction.invoke(retrieveSearchInfoFromIntent(intent))
}
SpecialMode.SELECTION -> {
val searchInfo: SearchInfo? = retrieveSearchInfoFromIntent(intent)
var assistStructureInit = false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AutofillHelper.retrieveAssistStructure(intent)?.let { assistStructure ->
@@ -122,7 +142,8 @@ object EntrySelectionHelper {
}
}
SpecialMode.REGISTRATION -> {
registrationAction.invoke(searchInfo)
val registerInfo: RegisterInfo? = retrieveRegisterInfoFromIntent(intent)
registrationAction.invoke(registerInfo)
}
}
}

View File

@@ -30,7 +30,8 @@ abstract class SpecialModeActivity : StylishActivity() {
mSpecialMode = EntrySelectionHelper.retrieveSpecialModeFromIntent(intent)
mTypeMode = EntrySelectionHelper.retrieveTypeModeFromIntent(intent)
val searchInfo: SearchInfo? = EntrySelectionHelper.retrieveSearchInfoFromIntent(intent)
val searchInfo: SearchInfo? = EntrySelectionHelper.retrieveRegisterInfoFromIntent(intent)?.searchInfo
?: EntrySelectionHelper.retrieveSearchInfoFromIntent(intent)
// To show the selection mode
mSpecialModeView = findViewById(R.id.special_mode_view)

View File

@@ -30,6 +30,7 @@ import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.AutofillLauncherActivity
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.search.SearchHelper
import com.kunzisoft.keepass.model.RegisterInfo
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.settings.PreferencesUtil
import java.util.concurrent.atomic.AtomicBoolean
@@ -65,10 +66,10 @@ class KeeAutofillService : AutofillService() {
// Build search info only if applicationId or webDomain are not blocked
if (autofillAllowedFor(parseResult.applicationId, applicationIdBlocklist)
&& autofillAllowedFor(parseResult.domain, webDomainBlocklist)) {
&& autofillAllowedFor(parseResult.webDomain, webDomainBlocklist)) {
val searchInfo = SearchInfo().apply {
applicationId = parseResult.applicationId
webDomain = parseResult.domain
webDomain = parseResult.webDomain
}
SearchHelper.checkAutoSearchInfo(this,
@@ -77,7 +78,7 @@ class KeeAutofillService : AutofillService() {
{ items ->
val responseBuilder = FillResponse.Builder()
AutofillHelper.addHeader(responseBuilder, packageName,
parseResult.domain, parseResult.applicationId)
parseResult.webDomain, parseResult.applicationId)
items.forEach {
responseBuilder.addDataset(AutofillHelper.buildDataset(this, it, parseResult))
}
@@ -107,9 +108,9 @@ class KeeAutofillService : AutofillService() {
val sender = AutofillLauncherActivity.getAuthIntentSenderForResponse(this,
searchInfo)
val responseBuilder = FillResponse.Builder()
val remoteViewsUnlock: RemoteViews = if (!parseResult.domain.isNullOrEmpty()) {
val remoteViewsUnlock: RemoteViews = if (!parseResult.webDomain.isNullOrEmpty()) {
RemoteViews(packageName, R.layout.item_autofill_unlock_web_domain).apply {
setTextViewText(R.id.autofill_web_domain_text, parseResult.domain)
setTextViewText(R.id.autofill_web_domain_text, parseResult.webDomain)
}
} else if (!parseResult.applicationId.isNullOrEmpty()) {
RemoteViews(packageName, R.layout.item_autofill_unlock_app_id).apply {
@@ -145,38 +146,26 @@ class KeeAutofillService : AutofillService() {
}
}
private fun showUIForEntryRegistration(parseResult: StructureParser.Result,
searchInfo: SearchInfo,
callback: SaveCallback) {
parseResult.passwordValue?.let { autofillPasswordValue ->
AutofillLauncherActivity.launchForRegistration(this, searchInfo)
// TODO Treat sender value to call
// callback.onSuccess() or
// callback.onFailure("Saving form canceled")
}
}
override fun onSaveRequest(request: SaveRequest, callback: SaveCallback) {
val latestStructure = request.fillContexts.last().structure
StructureParser(latestStructure).parse()?.let { parseResult ->
StructureParser(latestStructure).parse(true)?.let { parseResult ->
if (autofillAllowedFor(parseResult.applicationId, applicationIdBlocklist)
&& autofillAllowedFor(parseResult.domain, webDomainBlocklist)) {
&& autofillAllowedFor(parseResult.webDomain, webDomainBlocklist)) {
Log.d(TAG, "autofill onSaveRequest password")
val searchInfo = SearchInfo().apply {
applicationId = parseResult.applicationId
webDomain = parseResult.domain
}
// TODO Save ${autofillPasswordValue.textValue}
// Show UI to save data
showUIForEntryRegistration(parseResult,
searchInfo,
callback)
val registerInfo = RegisterInfo(SearchInfo().apply {
applicationId = parseResult.applicationId
webDomain = parseResult.webDomain
},
parseResult.usernameValue?.textValue?.toString(),
parseResult.passwordValue?.textValue?.toString())
AutofillLauncherActivity.launchForRegistration(this, registerInfo)
// TODO Treat sender value to call
// callback.onSuccess() or
// callback.onFailure("Saving form canceled")
return
}
}

View File

@@ -35,15 +35,19 @@ import java.util.*
@RequiresApi(api = Build.VERSION_CODES.O)
internal class StructureParser(private val structure: AssistStructure) {
private var result: Result? = null
private var usernameCandidate: AutofillId? = null
private var usernameNeeded = true
fun parse(): Result? {
private var usernameCandidate: AutofillId? = null
private var usernameValueCandidate: AutofillValue? = null
fun parse(saveValue: Boolean = false): Result? {
try {
result = Result()
result?.apply {
allowValues = true
allowSaveValues = saveValue
usernameCandidate = null
usernameValueCandidate = null
mainLoop@ for (i in 0 until structure.windowNodeCount) {
val windowNode = structure.getWindowNodeAt(i)
applicationId = windowNode.title.toString().split("/")[0]
@@ -53,8 +57,12 @@ internal class StructureParser(private val structure: AssistStructure) {
break@mainLoop
}
// If not explicit username field found, add the field just before password field.
if (usernameId == null && passwordId != null && usernameCandidate != null)
if (usernameId == null && passwordId != null && usernameCandidate != null) {
usernameId = usernameCandidate
if (allowSaveValues) {
usernameValue = usernameValueCandidate
}
}
}
// Return the result only if password field is retrieved
@@ -72,11 +80,11 @@ internal class StructureParser(private val structure: AssistStructure) {
// Get the domain of a web app
node.webDomain?.let { webDomain ->
if (webDomain.isNotEmpty()) {
result?.domain = webDomain
result?.webDomain = webDomain
Log.d(TAG, "Autofill domain: $webDomain")
}
}
val domainNotEmpty = result?.domain?.isNotEmpty() == true
val domainNotEmpty = result?.webDomain?.isNotEmpty() == true
var returnValue = false
// Only parse visible nodes
@@ -116,6 +124,7 @@ internal class StructureParser(private val structure: AssistStructure) {
|| it.contains("email", true)
|| it.contains(View.AUTOFILL_HINT_PHONE, true)-> {
result?.usernameId = autofillId
result?.usernameValue = node.autofillValue
Log.d(TAG, "Autofill username hint")
}
it.contains(View.AUTOFILL_HINT_PASSWORD, true) -> {
@@ -150,10 +159,12 @@ internal class StructureParser(private val structure: AssistStructure) {
when (pairAttribute.second.toLowerCase(Locale.ENGLISH)) {
"tel", "email" -> {
result?.usernameId = autofillId
result?.usernameValue = node.autofillValue
Log.d(TAG, "Autofill username web type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
}
"text" -> {
usernameCandidate = autofillId
usernameValueCandidate = node.autofillValue
Log.d(TAG, "Autofill username candidate web type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
}
"password" -> {
@@ -193,6 +204,7 @@ internal class StructureParser(private val structure: AssistStructure) {
InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS,
InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS) -> {
result?.usernameId = autofillId
result?.usernameValue = node.autofillValue
Log.d(TAG, "Autofill username android text type: ${showHexInputType(inputType)}")
}
inputIsVariationType(inputType,
@@ -200,6 +212,7 @@ internal class StructureParser(private val structure: AssistStructure) {
InputType.TYPE_TEXT_VARIATION_PERSON_NAME,
InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) -> {
usernameCandidate = autofillId
usernameValueCandidate = node.autofillValue
Log.d(TAG, "Autofill username candidate android text type: ${showHexInputType(inputType)}")
}
inputIsVariationType(inputType,
@@ -232,11 +245,13 @@ internal class StructureParser(private val structure: AssistStructure) {
inputIsVariationType(inputType,
InputType.TYPE_NUMBER_VARIATION_NORMAL) -> {
usernameCandidate = autofillId
usernameValueCandidate = node.autofillValue
Log.d(TAG, "Autofill usernale candidate android number type: ${showHexInputType(inputType)}")
}
inputIsVariationType(inputType,
InputType.TYPE_NUMBER_VARIATION_PASSWORD) -> {
result?.passwordId = autofillId
result?.passwordValue = node.autofillValue
Log.d(TAG, "Autofill password android number type: ${showHexInputType(inputType)}")
usernameNeeded = false
return true
@@ -253,7 +268,8 @@ internal class StructureParser(private val structure: AssistStructure) {
@RequiresApi(api = Build.VERSION_CODES.O)
internal class Result {
var applicationId: String? = null
var domain: String? = null
var webDomain: String? = null
set(value) {
if (field == null)
field = value
@@ -271,14 +287,6 @@ internal class StructureParser(private val structure: AssistStructure) {
field = value
}
var allowValues = false
var passwordValue: AutofillValue? = null
set(value) {
if (allowValues && field == null)
field = value
}
fun allAutofillIds(): Array<AutofillId> {
val all = ArrayList<AutofillId>()
usernameId?.let {
@@ -289,6 +297,21 @@ internal class StructureParser(private val structure: AssistStructure) {
}
return all.toTypedArray()
}
// Only in registration mode
var allowSaveValues = false
var usernameValue: AutofillValue? = null
set(value) {
if (allowSaveValues && field == null)
field = value
}
var passwordValue: AutofillValue? = null
set(value) {
if (allowSaveValues && field == null)
field = value
}
}
companion object {

View File

@@ -0,0 +1,35 @@
package com.kunzisoft.keepass.model
import android.os.Parcel
import android.os.Parcelable
data class RegisterInfo(val searchInfo: SearchInfo,
val username: String?,
val password: String?): Parcelable {
constructor(parcel: Parcel) : this(
parcel.readParcelable(SearchInfo::class.java.classLoader) ?: SearchInfo(),
parcel.readString() ?: "",
parcel.readString() ?: "") {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeParcelable(searchInfo, flags)
parcel.writeString(username)
parcel.writeString(password)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<RegisterInfo> {
override fun createFromParcel(parcel: Parcel): RegisterInfo {
return RegisterInfo(parcel)
}
override fun newArray(size: Int): Array<RegisterInfo?> {
return arrayOfNulls(size)
}
}
}

View File

@@ -29,6 +29,11 @@ class SearchInfo : ObjectNameResource, Parcelable {
constructor()
constructor(toCopy: SearchInfo?) {
applicationId = toCopy?.applicationId
webDomain = toCopy?.webDomain
}
private constructor(parcel: Parcel) {
val readAppId = parcel.readString()
applicationId = if (readAppId.isNullOrEmpty()) null else readAppId