1
0
Fork 0

For #12312 - Disable settings that navigate while authenticating

master
ekager 2020-07-07 15:58:11 -04:00 committed by Emily Kager
parent 3e617245b5
commit bceb07a05b
1 changed files with 40 additions and 13 deletions

View File

@ -17,6 +17,7 @@ import android.util.Log
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.biometric.BiometricManager import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.preference.Preference import androidx.preference.Preference
@ -31,6 +32,7 @@ import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.service.fxa.SyncEngine import mozilla.components.service.fxa.SyncEngine
import mozilla.components.service.fxa.manager.SyncEnginesStorage import mozilla.components.service.fxa.manager.SyncEnginesStorage
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.addons.runIfFragmentIsAttached
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
@ -39,7 +41,7 @@ import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.settings.SharedPreferenceUpdater import org.mozilla.fenix.settings.SharedPreferenceUpdater
import org.mozilla.fenix.settings.requirePreference import org.mozilla.fenix.settings.requirePreference
import java.util.concurrent.Executors import java.util.concurrent.Executor
@Suppress("TooManyFunctions", "LargeClass") @Suppress("TooManyFunctions", "LargeClass")
class SavedLoginsAuthFragment : PreferenceFragmentCompat(), AccountObserver { class SavedLoginsAuthFragment : PreferenceFragmentCompat(), AccountObserver {
@ -48,7 +50,7 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat(), AccountObserver {
private lateinit var biometricPromptCallback: BiometricPrompt.AuthenticationCallback private lateinit var biometricPromptCallback: BiometricPrompt.AuthenticationCallback
@TargetApi(M) @TargetApi(M)
private val executor = Executors.newSingleThreadExecutor() private lateinit var executor: Executor
@TargetApi(M) @TargetApi(M)
private lateinit var biometricPrompt: BiometricPrompt private lateinit var biometricPrompt: BiometricPrompt
@ -60,6 +62,28 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat(), AccountObserver {
setPreferencesFromResource(R.xml.logins_preferences, rootKey) setPreferencesFromResource(R.xml.logins_preferences, rootKey)
} }
/**
* There is a bug where while the biometric prompt is showing, you were able to quickly navigate
* so we are disabling the settings that navigate while authenticating.
* https://github.com/mozilla-mobile/fenix/issues/12312
*/
private fun togglePrefsEnabledWhileAuthenticating(enabled: Boolean) {
requirePreference<Preference>(R.string.pref_key_password_sync_logins).isEnabled = enabled
requirePreference<Preference>(R.string.pref_key_save_logins_settings).isEnabled = enabled
requirePreference<Preference>(R.string.pref_key_saved_logins).isEnabled = enabled
}
private fun navigateToSavedLogins() {
runIfFragmentIsAttached {
viewLifecycleOwner.lifecycleScope.launch(Main) {
// Workaround for likely biometric library bug
// https://github.com/mozilla-mobile/fenix/issues/8438
delay(SHORT_DELAY_MS)
navigateToSavedLoginsFragment()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -67,23 +91,22 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat(), AccountObserver {
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
Log.e(LOG_TAG, "onAuthenticationError $errString") Log.e(LOG_TAG, "onAuthenticationError $errString")
togglePrefsEnabledWhileAuthenticating(enabled = true)
} }
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
Log.d(LOG_TAG, "onAuthenticationSucceeded") Log.d(LOG_TAG, "onAuthenticationSucceeded")
viewLifecycleOwner.lifecycleScope.launch(Main) { navigateToSavedLogins()
// Workaround for likely biometric library bug
// https://github.com/mozilla-mobile/fenix/issues/8438
delay(SHORT_DELAY_MS)
navigateToSavedLoginsFragment()
}
} }
override fun onAuthenticationFailed() { override fun onAuthenticationFailed() {
Log.e(LOG_TAG, "onAuthenticationFailed") Log.e(LOG_TAG, "onAuthenticationFailed")
togglePrefsEnabledWhileAuthenticating(enabled = true)
} }
} }
executor = ContextCompat.getMainExecutor(requireContext())
biometricPrompt = BiometricPrompt(this, executor, biometricPromptCallback) biometricPrompt = BiometricPrompt(this, executor, biometricPromptCallback)
promptInfo = BiometricPrompt.PromptInfo.Builder() promptInfo = BiometricPrompt.PromptInfo.Builder()
@ -122,6 +145,7 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat(), AccountObserver {
requirePreference<Preference>(R.string.pref_key_saved_logins).setOnPreferenceClickListener { requirePreference<Preference>(R.string.pref_key_saved_logins).setOnPreferenceClickListener {
if (Build.VERSION.SDK_INT >= M && isHardwareAvailable && hasBiometricEnrolled) { if (Build.VERSION.SDK_INT >= M && isHardwareAvailable && hasBiometricEnrolled) {
togglePrefsEnabledWhileAuthenticating(enabled = false)
biometricPrompt.authenticate(promptInfo) biometricPrompt.authenticate(promptInfo)
} else { } else {
verifyPinOrShowSetupWarning() verifyPinOrShowSetupWarning()
@ -148,7 +172,7 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat(), AccountObserver {
override fun onAuthenticationProblems() = updateSyncPreferenceNeedsReauth() override fun onAuthenticationProblems() = updateSyncPreferenceNeedsReauth()
val isHardwareAvailable: Boolean by lazy { private val isHardwareAvailable: Boolean by lazy {
if (Build.VERSION.SDK_INT >= M) { if (Build.VERSION.SDK_INT >= M) {
context?.let { context?.let {
val bm = BiometricManager.from(it) val bm = BiometricManager.from(it)
@ -161,7 +185,7 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat(), AccountObserver {
} }
} }
val hasBiometricEnrolled: Boolean by lazy { private val hasBiometricEnrolled: Boolean by lazy {
if (Build.VERSION.SDK_INT >= M) { if (Build.VERSION.SDK_INT >= M) {
context?.let { context?.let {
val bm = BiometricManager.from(it) val bm = BiometricManager.from(it)
@ -252,7 +276,8 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat(), AccountObserver {
getString(R.string.logins_biometric_prompt_message_pin), getString(R.string.logins_biometric_prompt_message_pin),
getString(R.string.logins_biometric_prompt_message) getString(R.string.logins_biometric_prompt_message)
) )
startActivityForResult(intent, startActivityForResult(
intent,
PIN_REQUEST PIN_REQUEST
) )
} }
@ -267,7 +292,8 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat(), AccountObserver {
private fun navigateToSavedLoginsFragment() { private fun navigateToSavedLoginsFragment() {
context?.components?.analytics?.metrics?.track(Event.OpenLogins) context?.components?.analytics?.metrics?.track(Event.OpenLogins)
val directions = SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToLoginsListFragment() val directions =
SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToLoginsListFragment()
findNavController().navigate(directions) findNavController().navigate(directions)
} }
@ -283,7 +309,8 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat(), AccountObserver {
} }
private fun navigateToTurnOnSyncFragment() { private fun navigateToTurnOnSyncFragment() {
val directions = SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToTurnOnSyncFragment() val directions =
SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToTurnOnSyncFragment()
findNavController().navigate(directions) findNavController().navigate(directions)
} }