Loading mobile/android/fenix/app/src/beta/res/drawable/tor_browser_app_icon.png 0 → 100644 +7.26 KiB Loading image diff... mobile/android/fenix/app/src/main/java/org/mozilla/fenix/biometricauthentication/UnlockPrivateTabsFragment.kt +4 −4 Original line number Diff line number Diff line Loading @@ -56,8 +56,7 @@ class UnlockPrivateTabsFragment : Fragment(), UserInteractionHandler { UnlockPrivateTabsScreen( onUnlockClicked = { requestPrompt() }, onLeaveClicked = { PrivateBrowsingLocked.seeOtherTabsClicked.record() closeFragment() requireActivity().moveTaskToBack(true) }, ) Loading @@ -67,13 +66,14 @@ class UnlockPrivateTabsFragment : Fragment(), UserInteractionHandler { } override fun onBackPressed(): Boolean { closeFragment() requireActivity().moveTaskToBack(true) return true } private fun requestPrompt() { DefaultBiometricUtils.bindBiometricsCredentialsPromptOrShowWarning( titleRes = R.string.pbm_authentication_unlock_private_tabs, titleRes = R.string.tor_authentication_unlock_private_tabs, titleRes2 = R.string.app_name, view = requireView(), onShowPinVerification = { intent -> startForResult.launch(intent) }, onAuthSuccess = ::onAuthSuccess, Loading mobile/android/fenix/app/src/main/java/org/mozilla/fenix/biometricauthentication/UnlockPrivateTabsScreen.kt +28 −15 Original line number Diff line number Diff line Loading @@ -31,6 +31,14 @@ import org.mozilla.fenix.ext.isLargeWindow import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.Theme import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.size import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp import org.mozilla.fenix.compose.parseHtml private const val FILL_WIDTH_LARGE_WINDOW = 0.5f private const val FILL_WIDTH_DEFAULT = 1.0f Loading Loading @@ -71,17 +79,31 @@ private fun Header() { Column( modifier = Modifier.padding(horizontal = 16.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { Row ( verticalAlignment = Alignment.CenterVertically ) { Image( painter = painterResource(id = R.drawable.ic_pbm_firefox_logo), painter = painterResource(id = R.drawable.tor_browser_app_icon), contentDescription = null, // decorative only. modifier = Modifier.padding(32.dp), Modifier .size(62.dp) .padding(end = 10.dp), ) Text( text = stringResource(R.string.app_name), color = FirefoxTheme.colors.textPrimary, fontWeight = FontWeight.Bold, fontSize = 29.sp, letterSpacing = 0.18.sp, lineHeight = 52.sp, ) } Spacer(modifier = Modifier.height(24.dp)) Text( text = stringResource(id = R.string.pbm_authentication_unlock_private_tabs), text = stringResource(id = R.string.tor_authentication_unlock_private_tabs, stringResource(R.string.app_name)), color = FirefoxTheme.colors.textPrimary, textAlign = TextAlign.Center, style = FirefoxTheme.typography.headline6, Loading Loading @@ -109,15 +131,6 @@ private fun Footer(onUnlockClicked: () -> Unit, onLeaveClicked: () -> Unit) { modifier = Modifier.fillMaxWidth(), onClick = onUnlockClicked, ) Spacer(modifier = Modifier.height(8.dp)) TextButton( text = stringResource(R.string.pbm_authentication_leave_private_tabs), onClick = onLeaveClicked, textColor = FirefoxTheme.colors.textActionPrimary, upperCaseText = false, ) } } Loading mobile/android/fenix/app/src/main/java/org/mozilla/fenix/lifecycle/PrivateBrowsingLockFeature.kt +2 −1 Original line number Diff line number Diff line Loading @@ -312,7 +312,8 @@ fun Fragment.verifyUser( onVerified: (() -> Unit)? = null, ) { biometricUtils.bindBiometricsCredentialsPromptOrShowWarning( titleRes = R.string.pbm_authentication_unlock_private_tabs, titleRes = R.string.tor_authentication_unlock_private_tabs, titleRes2 = R.string.app_name, view = requireView(), onShowPinVerification = { intent -> fallbackVerification.launch(intent) }, onAuthSuccess = { handleVerificationSuccess(requireContext(), onVerified) }, Loading mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TabsSettingsFragment.kt +96 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,16 @@ import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.utils.view.addToRadioGroup import android.content.Intent import android.provider.Settings import androidx.activity.result.ActivityResultLauncher import androidx.biometric.BiometricManager import androidx.preference.Preference import org.mozilla.fenix.ext.registerForActivityResult import org.mozilla.fenix.settings.biometric.DefaultBiometricUtils import org.mozilla.fenix.settings.biometric.ext.isAuthenticatorAvailable import org.mozilla.fenix.settings.biometric.ext.isHardwareAvailable /** * Lets the user customize auto closing tabs. */ Loading @@ -40,6 +50,31 @@ class TabsSettingsFragment : PreferenceFragmentCompat() { findPreference<PreferenceCategory>(getString(R.string.pref_key_inactive_tabs_category))?.apply { isVisible = !context.settings().shouldDisableNormalMode } startForResult = registerForActivityResult( onFailure = { }, onSuccess = { onSuccessfulAuthenticationUsingFallbackPrompt() }, ) } private lateinit var startForResult: ActivityResultLauncher<Intent> private fun onSuccessfulAuthenticationUsingFallbackPrompt() { val newValue = !requireContext().settings().privateBrowsingLockedEnabled requireContext().settings().privateBrowsingLockedEnabled = newValue // Update switch state manually requirePreference<SwitchPreference>(R.string.pref_key_private_browsing_locked_enabled).apply { isChecked = !isChecked } } private fun onSuccessfulAuthenticationUsingPrimaryPrompt( pbmLockEnabled: Boolean, preference: Preference, ) { requireContext().settings().privateBrowsingLockedEnabled = pbmLockEnabled // Update switch state manually (preference as? SwitchPreference)?.isChecked = pbmLockEnabled } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { Loading Loading @@ -86,6 +121,67 @@ class TabsSettingsFragment : PreferenceFragmentCompat() { radioOneMonth.onClickListener(::enableInactiveTabsSetting) setupRadioGroups() /** * Changes in this file for "tor-browser#44027 Update PBM lockscreen" were copied from * [PrivateBrowsingFragment] and changed to make sense and work for TBA such as removing * any use of nimbus/glean that was being used for business logic which was making the * release build variant not work. We should check [PrivateBrowsingFragment] for updates * when we rebase * */ setUpHideBrowsingSessionPreference() } private fun setUpHideBrowsingSessionPreference() { val biometricManager = BiometricManager.from(requireContext()) val deviceCapable = biometricManager.isHardwareAvailable() val userHasEnabledCapability = biometricManager.isAuthenticatorAvailable() requirePreference<SwitchPreference>(R.string.pref_key_private_browsing_locked_enabled).apply { title = getString(R.string.preferences_tor_lock_screen_title, getString(R.string.app_name)) summary = getString(R.string.preferences_tor_lock_screen_summary, getString(R.string.app_name)) isChecked = context.settings().privateBrowsingLockedEnabled && biometricManager.isAuthenticatorAvailable() isVisible = deviceCapable isEnabled = userHasEnabledCapability setOnPreferenceChangeListener { preference, newValue -> val pbmLockEnabled = newValue as? Boolean ?: return@setOnPreferenceChangeListener false val titleRes = if (pbmLockEnabled) { R.string.tor_authentication_enable_lock } else { R.string.tor_authentication_disable_lock } DefaultBiometricUtils.bindBiometricsCredentialsPromptOrShowWarning( titleRes = titleRes, titleRes2 = R.string.app_name, view = requireView(), onShowPinVerification = { intent -> startForResult.launch(intent) }, onAuthSuccess = { onSuccessfulAuthenticationUsingPrimaryPrompt( pbmLockEnabled = pbmLockEnabled, preference = preference, ) }, onAuthFailure = { }, ) // Cancel toggle change until biometric is successful false } } requirePreference<Preference>(R.string.pref_key_private_browsing_lock_device_feature_enabled).apply { title = getString(R.string.tor_authentication_lock_device_feature_disabled, getString(R.string.app_name)) isVisible = deviceCapable && !userHasEnabledCapability setOnPreferenceClickListener { context.startActivity(Intent(Settings.ACTION_SECURITY_SETTINGS)) true } } } private fun setupRadioGroups() { Loading Loading
mobile/android/fenix/app/src/beta/res/drawable/tor_browser_app_icon.png 0 → 100644 +7.26 KiB Loading image diff...
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/biometricauthentication/UnlockPrivateTabsFragment.kt +4 −4 Original line number Diff line number Diff line Loading @@ -56,8 +56,7 @@ class UnlockPrivateTabsFragment : Fragment(), UserInteractionHandler { UnlockPrivateTabsScreen( onUnlockClicked = { requestPrompt() }, onLeaveClicked = { PrivateBrowsingLocked.seeOtherTabsClicked.record() closeFragment() requireActivity().moveTaskToBack(true) }, ) Loading @@ -67,13 +66,14 @@ class UnlockPrivateTabsFragment : Fragment(), UserInteractionHandler { } override fun onBackPressed(): Boolean { closeFragment() requireActivity().moveTaskToBack(true) return true } private fun requestPrompt() { DefaultBiometricUtils.bindBiometricsCredentialsPromptOrShowWarning( titleRes = R.string.pbm_authentication_unlock_private_tabs, titleRes = R.string.tor_authentication_unlock_private_tabs, titleRes2 = R.string.app_name, view = requireView(), onShowPinVerification = { intent -> startForResult.launch(intent) }, onAuthSuccess = ::onAuthSuccess, Loading
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/biometricauthentication/UnlockPrivateTabsScreen.kt +28 −15 Original line number Diff line number Diff line Loading @@ -31,6 +31,14 @@ import org.mozilla.fenix.ext.isLargeWindow import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.Theme import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.size import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp import org.mozilla.fenix.compose.parseHtml private const val FILL_WIDTH_LARGE_WINDOW = 0.5f private const val FILL_WIDTH_DEFAULT = 1.0f Loading Loading @@ -71,17 +79,31 @@ private fun Header() { Column( modifier = Modifier.padding(horizontal = 16.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { Row ( verticalAlignment = Alignment.CenterVertically ) { Image( painter = painterResource(id = R.drawable.ic_pbm_firefox_logo), painter = painterResource(id = R.drawable.tor_browser_app_icon), contentDescription = null, // decorative only. modifier = Modifier.padding(32.dp), Modifier .size(62.dp) .padding(end = 10.dp), ) Text( text = stringResource(R.string.app_name), color = FirefoxTheme.colors.textPrimary, fontWeight = FontWeight.Bold, fontSize = 29.sp, letterSpacing = 0.18.sp, lineHeight = 52.sp, ) } Spacer(modifier = Modifier.height(24.dp)) Text( text = stringResource(id = R.string.pbm_authentication_unlock_private_tabs), text = stringResource(id = R.string.tor_authentication_unlock_private_tabs, stringResource(R.string.app_name)), color = FirefoxTheme.colors.textPrimary, textAlign = TextAlign.Center, style = FirefoxTheme.typography.headline6, Loading Loading @@ -109,15 +131,6 @@ private fun Footer(onUnlockClicked: () -> Unit, onLeaveClicked: () -> Unit) { modifier = Modifier.fillMaxWidth(), onClick = onUnlockClicked, ) Spacer(modifier = Modifier.height(8.dp)) TextButton( text = stringResource(R.string.pbm_authentication_leave_private_tabs), onClick = onLeaveClicked, textColor = FirefoxTheme.colors.textActionPrimary, upperCaseText = false, ) } } Loading
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/lifecycle/PrivateBrowsingLockFeature.kt +2 −1 Original line number Diff line number Diff line Loading @@ -312,7 +312,8 @@ fun Fragment.verifyUser( onVerified: (() -> Unit)? = null, ) { biometricUtils.bindBiometricsCredentialsPromptOrShowWarning( titleRes = R.string.pbm_authentication_unlock_private_tabs, titleRes = R.string.tor_authentication_unlock_private_tabs, titleRes2 = R.string.app_name, view = requireView(), onShowPinVerification = { intent -> fallbackVerification.launch(intent) }, onAuthSuccess = { handleVerificationSuccess(requireContext(), onVerified) }, Loading
mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TabsSettingsFragment.kt +96 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,16 @@ import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.utils.view.addToRadioGroup import android.content.Intent import android.provider.Settings import androidx.activity.result.ActivityResultLauncher import androidx.biometric.BiometricManager import androidx.preference.Preference import org.mozilla.fenix.ext.registerForActivityResult import org.mozilla.fenix.settings.biometric.DefaultBiometricUtils import org.mozilla.fenix.settings.biometric.ext.isAuthenticatorAvailable import org.mozilla.fenix.settings.biometric.ext.isHardwareAvailable /** * Lets the user customize auto closing tabs. */ Loading @@ -40,6 +50,31 @@ class TabsSettingsFragment : PreferenceFragmentCompat() { findPreference<PreferenceCategory>(getString(R.string.pref_key_inactive_tabs_category))?.apply { isVisible = !context.settings().shouldDisableNormalMode } startForResult = registerForActivityResult( onFailure = { }, onSuccess = { onSuccessfulAuthenticationUsingFallbackPrompt() }, ) } private lateinit var startForResult: ActivityResultLauncher<Intent> private fun onSuccessfulAuthenticationUsingFallbackPrompt() { val newValue = !requireContext().settings().privateBrowsingLockedEnabled requireContext().settings().privateBrowsingLockedEnabled = newValue // Update switch state manually requirePreference<SwitchPreference>(R.string.pref_key_private_browsing_locked_enabled).apply { isChecked = !isChecked } } private fun onSuccessfulAuthenticationUsingPrimaryPrompt( pbmLockEnabled: Boolean, preference: Preference, ) { requireContext().settings().privateBrowsingLockedEnabled = pbmLockEnabled // Update switch state manually (preference as? SwitchPreference)?.isChecked = pbmLockEnabled } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { Loading Loading @@ -86,6 +121,67 @@ class TabsSettingsFragment : PreferenceFragmentCompat() { radioOneMonth.onClickListener(::enableInactiveTabsSetting) setupRadioGroups() /** * Changes in this file for "tor-browser#44027 Update PBM lockscreen" were copied from * [PrivateBrowsingFragment] and changed to make sense and work for TBA such as removing * any use of nimbus/glean that was being used for business logic which was making the * release build variant not work. We should check [PrivateBrowsingFragment] for updates * when we rebase * */ setUpHideBrowsingSessionPreference() } private fun setUpHideBrowsingSessionPreference() { val biometricManager = BiometricManager.from(requireContext()) val deviceCapable = biometricManager.isHardwareAvailable() val userHasEnabledCapability = biometricManager.isAuthenticatorAvailable() requirePreference<SwitchPreference>(R.string.pref_key_private_browsing_locked_enabled).apply { title = getString(R.string.preferences_tor_lock_screen_title, getString(R.string.app_name)) summary = getString(R.string.preferences_tor_lock_screen_summary, getString(R.string.app_name)) isChecked = context.settings().privateBrowsingLockedEnabled && biometricManager.isAuthenticatorAvailable() isVisible = deviceCapable isEnabled = userHasEnabledCapability setOnPreferenceChangeListener { preference, newValue -> val pbmLockEnabled = newValue as? Boolean ?: return@setOnPreferenceChangeListener false val titleRes = if (pbmLockEnabled) { R.string.tor_authentication_enable_lock } else { R.string.tor_authentication_disable_lock } DefaultBiometricUtils.bindBiometricsCredentialsPromptOrShowWarning( titleRes = titleRes, titleRes2 = R.string.app_name, view = requireView(), onShowPinVerification = { intent -> startForResult.launch(intent) }, onAuthSuccess = { onSuccessfulAuthenticationUsingPrimaryPrompt( pbmLockEnabled = pbmLockEnabled, preference = preference, ) }, onAuthFailure = { }, ) // Cancel toggle change until biometric is successful false } } requirePreference<Preference>(R.string.pref_key_private_browsing_lock_device_feature_enabled).apply { title = getString(R.string.tor_authentication_lock_device_feature_disabled, getString(R.string.app_name)) isVisible = deviceCapable && !userHasEnabledCapability setOnPreferenceClickListener { context.startActivity(Intent(Settings.ACTION_SECURITY_SETTINGS)) true } } } private fun setupRadioGroups() { Loading