diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/AutofillLauncherActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/AutofillLauncherActivity.kt index b14e715c8..26a38935d 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/AutofillLauncherActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/AutofillLauncherActivity.kt @@ -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(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) } diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt index 491cf7e40..e122f663f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt @@ -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) } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt index f3141d70d..6da4e5cf9 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/FileDatabaseSelectActivity.kt @@ -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) } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index a85ab6533..382369ac5 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -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) } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt index b6a8c0dd2..9a4cdc361 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/PasswordActivity.kt @@ -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) } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/helpers/EntrySelectionHelper.kt b/app/src/main/java/com/kunzisoft/keepass/activities/helpers/EntrySelectionHelper.kt index 9b1c1ab7a..8b173041b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/helpers/EntrySelectionHelper.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/helpers/EntrySelectionHelper.kt @@ -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) } } } diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/selection/SpecialModeActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/selection/SpecialModeActivity.kt index e2875ecf2..8344201e6 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/selection/SpecialModeActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/selection/SpecialModeActivity.kt @@ -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) diff --git a/app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.kt b/app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.kt index d3f02beda..2ac6f307c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.kt @@ -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 } } diff --git a/app/src/main/java/com/kunzisoft/keepass/autofill/StructureParser.kt b/app/src/main/java/com/kunzisoft/keepass/autofill/StructureParser.kt index c3daed267..b9d1d9c9a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/autofill/StructureParser.kt +++ b/app/src/main/java/com/kunzisoft/keepass/autofill/StructureParser.kt @@ -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 { val all = ArrayList() 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 { diff --git a/app/src/main/java/com/kunzisoft/keepass/model/RegisterInfo.kt b/app/src/main/java/com/kunzisoft/keepass/model/RegisterInfo.kt new file mode 100644 index 000000000..496097e2d --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/model/RegisterInfo.kt @@ -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 { + override fun createFromParcel(parcel: Parcel): RegisterInfo { + return RegisterInfo(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/model/SearchInfo.kt b/app/src/main/java/com/kunzisoft/keepass/model/SearchInfo.kt index c9adeef5e..78582367e 100644 --- a/app/src/main/java/com/kunzisoft/keepass/model/SearchInfo.kt +++ b/app/src/main/java/com/kunzisoft/keepass/model/SearchInfo.kt @@ -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