diff --git a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/EntrySelectionHelper.kt b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/EntrySelectionHelper.kt index c5f31f4fb..e929852d4 100644 --- a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/EntrySelectionHelper.kt +++ b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/EntrySelectionHelper.kt @@ -39,9 +39,12 @@ import com.kunzisoft.keepass.model.EntryInfo import com.kunzisoft.keepass.model.RegisterInfo import com.kunzisoft.keepass.model.SearchInfo import com.kunzisoft.keepass.utils.LOCK_ACTION +import com.kunzisoft.keepass.utils.getEnum import com.kunzisoft.keepass.utils.getEnumExtra +import com.kunzisoft.keepass.utils.getParcelableCompat import com.kunzisoft.keepass.utils.getParcelableExtraCompat import com.kunzisoft.keepass.utils.getParcelableList +import com.kunzisoft.keepass.utils.putEnum import com.kunzisoft.keepass.utils.putEnumExtra import com.kunzisoft.keepass.utils.putParcelableList import java.io.IOException @@ -159,10 +162,21 @@ object EntrySelectionHelper { return this } + fun Bundle.addSearchInfo(searchInfo: SearchInfo?): Bundle { + searchInfo?.let { + putParcelable(KEY_SEARCH_INFO, it) + } + return this + } + fun Intent.retrieveSearchInfo(): SearchInfo? { return getParcelableExtraCompat(KEY_SEARCH_INFO) } + fun Bundle.getSearchInfo(): SearchInfo? { + return getParcelableCompat(KEY_SEARCH_INFO) + } + fun Intent.addRegisterInfo(registerInfo: RegisterInfo?): Intent { registerInfo?.let { putExtra(KEY_REGISTER_INFO, it) @@ -170,10 +184,21 @@ object EntrySelectionHelper { return this } + fun Bundle.addRegisterInfo(registerInfo: RegisterInfo?): Bundle { + registerInfo?.let { + putParcelable(KEY_REGISTER_INFO, it) + } + return this + } + fun Intent.retrieveRegisterInfo(): RegisterInfo? { return getParcelableExtraCompat(KEY_REGISTER_INFO) } + fun Bundle.getRegisterInfo(): RegisterInfo? { + return getParcelableCompat(KEY_REGISTER_INFO) + } + fun Intent.removeInfo() { removeExtra(KEY_SEARCH_INFO) removeExtra(KEY_REGISTER_INFO) @@ -184,8 +209,17 @@ object EntrySelectionHelper { return this } + fun Bundle.addSpecialMode(specialMode: SpecialMode): Bundle { + this.putEnum(KEY_SPECIAL_MODE, specialMode) + return this + } + fun Intent.retrieveSpecialMode(): SpecialMode { - return getEnumExtra(KEY_SPECIAL_MODE) ?: SpecialMode.DEFAULT + return this.getEnumExtra(KEY_SPECIAL_MODE) ?: SpecialMode.DEFAULT + } + + fun Bundle.getSpecialMode(): SpecialMode { + return this.getEnum(KEY_SPECIAL_MODE) ?: SpecialMode.DEFAULT } fun Intent.addTypeMode(typeMode: TypeMode): Intent { @@ -236,7 +270,7 @@ object EntrySelectionHelper { } /** - * Retrieve nodes ids from [intent] and get the corresponding entry info list in [database] + * Retrieve nodes ids from intent and get the corresponding entry info list in [database] */ fun Intent.retrieveAndRemoveEntries(database: ContextualDatabase): List { val nodesIds = retrieveNodesIds() diff --git a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/activity/AutofillLauncherActivity.kt b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/activity/AutofillLauncherActivity.kt index aa3c34c04..2e02fbf8f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/activity/AutofillLauncherActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/activity/AutofillLauncherActivity.kt @@ -38,10 +38,14 @@ import com.kunzisoft.keepass.activities.legacy.DatabaseModeActivity import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.addRegisterInfo import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.addSearchInfo import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.addSpecialMode +import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.getRegisterInfo +import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.getSearchInfo +import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.getSpecialMode import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.setActivityResult import com.kunzisoft.keepass.credentialprovider.SpecialMode import com.kunzisoft.keepass.credentialprovider.autofill.AutofillComponent import com.kunzisoft.keepass.credentialprovider.autofill.AutofillHelper.addAutofillComponent +import com.kunzisoft.keepass.credentialprovider.autofill.AutofillHelper.retrieveAutofillComponent import com.kunzisoft.keepass.credentialprovider.viewmodel.AutofillLauncherViewModel import com.kunzisoft.keepass.credentialprovider.viewmodel.CredentialLauncherViewModel import com.kunzisoft.keepass.database.ContextualDatabase @@ -75,6 +79,14 @@ class AutofillLauncherActivity : DatabaseModeActivity() { } override fun onCreate(savedInstanceState: Bundle?) { + // To apply the bypass https://github.com/Kunzisoft/KeePassDX/issues/2238 + // before managing intent in super class + intent.retrieveSelectionBundle()?.apply { + intent.addSpecialMode(getSpecialMode()) + intent.addSearchInfo(getSearchInfo()) + intent.addRegisterInfo(getRegisterInfo()) + intent.addAutofillComponent(retrieveAutofillComponent()) + } super.onCreate(savedInstanceState) autofillLauncherViewModel.initialize() lifecycleScope.launch { @@ -171,23 +183,32 @@ class AutofillLauncherActivity : DatabaseModeActivity() { companion object { + private const val KEY_PENDING_INTENT_BUNDLE = "com.kunzisoft.keepass.extra.BUNDLE" private val TAG = AutofillLauncherActivity::class.java.name + fun Intent.retrieveSelectionBundle(): Bundle? { + return this.getBundleExtra(KEY_PENDING_INTENT_BUNDLE) + } + fun getPendingIntentForSelection( context: Context, searchInfo: SearchInfo? = null, autofillComponent: AutofillComponent ): PendingIntent? { try { + // Doesn't work with direct extra Parcelable in Android 11 (don't know why?) + // https://github.com/Kunzisoft/KeePassDX/issues/2238 + // Wrap into a bundle to bypass the problem + val tempBundle = Bundle().apply { + addSpecialMode(SpecialMode.SELECTION) + addSearchInfo(searchInfo) + addAutofillComponent(autofillComponent) + } return PendingIntent.getActivity( context, randomRequestCode(), - // Doesn't work with direct extra Parcelable (don't know why?) - // Wrap into a bundle to bypass the problem Intent(context, AutofillLauncherActivity::class.java).apply { - addSpecialMode(SpecialMode.SELECTION) - addSearchInfo(searchInfo) - addAutofillComponent(autofillComponent) + putExtra(KEY_PENDING_INTENT_BUNDLE, tempBundle) }, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_CANCEL_CURRENT @@ -206,12 +227,16 @@ class AutofillLauncherActivity : DatabaseModeActivity() { registerInfo: RegisterInfo ): PendingIntent? { try { + // Bypass intent issue + val tempBundle = Bundle().apply { + addSpecialMode(SpecialMode.REGISTRATION) + addRegisterInfo(registerInfo) + } return PendingIntent.getActivity( context, randomRequestCode(), Intent(context, AutofillLauncherActivity::class.java).apply { - addSpecialMode(SpecialMode.REGISTRATION) - addRegisterInfo(registerInfo) + putExtra(KEY_PENDING_INTENT_BUNDLE, tempBundle) }, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_CANCEL_CURRENT diff --git a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/autofill/AutofillHelper.kt b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/autofill/AutofillHelper.kt index 3663db746..6df679543 100644 --- a/app/src/main/java/com/kunzisoft/keepass/credentialprovider/autofill/AutofillHelper.kt +++ b/app/src/main/java/com/kunzisoft/keepass/credentialprovider/autofill/AutofillHelper.kt @@ -27,6 +27,7 @@ import android.content.Intent import android.graphics.BlendMode import android.graphics.drawable.Icon import android.os.Build +import android.os.Bundle import android.service.autofill.Dataset import android.service.autofill.Field import android.service.autofill.FillResponse @@ -53,6 +54,7 @@ import com.kunzisoft.keepass.model.SearchInfo import com.kunzisoft.keepass.settings.AutofillSettingsActivity import com.kunzisoft.keepass.settings.PreferencesUtil import com.kunzisoft.keepass.utils.AppUtil.randomRequestCode +import com.kunzisoft.keepass.utils.getParcelableCompat import com.kunzisoft.keepass.utils.getParcelableExtraCompat import java.io.IOException import kotlin.math.min @@ -64,20 +66,50 @@ object AutofillHelper { private const val EXTRA_BASE_STRUCTURE = "com.kunzisoft.keepass.autofill.BASE_STRUCTURE" private const val EXTRA_INLINE_SUGGESTIONS_REQUEST = "com.kunzisoft.keepass.autofill.INLINE_SUGGESTIONS_REQUEST" - fun Intent.addAutofillComponent(autofillComponent: AutofillComponent) { - this.putExtra(EXTRA_BASE_STRUCTURE, autofillComponent.assistStructure) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - autofillComponent.compatInlineSuggestionsRequest?.let { - this.putExtra(EXTRA_INLINE_SUGGESTIONS_REQUEST, it) + fun Intent.addAutofillComponent(autofillComponent: AutofillComponent?): Intent { + autofillComponent?.let { + this.putExtra(EXTRA_BASE_STRUCTURE, autofillComponent.assistStructure) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + autofillComponent.compatInlineSuggestionsRequest?.let { + this.putExtra(EXTRA_INLINE_SUGGESTIONS_REQUEST, it) + } } } + return this } fun Intent.retrieveAutofillComponent(): AutofillComponent? { - getParcelableExtraCompat(EXTRA_BASE_STRUCTURE)?.let { assistStructure -> + this.getParcelableExtraCompat(EXTRA_BASE_STRUCTURE)?.let { assistStructure -> return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - AutofillComponent(assistStructure, - getParcelableExtraCompat(EXTRA_INLINE_SUGGESTIONS_REQUEST)) + AutofillComponent( + assistStructure, + this.getParcelableExtraCompat(EXTRA_INLINE_SUGGESTIONS_REQUEST)) + } else { + AutofillComponent(assistStructure, null) + } + } + return null + } + + fun Bundle.addAutofillComponent(autofillComponent: AutofillComponent?): Bundle { + autofillComponent?.let { + this.putParcelable(EXTRA_BASE_STRUCTURE, autofillComponent.assistStructure) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + autofillComponent.compatInlineSuggestionsRequest?.let { + this.putParcelable(EXTRA_INLINE_SUGGESTIONS_REQUEST, it) + } + } + } + return this + } + + fun Bundle.retrieveAutofillComponent(): AutofillComponent? { + this.getParcelableCompat(EXTRA_BASE_STRUCTURE)?.let { assistStructure -> + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + AutofillComponent( + assistStructure, + this.getParcelableCompat(EXTRA_INLINE_SUGGESTIONS_REQUEST) + ) } else { AutofillComponent(assistStructure, null) } diff --git a/database/src/main/java/com/kunzisoft/keepass/utils/ParcelableUtil.kt b/database/src/main/java/com/kunzisoft/keepass/utils/ParcelableUtil.kt index 94d3a5e71..6055f21d2 100644 --- a/database/src/main/java/com/kunzisoft/keepass/utils/ParcelableUtil.kt +++ b/database/src/main/java/com/kunzisoft/keepass/utils/ParcelableUtil.kt @@ -82,6 +82,13 @@ inline fun Bundle.getParcelableList(key: String?): Muta else -> @Suppress("DEPRECATION", "UNCHECKED_CAST") (getParcelableArray(key) as? Array)?.toMutableList() } +inline fun > Bundle.putEnum(key: String?, value: T?) = + putString(key, value?.name) + +inline fun > Bundle.getEnum(key: String?): T? { + return getString(key)?.let { enumValueOf(it) } +} + // -------- Parcel -------- inline fun Parcel.readParcelableCompat(): T? = when {