[fenix] For https://github.com/mozilla-mobile/fenix/issues/19693 - Display a biometric prompt when a credit card is selected to autofill (https://github.com/mozilla-mobile/fenix/pull/19697)

Co-authored-by: Arturo Mejia <arturomejiamarmol@gmail.com>
pull/600/head
Gabriel Luong 3 years ago committed by GitHub
parent 67f91bff90
commit c0ce74f75e

@ -4,11 +4,14 @@
package org.mozilla.fenix.browser package org.mozilla.fenix.browser
import android.app.KeyguardManager
import android.content.Context import android.content.Context
import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.content.res.Configuration import android.content.res.Configuration
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.Settings
import android.view.Gravity import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -16,7 +19,9 @@ import android.view.ViewGroup
import android.view.accessibility.AccessibilityManager import android.view.accessibility.AccessibilityManager
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AlertDialog
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.getSystemService
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -65,6 +70,7 @@ import mozilla.components.feature.intent.ext.EXTRA_SESSION_ID
import mozilla.components.feature.media.fullscreen.MediaSessionFullscreenFeature import mozilla.components.feature.media.fullscreen.MediaSessionFullscreenFeature
import mozilla.components.feature.privatemode.feature.SecureWindowFeature import mozilla.components.feature.privatemode.feature.SecureWindowFeature
import mozilla.components.feature.prompts.PromptFeature import mozilla.components.feature.prompts.PromptFeature
import mozilla.components.feature.prompts.PromptFeature.Companion.PIN_REQUEST
import mozilla.components.feature.prompts.share.ShareDelegate import mozilla.components.feature.prompts.share.ShareDelegate
import mozilla.components.feature.readerview.ReaderViewFeature import mozilla.components.feature.readerview.ReaderViewFeature
import mozilla.components.feature.search.SearchFeature import mozilla.components.feature.search.SearchFeature
@ -132,6 +138,8 @@ import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph
import mozilla.components.support.ktx.android.view.enterToImmersiveMode import mozilla.components.support.ktx.android.view.enterToImmersiveMode
import org.mozilla.fenix.GleanMetrics.PerfStartup import org.mozilla.fenix.GleanMetrics.PerfStartup
import org.mozilla.fenix.ext.measureNoInline import org.mozilla.fenix.ext.measureNoInline
import org.mozilla.fenix.ext.secure
import org.mozilla.fenix.settings.biometric.BiometricPromptFeature
import mozilla.components.feature.session.behavior.ToolbarPosition as MozacToolbarPosition import mozilla.components.feature.session.behavior.ToolbarPosition as MozacToolbarPosition
/** /**
@ -180,6 +188,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
ViewBoundFeatureWrapper<MediaSessionFullscreenFeature>() ViewBoundFeatureWrapper<MediaSessionFullscreenFeature>()
private val searchFeature = ViewBoundFeatureWrapper<SearchFeature>() private val searchFeature = ViewBoundFeatureWrapper<SearchFeature>()
private val webAuthnFeature = ViewBoundFeatureWrapper<WebAuthnFeature>() private val webAuthnFeature = ViewBoundFeatureWrapper<WebAuthnFeature>()
private val biometricPromptFeature = ViewBoundFeatureWrapper<BiometricPromptFeature>()
private var pipFeature: PictureInPictureFeature? = null private var pipFeature: PictureInPictureFeature? = null
var customTabSessionId: String? = null var customTabSessionId: String? = null
@ -533,6 +542,21 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
view = view view = view
) )
biometricPromptFeature.set(
feature = BiometricPromptFeature(
context = context,
fragment = this,
onAuthFailure = {
promptsFeature.get()?.onBiometricResult(isAuthenticated = false)
},
onAuthSuccess = {
promptsFeature.get()?.onBiometricResult(isAuthenticated = true)
}
),
owner = this,
view = view
)
promptsFeature.set( promptsFeature.set(
feature = PromptFeature( feature = PromptFeature(
activity = activity, activity = activity,
@ -580,6 +604,9 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
val directions = val directions =
NavGraphDirections.actionGlobalCreditCardsSettingFragment() NavGraphDirections.actionGlobalCreditCardsSettingFragment()
findNavController().navigateBlockingForAsyncNavGraph(directions) findNavController().navigateBlockingForAsyncNavGraph(directions)
},
onSelectCreditCard = {
showBiometricPrompt(context)
} }
), ),
owner = this, owner = this,
@ -731,6 +758,66 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
initializeEngineView(toolbarHeight) initializeEngineView(toolbarHeight)
} }
/**
* Shows a biometric prompt and fallback to prompting for the password.
*/
private fun showBiometricPrompt(context: Context) {
if (BiometricPromptFeature.canUseFeature(context)) {
biometricPromptFeature.get()
?.requestAuthentication(getString(R.string.credit_cards_biometric_prompt_unlock_message))
return
}
// Fallback to prompting for password with the KeyguardManager
val manager = context.getSystemService<KeyguardManager>()
if (manager?.isKeyguardSecure == true) {
showPinVerification(manager)
} else {
// Warn that the device has not been secured
if (context.settings().shouldShowSecurityPinWarning) {
showPinDialogWarning(context)
} else {
promptsFeature.get()?.onBiometricResult(isAuthenticated = true)
}
}
}
/**
* Shows a pin request prompt. This is only used when BiometricPrompt is unavailable.
*/
@Suppress("Deprecation")
private fun showPinVerification(manager: KeyguardManager) {
val intent = manager.createConfirmDeviceCredentialIntent(
getString(R.string.credit_cards_biometric_prompt_message_pin),
getString(R.string.credit_cards_biometric_prompt_unlock_message)
)
requireActivity().startActivityForResult(intent, PIN_REQUEST)
}
/**
* Shows a dialog warning about setting up a device lock PIN.
*/
private fun showPinDialogWarning(context: Context) {
AlertDialog.Builder(context).apply {
setTitle(getString(R.string.credit_cards_warning_dialog_title))
setMessage(getString(R.string.credit_cards_warning_dialog_message))
setNegativeButton(getString(R.string.credit_cards_warning_dialog_later)) { _: DialogInterface, _ ->
promptsFeature.get()?.onBiometricResult(isAuthenticated = false)
}
setPositiveButton(getString(R.string.credit_cards_warning_dialog_set_up_now)) { it: DialogInterface, _ ->
it.dismiss()
promptsFeature.get()?.onBiometricResult(isAuthenticated = false)
startActivity(Intent(Settings.ACTION_SECURITY_SETTINGS))
}
create()
}.show().secure(activity)
context.settings().incrementSecureWarningCount()
}
@VisibleForTesting @VisibleForTesting
internal fun expandToolbarOnNavigation(store: BrowserStore) { internal fun expandToolbarOnNavigation(store: BrowserStore) {
consumeFlow(store) { flow -> consumeFlow(store) { flow ->

@ -3,5 +3,5 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
object AndroidComponents { object AndroidComponents {
const val VERSION = "90.0.20210528002854" const val VERSION = "90.0.20210528204811"
} }

Loading…
Cancel
Save