Skip to content

Commit

Permalink
For mozilla-mobile#11892 - Pass ParsedStructure as bytearray instead …
Browse files Browse the repository at this point in the history
…of as parcelable

This avoids the system trying to remap our ParsedStructure parcelable failing
by not using the right ClassLoader.

Implementing Parcelable on our own was needed to be able to manually create
`ParsedStructure` from the unmarshalled parcel.
  • Loading branch information
Mugurell committed Mar 23, 2022
1 parent 951fb39 commit 864b50f
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 15 deletions.
Expand Up @@ -11,6 +11,7 @@ import android.content.Intent
import android.content.IntentSender
import android.graphics.drawable.Icon
import android.os.Build
import android.os.Parcel
import android.service.autofill.FillResponse
import android.service.autofill.InlinePresentation
import android.view.autofill.AutofillId
Expand Down Expand Up @@ -52,10 +53,21 @@ internal data class AuthFillResponseBuilder(
}

val authIntent = Intent(context, configuration.unlockActivity)
authIntent.putExtra(
AbstractAutofillUnlockActivity.EXTRA_PARSED_STRUCTURE,
parsedStructure
)

// Pass `ParsedStructure` as raw bytes to prevent the system throwing a ClassNotFoundException
// when updating the PendingIntent and trying to create and remap `ParsedStructure`
// from the parcelable extra because of an unknown ClassLoader.
with(Parcel.obtain()) {
parsedStructure.writeToParcel(this, 0)

authIntent.putExtra(
AbstractAutofillUnlockActivity.EXTRA_PARSED_STRUCTURE,
this.marshall()
)

recycle()
}

authIntent.putExtra(AbstractAutofillUnlockActivity.EXTRA_IME_SPEC, imeSpec)
authIntent.putExtra(
AbstractAutofillUnlockActivity.EXTRA_MAX_SUGGESTION_COUNT,
Expand Down
Expand Up @@ -6,10 +6,11 @@ package mozilla.components.feature.autofill.structure

import android.content.Context
import android.os.Build
import android.os.Parcel
import android.os.Parcelable
import android.os.Parcelable.Creator
import android.view.autofill.AutofillId
import androidx.annotation.RequiresApi
import kotlinx.parcelize.Parcelize
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
import mozilla.components.support.utils.Browsers

Expand All @@ -20,13 +21,43 @@ import mozilla.components.support.utils.Browsers
* https://github.com/mozilla-lockwise/lockwise-android/blob/d3c0511f73c34e8759e1bb597f2d3dc9bcc146f0/app/src/main/java/mozilla/lockbox/autofill/ParsedStructure.kt#L52
*/
@RequiresApi(Build.VERSION_CODES.O)
@Parcelize
internal data class ParsedStructure(
data class ParsedStructure(
val usernameId: AutofillId? = null,
val passwordId: AutofillId? = null,
val webDomain: String? = null,
val packageName: String
) : Parcelable
) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readParcelable(AutofillId::class.java.classLoader),
parcel.readParcelable(AutofillId::class.java.classLoader),
parcel.readString(),
parcel.readString() ?: ""
)

override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeParcelable(usernameId, flags)
parcel.writeParcelable(passwordId, flags)
parcel.writeString(webDomain)
parcel.writeString(packageName)
}

override fun describeContents(): Int {
return 0
}

/**
* Create instances of [ParsedStructure] from a [Parcel].
*/
companion object CREATOR : Creator<ParsedStructure> {
override fun createFromParcel(parcel: Parcel): ParsedStructure {
return ParsedStructure(parcel)
}

override fun newArray(size: Int): Array<ParsedStructure?> {
return arrayOfNulls(size)
}
}
}

/**
* Try to find a domain in the [ParsedStructure] for looking up logins. This is either a "web domain"
Expand Down
Expand Up @@ -7,6 +7,7 @@ package mozilla.components.feature.autofill.ui
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Parcel
import android.service.autofill.FillResponse
import android.view.autofill.AutofillManager
import android.widget.inline.InlinePresentationSpec
Expand Down Expand Up @@ -40,16 +41,21 @@ abstract class AbstractAutofillUnlockActivity : FragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val parsedStructure = intent.getParcelableExtra<ParsedStructure>(EXTRA_PARSED_STRUCTURE)
val parsedStructure = with(Parcel.obtain()) {
val rawBytes = intent.getByteArrayExtra(EXTRA_PARSED_STRUCTURE)
unmarshall(rawBytes!!, 0, rawBytes.size)
setDataPosition(0)
ParsedStructure(this).also {
recycle()
}
}
val imeSpec = intent.getImeSpec()
val maxSuggestionCount = intent.getIntExtra(EXTRA_MAX_SUGGESTION_COUNT, MAX_LOGINS)
// While the user is asked to authenticate, we already try to build the fill response asynchronously.
if (parsedStructure != null) {
fillResponse = lifecycleScope.async(Dispatchers.IO) {
val builder = fillHandler.handle(parsedStructure, forceUnlock = true, maxSuggestionCount)
val result = builder.build(this@AbstractAutofillUnlockActivity, configuration, imeSpec)
result
}
fillResponse = lifecycleScope.async(Dispatchers.IO) {
val builder = fillHandler.handle(parsedStructure, forceUnlock = true, maxSuggestionCount)
val result = builder.build(this@AbstractAutofillUnlockActivity, configuration, imeSpec)
result
}

if (authenticator == null) {
Expand Down
3 changes: 3 additions & 0 deletions docs/changelog.md
Expand Up @@ -11,6 +11,9 @@ permalink: /changelog/
* [Gecko](https://github.com/mozilla-mobile/android-components/blob/main/buildSrc/src/main/java/Gecko.kt)
* [Configuration](https://github.com/mozilla-mobile/android-components/blob/main/.config.yml)

* **feature-autofill**
* 🚒 Bug fixed [issue #11893](https://github.com/mozilla-mobile/android-components/issues/11893) - Fix issue with autofilling in 3rd party applications not being immediately available after unlocking the autofill service.

* **feature-autofill**
* 🚒 Bug fixed [issue #11869](https://github.com/mozilla-mobile/android-components/issues/11869) - Fix regression causing autofill to not work after unlocking the app doing the autofill or after accepting that the authenticity of the autofill target could not be verified.

Expand Down

0 comments on commit 864b50f

Please sign in to comment.