mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
fix: Autofill pending intent bypass #2238
This commit is contained in:
@@ -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<SpecialMode>(KEY_SPECIAL_MODE) ?: SpecialMode.DEFAULT
|
||||
return this.getEnumExtra<SpecialMode>(KEY_SPECIAL_MODE) ?: SpecialMode.DEFAULT
|
||||
}
|
||||
|
||||
fun Bundle.getSpecialMode(): SpecialMode {
|
||||
return this.getEnum<SpecialMode>(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<EntryInfo> {
|
||||
val nodesIds = retrieveNodesIds()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<AssistStructure>(EXTRA_BASE_STRUCTURE)?.let { assistStructure ->
|
||||
this.getParcelableExtraCompat<AssistStructure>(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<AssistStructure>(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)
|
||||
}
|
||||
|
||||
@@ -82,6 +82,13 @@ inline fun <reified E : Parcelable> Bundle.getParcelableList(key: String?): Muta
|
||||
else -> @Suppress("DEPRECATION", "UNCHECKED_CAST") (getParcelableArray(key) as? Array<E>)?.toMutableList()
|
||||
}
|
||||
|
||||
inline fun <reified T : Enum<T>> Bundle.putEnum(key: String?, value: T?) =
|
||||
putString(key, value?.name)
|
||||
|
||||
inline fun <reified T : Enum<T>> Bundle.getEnum(key: String?): T? {
|
||||
return getString(key)?.let { enumValueOf<T>(it) }
|
||||
}
|
||||
|
||||
// -------- Parcel --------
|
||||
|
||||
inline fun <reified T : Parcelable> Parcel.readParcelableCompat(): T? = when {
|
||||
|
||||
Reference in New Issue
Block a user