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.RegisterInfo
|
||||||
import com.kunzisoft.keepass.model.SearchInfo
|
import com.kunzisoft.keepass.model.SearchInfo
|
||||||
import com.kunzisoft.keepass.utils.LOCK_ACTION
|
import com.kunzisoft.keepass.utils.LOCK_ACTION
|
||||||
|
import com.kunzisoft.keepass.utils.getEnum
|
||||||
import com.kunzisoft.keepass.utils.getEnumExtra
|
import com.kunzisoft.keepass.utils.getEnumExtra
|
||||||
|
import com.kunzisoft.keepass.utils.getParcelableCompat
|
||||||
import com.kunzisoft.keepass.utils.getParcelableExtraCompat
|
import com.kunzisoft.keepass.utils.getParcelableExtraCompat
|
||||||
import com.kunzisoft.keepass.utils.getParcelableList
|
import com.kunzisoft.keepass.utils.getParcelableList
|
||||||
|
import com.kunzisoft.keepass.utils.putEnum
|
||||||
import com.kunzisoft.keepass.utils.putEnumExtra
|
import com.kunzisoft.keepass.utils.putEnumExtra
|
||||||
import com.kunzisoft.keepass.utils.putParcelableList
|
import com.kunzisoft.keepass.utils.putParcelableList
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@@ -159,10 +162,21 @@ object EntrySelectionHelper {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Bundle.addSearchInfo(searchInfo: SearchInfo?): Bundle {
|
||||||
|
searchInfo?.let {
|
||||||
|
putParcelable(KEY_SEARCH_INFO, it)
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
fun Intent.retrieveSearchInfo(): SearchInfo? {
|
fun Intent.retrieveSearchInfo(): SearchInfo? {
|
||||||
return getParcelableExtraCompat(KEY_SEARCH_INFO)
|
return getParcelableExtraCompat(KEY_SEARCH_INFO)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Bundle.getSearchInfo(): SearchInfo? {
|
||||||
|
return getParcelableCompat(KEY_SEARCH_INFO)
|
||||||
|
}
|
||||||
|
|
||||||
fun Intent.addRegisterInfo(registerInfo: RegisterInfo?): Intent {
|
fun Intent.addRegisterInfo(registerInfo: RegisterInfo?): Intent {
|
||||||
registerInfo?.let {
|
registerInfo?.let {
|
||||||
putExtra(KEY_REGISTER_INFO, it)
|
putExtra(KEY_REGISTER_INFO, it)
|
||||||
@@ -170,10 +184,21 @@ object EntrySelectionHelper {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Bundle.addRegisterInfo(registerInfo: RegisterInfo?): Bundle {
|
||||||
|
registerInfo?.let {
|
||||||
|
putParcelable(KEY_REGISTER_INFO, it)
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
fun Intent.retrieveRegisterInfo(): RegisterInfo? {
|
fun Intent.retrieveRegisterInfo(): RegisterInfo? {
|
||||||
return getParcelableExtraCompat(KEY_REGISTER_INFO)
|
return getParcelableExtraCompat(KEY_REGISTER_INFO)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Bundle.getRegisterInfo(): RegisterInfo? {
|
||||||
|
return getParcelableCompat(KEY_REGISTER_INFO)
|
||||||
|
}
|
||||||
|
|
||||||
fun Intent.removeInfo() {
|
fun Intent.removeInfo() {
|
||||||
removeExtra(KEY_SEARCH_INFO)
|
removeExtra(KEY_SEARCH_INFO)
|
||||||
removeExtra(KEY_REGISTER_INFO)
|
removeExtra(KEY_REGISTER_INFO)
|
||||||
@@ -184,8 +209,17 @@ object EntrySelectionHelper {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Bundle.addSpecialMode(specialMode: SpecialMode): Bundle {
|
||||||
|
this.putEnum(KEY_SPECIAL_MODE, specialMode)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
fun Intent.retrieveSpecialMode(): SpecialMode {
|
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 {
|
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> {
|
fun Intent.retrieveAndRemoveEntries(database: ContextualDatabase): List<EntryInfo> {
|
||||||
val nodesIds = retrieveNodesIds()
|
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.addRegisterInfo
|
||||||
import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.addSearchInfo
|
import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.addSearchInfo
|
||||||
import com.kunzisoft.keepass.credentialprovider.EntrySelectionHelper.addSpecialMode
|
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.EntrySelectionHelper.setActivityResult
|
||||||
import com.kunzisoft.keepass.credentialprovider.SpecialMode
|
import com.kunzisoft.keepass.credentialprovider.SpecialMode
|
||||||
import com.kunzisoft.keepass.credentialprovider.autofill.AutofillComponent
|
import com.kunzisoft.keepass.credentialprovider.autofill.AutofillComponent
|
||||||
import com.kunzisoft.keepass.credentialprovider.autofill.AutofillHelper.addAutofillComponent
|
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.AutofillLauncherViewModel
|
||||||
import com.kunzisoft.keepass.credentialprovider.viewmodel.CredentialLauncherViewModel
|
import com.kunzisoft.keepass.credentialprovider.viewmodel.CredentialLauncherViewModel
|
||||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||||
@@ -75,6 +79,14 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
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)
|
super.onCreate(savedInstanceState)
|
||||||
autofillLauncherViewModel.initialize()
|
autofillLauncherViewModel.initialize()
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
@@ -171,23 +183,32 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
private const val KEY_PENDING_INTENT_BUNDLE = "com.kunzisoft.keepass.extra.BUNDLE"
|
||||||
private val TAG = AutofillLauncherActivity::class.java.name
|
private val TAG = AutofillLauncherActivity::class.java.name
|
||||||
|
|
||||||
|
fun Intent.retrieveSelectionBundle(): Bundle? {
|
||||||
|
return this.getBundleExtra(KEY_PENDING_INTENT_BUNDLE)
|
||||||
|
}
|
||||||
|
|
||||||
fun getPendingIntentForSelection(
|
fun getPendingIntentForSelection(
|
||||||
context: Context,
|
context: Context,
|
||||||
searchInfo: SearchInfo? = null,
|
searchInfo: SearchInfo? = null,
|
||||||
autofillComponent: AutofillComponent
|
autofillComponent: AutofillComponent
|
||||||
): PendingIntent? {
|
): PendingIntent? {
|
||||||
try {
|
try {
|
||||||
return PendingIntent.getActivity(
|
// Doesn't work with direct extra Parcelable in Android 11 (don't know why?)
|
||||||
context,
|
// https://github.com/Kunzisoft/KeePassDX/issues/2238
|
||||||
randomRequestCode(),
|
|
||||||
// Doesn't work with direct extra Parcelable (don't know why?)
|
|
||||||
// Wrap into a bundle to bypass the problem
|
// Wrap into a bundle to bypass the problem
|
||||||
Intent(context, AutofillLauncherActivity::class.java).apply {
|
val tempBundle = Bundle().apply {
|
||||||
addSpecialMode(SpecialMode.SELECTION)
|
addSpecialMode(SpecialMode.SELECTION)
|
||||||
addSearchInfo(searchInfo)
|
addSearchInfo(searchInfo)
|
||||||
addAutofillComponent(autofillComponent)
|
addAutofillComponent(autofillComponent)
|
||||||
|
}
|
||||||
|
return PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
randomRequestCode(),
|
||||||
|
Intent(context, AutofillLauncherActivity::class.java).apply {
|
||||||
|
putExtra(KEY_PENDING_INTENT_BUNDLE, tempBundle)
|
||||||
},
|
},
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
|
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
|
||||||
@@ -206,12 +227,16 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
|
|||||||
registerInfo: RegisterInfo
|
registerInfo: RegisterInfo
|
||||||
): PendingIntent? {
|
): PendingIntent? {
|
||||||
try {
|
try {
|
||||||
|
// Bypass intent issue
|
||||||
|
val tempBundle = Bundle().apply {
|
||||||
|
addSpecialMode(SpecialMode.REGISTRATION)
|
||||||
|
addRegisterInfo(registerInfo)
|
||||||
|
}
|
||||||
return PendingIntent.getActivity(
|
return PendingIntent.getActivity(
|
||||||
context,
|
context,
|
||||||
randomRequestCode(),
|
randomRequestCode(),
|
||||||
Intent(context, AutofillLauncherActivity::class.java).apply {
|
Intent(context, AutofillLauncherActivity::class.java).apply {
|
||||||
addSpecialMode(SpecialMode.REGISTRATION)
|
putExtra(KEY_PENDING_INTENT_BUNDLE, tempBundle)
|
||||||
addRegisterInfo(registerInfo)
|
|
||||||
},
|
},
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
|
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import android.content.Intent
|
|||||||
import android.graphics.BlendMode
|
import android.graphics.BlendMode
|
||||||
import android.graphics.drawable.Icon
|
import android.graphics.drawable.Icon
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
import android.service.autofill.Dataset
|
import android.service.autofill.Dataset
|
||||||
import android.service.autofill.Field
|
import android.service.autofill.Field
|
||||||
import android.service.autofill.FillResponse
|
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.AutofillSettingsActivity
|
||||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
import com.kunzisoft.keepass.utils.AppUtil.randomRequestCode
|
import com.kunzisoft.keepass.utils.AppUtil.randomRequestCode
|
||||||
|
import com.kunzisoft.keepass.utils.getParcelableCompat
|
||||||
import com.kunzisoft.keepass.utils.getParcelableExtraCompat
|
import com.kunzisoft.keepass.utils.getParcelableExtraCompat
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
@@ -64,7 +66,8 @@ object AutofillHelper {
|
|||||||
private const val EXTRA_BASE_STRUCTURE = "com.kunzisoft.keepass.autofill.BASE_STRUCTURE"
|
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"
|
private const val EXTRA_INLINE_SUGGESTIONS_REQUEST = "com.kunzisoft.keepass.autofill.INLINE_SUGGESTIONS_REQUEST"
|
||||||
|
|
||||||
fun Intent.addAutofillComponent(autofillComponent: AutofillComponent) {
|
fun Intent.addAutofillComponent(autofillComponent: AutofillComponent?): Intent {
|
||||||
|
autofillComponent?.let {
|
||||||
this.putExtra(EXTRA_BASE_STRUCTURE, autofillComponent.assistStructure)
|
this.putExtra(EXTRA_BASE_STRUCTURE, autofillComponent.assistStructure)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
autofillComponent.compatInlineSuggestionsRequest?.let {
|
autofillComponent.compatInlineSuggestionsRequest?.let {
|
||||||
@@ -72,12 +75,41 @@ object AutofillHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
fun Intent.retrieveAutofillComponent(): AutofillComponent? {
|
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) {
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
AutofillComponent(assistStructure,
|
AutofillComponent(
|
||||||
getParcelableExtraCompat(EXTRA_INLINE_SUGGESTIONS_REQUEST))
|
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 {
|
} else {
|
||||||
AutofillComponent(assistStructure, null)
|
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()
|
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 --------
|
// -------- Parcel --------
|
||||||
|
|
||||||
inline fun <reified T : Parcelable> Parcel.readParcelableCompat(): T? = when {
|
inline fun <reified T : Parcelable> Parcel.readParcelableCompat(): T? = when {
|
||||||
|
|||||||
Reference in New Issue
Block a user