clairehurst pushed to branch tor-browser-140.3.0esr-15.0-1 at The Tor Project / Applications / Tor Browser

Commits:

14 changed files:

Changes:

  • mobile/android/fenix/app/src/beta/res/drawable/tor_browser_app_icon.png
    No preview for this file type
  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/biometricauthentication/UnlockPrivateTabsFragment.kt
    ... ... @@ -56,8 +56,7 @@ class UnlockPrivateTabsFragment : Fragment(), UserInteractionHandler {
    56 56
                     UnlockPrivateTabsScreen(
    
    57 57
                         onUnlockClicked = { requestPrompt() },
    
    58 58
                         onLeaveClicked = {
    
    59
    -                        PrivateBrowsingLocked.seeOtherTabsClicked.record()
    
    60
    -                        closeFragment()
    
    59
    +                        requireActivity().moveTaskToBack(true)
    
    61 60
                         },
    
    62 61
                     )
    
    63 62
     
    
    ... ... @@ -67,13 +66,14 @@ class UnlockPrivateTabsFragment : Fragment(), UserInteractionHandler {
    67 66
         }
    
    68 67
     
    
    69 68
         override fun onBackPressed(): Boolean {
    
    70
    -        closeFragment()
    
    69
    +        requireActivity().moveTaskToBack(true)
    
    71 70
             return true
    
    72 71
         }
    
    73 72
     
    
    74 73
         private fun requestPrompt() {
    
    75 74
             DefaultBiometricUtils.bindBiometricsCredentialsPromptOrShowWarning(
    
    76
    -            titleRes = R.string.pbm_authentication_unlock_private_tabs,
    
    75
    +            titleRes = R.string.tor_authentication_unlock_private_tabs,
    
    76
    +            titleRes2 = R.string.app_name,
    
    77 77
                 view = requireView(),
    
    78 78
                 onShowPinVerification = { intent -> startForResult.launch(intent) },
    
    79 79
                 onAuthSuccess = ::onAuthSuccess,
    

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/biometricauthentication/UnlockPrivateTabsScreen.kt
    ... ... @@ -31,6 +31,14 @@ import org.mozilla.fenix.ext.isLargeWindow
    31 31
     import org.mozilla.fenix.theme.FirefoxTheme
    
    32 32
     import org.mozilla.fenix.theme.Theme
    
    33 33
     
    
    34
    +import androidx.compose.foundation.layout.Row
    
    35
    +import androidx.compose.foundation.layout.size
    
    36
    +import androidx.compose.ui.text.AnnotatedString
    
    37
    +import androidx.compose.ui.text.SpanStyle
    
    38
    +import androidx.compose.ui.text.font.FontWeight
    
    39
    +import androidx.compose.ui.unit.sp
    
    40
    +import org.mozilla.fenix.compose.parseHtml
    
    41
    +
    
    34 42
     private const val FILL_WIDTH_LARGE_WINDOW = 0.5f
    
    35 43
     private const val FILL_WIDTH_DEFAULT = 1.0f
    
    36 44
     
    
    ... ... @@ -72,16 +80,30 @@ private fun Header() {
    72 80
             modifier = Modifier.padding(horizontal = 16.dp),
    
    73 81
             horizontalAlignment = Alignment.CenterHorizontally,
    
    74 82
         ) {
    
    75
    -        Image(
    
    76
    -            painter = painterResource(id = R.drawable.ic_pbm_firefox_logo),
    
    77
    -            contentDescription = null, // decorative only.
    
    78
    -            modifier = Modifier.padding(32.dp),
    
    79
    -        )
    
    83
    +        Row (
    
    84
    +            verticalAlignment = Alignment.CenterVertically
    
    85
    +        ) {
    
    86
    +            Image(
    
    87
    +                painter = painterResource(id = R.drawable.tor_browser_app_icon),
    
    88
    +                contentDescription = null, // decorative only.
    
    89
    +                Modifier
    
    90
    +                    .size(62.dp)
    
    91
    +                    .padding(end = 10.dp),
    
    92
    +            )
    
    93
    +            Text(
    
    94
    +                text = stringResource(R.string.app_name),
    
    95
    +                color = FirefoxTheme.colors.textPrimary,
    
    96
    +                fontWeight = FontWeight.Bold,
    
    97
    +                fontSize = 29.sp,
    
    98
    +                letterSpacing = 0.18.sp,
    
    99
    +                lineHeight = 52.sp,
    
    100
    +            )
    
    101
    +        }
    
    80 102
     
    
    81 103
             Spacer(modifier = Modifier.height(24.dp))
    
    82 104
     
    
    83 105
             Text(
    
    84
    -            text = stringResource(id = R.string.pbm_authentication_unlock_private_tabs),
    
    106
    +            text = stringResource(id = R.string.tor_authentication_unlock_private_tabs, stringResource(R.string.app_name)),
    
    85 107
                 color = FirefoxTheme.colors.textPrimary,
    
    86 108
                 textAlign = TextAlign.Center,
    
    87 109
                 style = FirefoxTheme.typography.headline6,
    
    ... ... @@ -109,15 +131,6 @@ private fun Footer(onUnlockClicked: () -> Unit, onLeaveClicked: () -> Unit) {
    109 131
                 modifier = Modifier.fillMaxWidth(),
    
    110 132
                 onClick = onUnlockClicked,
    
    111 133
             )
    
    112
    -
    
    113
    -        Spacer(modifier = Modifier.height(8.dp))
    
    114
    -
    
    115
    -        TextButton(
    
    116
    -            text = stringResource(R.string.pbm_authentication_leave_private_tabs),
    
    117
    -            onClick = onLeaveClicked,
    
    118
    -            textColor = FirefoxTheme.colors.textActionPrimary,
    
    119
    -            upperCaseText = false,
    
    120
    -        )
    
    121 134
         }
    
    122 135
     }
    
    123 136
     
    

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/lifecycle/PrivateBrowsingLockFeature.kt
    ... ... @@ -312,7 +312,8 @@ fun Fragment.verifyUser(
    312 312
         onVerified: (() -> Unit)? = null,
    
    313 313
     ) {
    
    314 314
         biometricUtils.bindBiometricsCredentialsPromptOrShowWarning(
    
    315
    -        titleRes = R.string.pbm_authentication_unlock_private_tabs,
    
    315
    +        titleRes = R.string.tor_authentication_unlock_private_tabs,
    
    316
    +        titleRes2 = R.string.app_name,
    
    316 317
             view = requireView(),
    
    317 318
             onShowPinVerification = { intent -> fallbackVerification.launch(intent) },
    
    318 319
             onAuthSuccess = { handleVerificationSuccess(requireContext(), onVerified) },
    

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/TabsSettingsFragment.kt
    ... ... @@ -17,6 +17,16 @@ import org.mozilla.fenix.ext.settings
    17 17
     import org.mozilla.fenix.ext.showToolbar
    
    18 18
     import org.mozilla.fenix.utils.view.addToRadioGroup
    
    19 19
     
    
    20
    +import android.content.Intent
    
    21
    +import android.provider.Settings
    
    22
    +import androidx.activity.result.ActivityResultLauncher
    
    23
    +import androidx.biometric.BiometricManager
    
    24
    +import androidx.preference.Preference
    
    25
    +import org.mozilla.fenix.ext.registerForActivityResult
    
    26
    +import org.mozilla.fenix.settings.biometric.DefaultBiometricUtils
    
    27
    +import org.mozilla.fenix.settings.biometric.ext.isAuthenticatorAvailable
    
    28
    +import org.mozilla.fenix.settings.biometric.ext.isHardwareAvailable
    
    29
    +
    
    20 30
     /**
    
    21 31
      * Lets the user customize auto closing tabs.
    
    22 32
      */
    
    ... ... @@ -40,6 +50,31 @@ class TabsSettingsFragment : PreferenceFragmentCompat() {
    40 50
             findPreference<PreferenceCategory>(getString(R.string.pref_key_inactive_tabs_category))?.apply {
    
    41 51
                 isVisible = !context.settings().shouldDisableNormalMode
    
    42 52
             }
    
    53
    +
    
    54
    +        startForResult = registerForActivityResult(
    
    55
    +            onFailure = { },
    
    56
    +            onSuccess = { onSuccessfulAuthenticationUsingFallbackPrompt() },
    
    57
    +        )
    
    58
    +    }
    
    59
    +
    
    60
    +    private lateinit var startForResult: ActivityResultLauncher<Intent>
    
    61
    +
    
    62
    +    private fun onSuccessfulAuthenticationUsingFallbackPrompt() {
    
    63
    +        val newValue = !requireContext().settings().privateBrowsingLockedEnabled
    
    64
    +        requireContext().settings().privateBrowsingLockedEnabled = newValue
    
    65
    +        // Update switch state manually
    
    66
    +        requirePreference<SwitchPreference>(R.string.pref_key_private_browsing_locked_enabled).apply {
    
    67
    +            isChecked = !isChecked
    
    68
    +        }
    
    69
    +    }
    
    70
    +
    
    71
    +    private fun onSuccessfulAuthenticationUsingPrimaryPrompt(
    
    72
    +        pbmLockEnabled: Boolean,
    
    73
    +        preference: Preference,
    
    74
    +    ) {
    
    75
    +        requireContext().settings().privateBrowsingLockedEnabled = pbmLockEnabled
    
    76
    +        // Update switch state manually
    
    77
    +        (preference as? SwitchPreference)?.isChecked = pbmLockEnabled
    
    43 78
         }
    
    44 79
     
    
    45 80
         override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    
    ... ... @@ -86,6 +121,67 @@ class TabsSettingsFragment : PreferenceFragmentCompat() {
    86 121
             radioOneMonth.onClickListener(::enableInactiveTabsSetting)
    
    87 122
     
    
    88 123
             setupRadioGroups()
    
    124
    +        /**
    
    125
    +         * Changes in this file for "tor-browser#44027 Update PBM lockscreen" were copied from
    
    126
    +         * [PrivateBrowsingFragment] and changed to make sense and work for TBA such as removing
    
    127
    +         * any use of nimbus/glean that was being used for business logic which was making the
    
    128
    +         * release build variant not work. We should check [PrivateBrowsingFragment] for updates
    
    129
    +         * when we rebase
    
    130
    +         * */
    
    131
    +        setUpHideBrowsingSessionPreference()
    
    132
    +    }
    
    133
    +
    
    134
    +    private fun setUpHideBrowsingSessionPreference() {
    
    135
    +        val biometricManager = BiometricManager.from(requireContext())
    
    136
    +        val deviceCapable = biometricManager.isHardwareAvailable()
    
    137
    +        val userHasEnabledCapability = biometricManager.isAuthenticatorAvailable()
    
    138
    +
    
    139
    +        requirePreference<SwitchPreference>(R.string.pref_key_private_browsing_locked_enabled).apply {
    
    140
    +            title = getString(R.string.preferences_tor_lock_screen_title, getString(R.string.app_name))
    
    141
    +            summary = getString(R.string.preferences_tor_lock_screen_summary, getString(R.string.app_name))
    
    142
    +            isChecked = context.settings().privateBrowsingLockedEnabled &&
    
    143
    +                    biometricManager.isAuthenticatorAvailable()
    
    144
    +            isVisible = deviceCapable
    
    145
    +            isEnabled = userHasEnabledCapability
    
    146
    +
    
    147
    +            setOnPreferenceChangeListener { preference, newValue ->
    
    148
    +                val pbmLockEnabled = newValue as? Boolean
    
    149
    +                    ?: return@setOnPreferenceChangeListener false
    
    150
    +
    
    151
    +                val titleRes = if (pbmLockEnabled) {
    
    152
    +                    R.string.tor_authentication_enable_lock
    
    153
    +                } else {
    
    154
    +                    R.string.tor_authentication_disable_lock
    
    155
    +                }
    
    156
    +
    
    157
    +                DefaultBiometricUtils.bindBiometricsCredentialsPromptOrShowWarning(
    
    158
    +                    titleRes = titleRes,
    
    159
    +                    titleRes2 = R.string.app_name,
    
    160
    +                    view = requireView(),
    
    161
    +                    onShowPinVerification = { intent -> startForResult.launch(intent) },
    
    162
    +                    onAuthSuccess = {
    
    163
    +                        onSuccessfulAuthenticationUsingPrimaryPrompt(
    
    164
    +                            pbmLockEnabled = pbmLockEnabled,
    
    165
    +                            preference = preference,
    
    166
    +                        )
    
    167
    +                    },
    
    168
    +                    onAuthFailure = { },
    
    169
    +                )
    
    170
    +
    
    171
    +                // Cancel toggle change until biometric is successful
    
    172
    +                false
    
    173
    +            }
    
    174
    +        }
    
    175
    +
    
    176
    +        requirePreference<Preference>(R.string.pref_key_private_browsing_lock_device_feature_enabled).apply {
    
    177
    +            title = getString(R.string.tor_authentication_lock_device_feature_disabled, getString(R.string.app_name))
    
    178
    +            isVisible = deviceCapable && !userHasEnabledCapability
    
    179
    +
    
    180
    +            setOnPreferenceClickListener {
    
    181
    +                context.startActivity(Intent(Settings.ACTION_SECURITY_SETTINGS))
    
    182
    +                true
    
    183
    +            }
    
    184
    +        }
    
    89 185
         }
    
    90 186
     
    
    91 187
         private fun setupRadioGroups() {
    

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/biometric/BiometricUtils.kt
    ... ... @@ -42,6 +42,7 @@ interface BiometricUtils {
    42 42
          */
    
    43 43
         fun bindBiometricsCredentialsPromptOrShowWarning(
    
    44 44
             @StringRes titleRes: Int = R.string.logins_biometric_prompt_message_2,
    
    45
    +        @StringRes titleRes2: Int = R.string.empty_string,
    
    45 46
             view: View,
    
    46 47
             onShowPinVerification: (Intent) -> Unit,
    
    47 48
             onAuthSuccess: () -> Unit,
    
    ... ... @@ -56,6 +57,7 @@ object DefaultBiometricUtils : BiometricUtils {
    56 57
         @Suppress("Deprecation")
    
    57 58
         override fun bindBiometricsCredentialsPromptOrShowWarning(
    
    58 59
             @StringRes titleRes: Int,
    
    60
    +        @StringRes titleRes2: Int,
    
    59 61
             view: View,
    
    60 62
             onShowPinVerification: (Intent) -> Unit,
    
    61 63
             onAuthSuccess: () -> Unit,
    
    ... ... @@ -90,7 +92,7 @@ object DefaultBiometricUtils : BiometricUtils {
    90 92
             // Use the BiometricPrompt first
    
    91 93
             if (BiometricPromptFeature.canUseFeature(BiometricManager.from(context))) {
    
    92 94
                 biometricPromptFeature.get()
    
    93
    -                ?.requestAuthentication(context.resources.getString(titleRes))
    
    95
    +                ?.requestAuthentication(context.resources.getString(titleRes, context.resources.getString(titleRes2)))
    
    94 96
                 return
    
    95 97
             }
    
    96 98
     
    
    ... ... @@ -99,7 +101,7 @@ object DefaultBiometricUtils : BiometricUtils {
    99 101
             if (manager?.isKeyguardSecure == true) {
    
    100 102
                 val confirmDeviceCredentialIntent = manager.createConfirmDeviceCredentialIntent(
    
    101 103
                     context.resources.getString(R.string.logins_biometric_prompt_message_pin),
    
    102
    -                context.resources.getString(titleRes),
    
    104
    +                context.resources.getString(titleRes, context.resources.getString(titleRes2)),
    
    103 105
                 )
    
    104 106
                 onShowPinVerification(confirmDeviceCredentialIntent)
    
    105 107
             } else {
    

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayBanner.kt
    ... ... @@ -205,7 +205,7 @@ fun TabsTrayBanner(
    205 205
                     // After this bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1965545
    
    206 206
                     // is resolved, we should swap the button 1 and button 2 click actions.
    
    207 207
                     Banner(
    
    208
    -                    message = stringResource(id = R.string.private_tab_cfr_title),
    
    208
    +                    message = stringResource(id = R.string.tor_tab_cfr_title, stringResource(R.string.app_name)),
    
    209 209
                         button1Text = stringResource(id = R.string.private_tab_cfr_negative),
    
    210 210
                         button2Text = stringResource(id = R.string.private_tab_cfr_positive),
    
    211 211
                         onButton1Click = {
    

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayFragment.kt
    ... ... @@ -265,7 +265,7 @@ class TabsTrayFragment : AppCompatDialogFragment() {
    265 265
                         shouldShowTabAutoCloseBanner = requireContext().settings().shouldShowAutoCloseTabsBanner &&
    
    266 266
                             requireContext().settings().canShowCfr,
    
    267 267
                         shouldShowLockPbmBanner =
    
    268
    -                        if (FxNimbus.features.privateBrowsingLock.value().enabled) {
    
    268
    +                        if (true) {
    
    269 269
                                 shouldShowLockPbmBanner(
    
    270 270
                                     isPrivateMode = (activity as HomeActivity).browsingModeManager.mode.isPrivate,
    
    271 271
                                     hasPrivateTabs = requireComponents.core.store.state.privateTabs.isNotEmpty(),
    
    ... ... @@ -775,10 +775,11 @@ class TabsTrayFragment : AppCompatDialogFragment() {
    775 775
             val isAuthenticatorAvailable =
    
    776 776
                 BiometricManager.from(requireContext()).isAuthenticatorAvailable()
    
    777 777
             if (!isAuthenticatorAvailable) {
    
    778
    -            findNavController().navigate(TabsTrayFragmentDirections.actionGlobalPrivateBrowsingFragment())
    
    778
    +            findNavController().navigate(TabsTrayFragmentDirections.actionGlobalTabSettingsFragment())
    
    779 779
             } else {
    
    780 780
                 DefaultBiometricUtils.bindBiometricsCredentialsPromptOrShowWarning(
    
    781
    -                titleRes = R.string.pbm_authentication_enable_lock,
    
    781
    +                titleRes = R.string.tor_authentication_enable_lock,
    
    782
    +                titleRes2 = R.string.app_name,
    
    782 783
                     view = requireView(),
    
    783 784
                     onShowPinVerification = { intent -> enablePbmPinLauncher.launch(intent) },
    
    784 785
                     onAuthSuccess = {
    

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt
    ... ... @@ -334,10 +334,9 @@ class Settings(private val appContext: Context) : PreferencesHolder {
    334 334
             default = false,
    
    335 335
         )
    
    336 336
     
    
    337
    -    var privateBrowsingLockedEnabled by lazyFeatureFlagPreference(
    
    337
    +    var privateBrowsingLockedEnabled by booleanPreference(
    
    338 338
             appContext.getPreferenceKey(R.string.pref_key_private_browsing_locked_enabled),
    
    339
    -        featureFlag = FxNimbus.features.privateBrowsingLock.value().enabled,
    
    340
    -        default = { false },
    
    339
    +        default = false,
    
    341 340
         )
    
    342 341
     
    
    343 342
         var shouldReturnToBrowser by booleanPreference(
    

  • mobile/android/fenix/app/src/main/res/drawable/tor_browser_app_icon.png
    No preview for this file type
  • mobile/android/fenix/app/src/main/res/values/torbrowser_strings.xml
    ... ... @@ -142,4 +142,21 @@
    142 142
         <!-- Notification body for closing browser tabs. "%s" will be replaced with the localised application name, such as "Tor Browser". -->
    
    143 143
         <string name="notification_close_tor_browser_tabs_long">Tap or swipe this notification to close %s’s tabs</string>
    
    144 144
     
    
    145
    +    <!-- Hide Tor Browser tabs authentication screen -->
    
    146
    +    <!-- Label for the primary action button to unlock private tabs. "%s" will be replaced with the localised application name, such as "Tor Browser" -->
    
    147
    +    <string name="tor_authentication_unlock_private_tabs">Unlock %s tabs</string>
    
    148
    +    <!-- Authentication prompt title to enable the private tabs mode. "%s" will be replaced with the localised application name, such as "Tor Browser" -->
    
    149
    +    <string name="tor_authentication_enable_lock">Enable %s tabs screen lock</string>
    
    150
    +    <!-- Authentication prompt title to disable the private tabs mode. "%s" will be replaced with the localised application name, such as "Tor Browser" -->
    
    151
    +    <string name="tor_authentication_disable_lock">Disable %s tabs screen lock</string>
    
    152
    +    <!-- Label for a preference shown when the device supports screen lock (e.g., PIN, pattern, or password) but the user has not set one up. "%s" will be replaced with the localised application name, such as "Tor Browser" -->
    
    153
    +    <string name="tor_authentication_lock_device_feature_disabled">Set up screen lock to hide %s tabs</string>
    
    154
    +    <!-- Title text for the contextual feature recommendation (CFR) suggesting the user enable a screen lock to protect Tor Browser tabs. "%s" will be replaced with the localised application name, such as "Tor Browser" -->
    
    155
    +    <string name="tor_tab_cfr_title">Use screen lock to hide %s tabs?</string>
    
    156
    +
    
    157
    +    <!-- Preference title for using the screen lock to hide Tor Browser tabs. "%s" will be replaced with the localised application name, such as "Tor Browser" -->
    
    158
    +    <string name="preferences_tor_lock_screen_title">Use screen lock to hide %s tabs</string>
    
    159
    +    <!-- Informs the user how to access the tabs when "Use screen lock to hide Tor Browser tabs" is enabled. "%s" will be replaced with the localised application name, such as "Tor Browser" -->
    
    160
    +    <string name="preferences_tor_lock_screen_summary">View %s tabs with your fingerprint, PIN, or face unlock.</string>
    
    161
    +
    
    145 162
     </resources>

  • mobile/android/fenix/app/src/main/res/xml/tabs_preferences.xml
    ... ... @@ -57,4 +57,14 @@
    57 57
                 android:key="@string/pref_key_inactive_tabs"
    
    58 58
                 android:title="@string/preferences_inactive_tabs_title"/>
    
    59 59
         </androidx.preference.PreferenceCategory>
    
    60
    +
    
    61
    +    <PreferenceCategory
    
    62
    +        android:key="@string/pref_key_pbm_lock_category_divider"
    
    63
    +        android:layout="@xml/preference_category_divider"
    
    64
    +        android:selectable="false" />
    
    65
    +    <SwitchPreference
    
    66
    +        android:defaultValue="false"
    
    67
    +        android:key="pref_key_private_browsing_locked_enabled" />
    
    68
    +    <Preference
    
    69
    +        android:key="@string/pref_key_private_browsing_lock_device_feature_enabled" />
    
    60 70
     </androidx.preference.PreferenceScreen>

  • mobile/android/fenix/app/src/nightly/res/drawable/tor_browser_app_icon.png
    No preview for this file type
  • mobile/android/fenix/app/src/release/res/drawable/tor_browser_app_icon.png
    No preview for this file type