[tbb-commits] [Git][tpo/applications/firefox-android][firefox-android-115.2.1-13.5-1] 4 commits: fixup! Modify build system

Pier Angelo Vendrame (@pierov) git at gitlab.torproject.org
Thu Feb 22 09:15:26 UTC 2024



Pier Angelo Vendrame pushed to branch firefox-android-115.2.1-13.5-1 at The Tor Project / Applications / firefox-android


Commits:
6c3669ee by clairehurst at 2024-02-21T18:55:49-07:00
fixup! Modify build system

- - - - -
cd3473f6 by clairehurst at 2024-02-21T20:41:44-07:00
fixup! Add Tor integration and UI

Remove quick start

- - - - -
5e60c209 by clairehurst at 2024-02-21T21:10:03-07:00
Implement Android-native Connection Assist UI

- - - - -
7c1cc539 by clairehurst at 2024-02-21T21:10:03-07:00
fixup! Enable the connect assist experiments on alpha

- - - - -


22 changed files:

- fenix/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt
- fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt
- fenix/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorBetaConnectionFeaturesFragment.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapFragment.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapStatus.kt
- + fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistFragment.kt
- + fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistViewModel.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerTAS.kt
- − fenix/app/src/main/java/org/mozilla/fenix/tor/bootstrap/TorQuickStart.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapConnectViewHolder.kt
- + fenix/app/src/main/res/drawable/connect.xml
- fenix/app/src/main/res/drawable/progress_gradient.xml
- + fenix/app/src/main/res/layout/fragment_tor_connection_assist.xml
- fenix/app/src/main/res/layout/tor_bootstrap_connect.xml
- fenix/app/src/main/res/layout/tor_network_settings_beta_connection_features.xml
- fenix/app/src/main/res/navigation/nav_graph.xml
- fenix/app/src/main/res/values/colors.xml
- fenix/app/src/main/res/values/torbrowser_strings.xml
- fenix/tools/tba-fetch-deps.sh


Changes:

=====================================
fenix/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt
=====================================
@@ -41,4 +41,5 @@ enum class BrowserDirection(@IdRes val fragmentId: Int) {
     FromLoginDetailFragment(R.id.loginDetailFragment),
     FromTabsTray(R.id.tabsTrayFragment),
     FromRecentlyClosed(R.id.recentlyClosedFragment),
+    FromTorConnectionAssistFragment(R.id.torConnectionAssistFragment)
 }


=====================================
fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt
=====================================
@@ -157,6 +157,7 @@ import org.mozilla.fenix.tabstray.TabsTrayFragment
 import org.mozilla.fenix.tabstray.TabsTrayFragmentDirections
 import org.mozilla.fenix.theme.DefaultThemeManager
 import org.mozilla.fenix.theme.ThemeManager
+import org.mozilla.fenix.tor.TorConnectionAssistFragmentDirections
 import org.mozilla.fenix.tor.TorEvents
 import org.mozilla.fenix.trackingprotection.TrackingProtectionPanelDialogFragmentDirections
 import org.mozilla.fenix.utils.BrowsersCache
@@ -1085,6 +1086,10 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, TorIn
         BrowserDirection.FromStudiesFragment -> StudiesFragmentDirections.actionGlobalBrowser(
             customTabSessionId,
         )
+        BrowserDirection.FromTorConnectionAssistFragment,
+        -> TorConnectionAssistFragmentDirections.actionGlobalBrowser(
+            customTabSessionId,
+        )
     }
 
     /**


=====================================
fenix/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
=====================================
@@ -115,7 +115,6 @@ import org.mozilla.fenix.search.toolbar.SearchSelectorMenu
 import org.mozilla.fenix.tabstray.TabsTrayAccessPoint
 import org.mozilla.fenix.tor.TorBootstrapFragmentDirections
 import org.mozilla.fenix.tor.TorBootstrapStatus
-import org.mozilla.fenix.tor.bootstrap.TorQuickStart
 import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_MAX_THRESHOLD
 import org.mozilla.fenix.utils.allowUndo
 import org.mozilla.fenix.wallpapers.Wallpaper
@@ -202,7 +201,6 @@ class HomeFragment : Fragment() {
     private val recentBookmarksFeature = ViewBoundFeatureWrapper<RecentBookmarksFeature>()
     private val historyMetadataFeature = ViewBoundFeatureWrapper<RecentVisitsFeature>()
     private val searchSelectorBinding = ViewBoundFeatureWrapper<SearchSelectorBinding>()
-    private val torQuickStart by lazy { TorQuickStart(requireContext()) }
     private val searchSelectorMenuBinding = ViewBoundFeatureWrapper<SearchSelectorMenuBinding>()
     private lateinit var torBootstrapStatus: TorBootstrapStatus
 
@@ -236,7 +234,6 @@ class HomeFragment : Fragment() {
         val components = requireComponents
 
         torBootstrapStatus = TorBootstrapStatus(
-            torQuickStart,
             !BuildConfig.DISABLE_TOR,
             components.torController,
             ::dispatchModeChanges


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorBetaConnectionFeaturesFragment.kt
=====================================
@@ -54,10 +54,7 @@ class TorBetaConnectionFeaturesFragment : Fragment() {
                 children.forEach { it.isEnabled = false }
             }
         } else {
-            // Do not enable the native UI until it is actually available.
-            // binding.enableBetaConnectionFeaturesModes.children.forEach { it.isEnabled = true }
-            binding.useNewBootstrapWithHtmlUiRadioButton.isEnabled = true
-            binding.useNewBootstrapWithNativeUiRadioButton.isEnabled = false
+            binding.enableBetaConnectionFeaturesModes.children.forEach { it.isEnabled = true }
         }
     }
 


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapFragment.kt
=====================================
@@ -8,14 +8,12 @@ import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
-import androidx.annotation.VisibleForTesting
 import androidx.core.view.children
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.lifecycleScope
 import org.mozilla.fenix.BuildConfig
 import org.mozilla.fenix.databinding.FragmentHomeBinding
 import org.mozilla.fenix.ext.requireComponents
-import org.mozilla.fenix.tor.bootstrap.TorQuickStart
 import org.mozilla.fenix.tor.interactor.DefaultTorBootstrapInteractor
 import org.mozilla.fenix.tor.interactor.TorBootstrapInteractor
 import androidx.navigation.fragment.findNavController
@@ -30,7 +28,6 @@ import org.mozilla.fenix.tor.view.TorBootstrapView
 
 @Suppress("TooManyFunctions", "LargeClass")
 class TorBootstrapFragment : Fragment() {
-    private val torQuickStart by lazy { TorQuickStart(requireContext()) }
 
     internal var _binding: FragmentHomeBinding? = null
     private val binding get() = _binding!!
@@ -55,7 +52,6 @@ class TorBootstrapFragment : Fragment() {
         val components = requireComponents
 
         torBootstrapStatus = TorBootstrapStatus(
-            torQuickStart,
             !BuildConfig.DISABLE_TOR,
             components.torController,
             ::dispatchModeChanges


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapStatus.kt
=====================================
@@ -4,11 +4,8 @@
 
 package org.mozilla.fenix.tor
 
-import org.mozilla.fenix.tor.bootstrap.TorQuickStart
-
 @SuppressWarnings("LongParameterList", "TooManyFunctions")
 class TorBootstrapStatus(
-        private val torQuickStart: TorQuickStart,
         private val shouldStartTor: Boolean,
         private val torController: TorController,
         private val dispatchModeChanges: (isShouldBootstrap: Boolean) -> Unit
@@ -18,7 +15,7 @@ class TorBootstrapStatus(
             torController.registerTorListener(this)
         }
 
-        fun isBootstrapping() = (shouldStartTor && (!torQuickStart.quickStartTor() && !torController.isBootstrapped))
+        fun isBootstrapping() = (shouldStartTor && !torController.isBootstrapped)
 
 
         @SuppressWarnings("EmptyFunctionBlock")


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistFragment.kt
=====================================
@@ -0,0 +1,131 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.fenix.tor
+
+import android.os.Build
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import androidx.navigation.fragment.findNavController
+import kotlinx.coroutines.launch
+import org.mozilla.fenix.R
+import org.mozilla.fenix.databinding.FragmentTorConnectionAssistBinding
+import org.mozilla.fenix.ext.hideToolbar
+
+class TorConnectionAssistFragment : Fragment() {
+
+    private var _binding: FragmentTorConnectionAssistBinding? = null
+    private val binding get() = _binding!!
+
+    private val viewModel: TorConnectionAssistViewModel by viewModels()
+
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?,
+    ): View {
+        _binding = FragmentTorConnectionAssistBinding.inflate(
+            inflater, container, false,
+        )
+
+        return binding.root
+    }
+
+    override fun onResume() {
+        super.onResume()
+        hideToolbar()
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        lifecycleScope.launch {
+            repeatOnLifecycle(Lifecycle.State.STARTED) {
+                viewModel.torConnectState.collect {
+                    when (it) {
+                        TorConnectState.Initial -> showConfiguring()
+                        TorConnectState.Configuring -> showConfiguring()
+                        TorConnectState.AutoBootstrapping -> showBootstrapping()
+                        TorConnectState.Bootstrapping -> showBootstrapping()
+                        TorConnectState.Error -> TODO()
+                        TorConnectState.Bootstrapped -> openHome()
+                        TorConnectState.Disabled -> openHome()
+                    }
+                }
+            }
+        }
+
+        viewModel.progress().observe(
+            viewLifecycleOwner,
+        ) { progress ->
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                binding.torBootstrapProgressBar.setProgress(progress, true)
+            } else {
+                binding.torBootstrapProgressBar.progress = progress
+            }
+        }
+
+        viewModel.quickconnectToggle().observe(
+            viewLifecycleOwner
+        ) {
+            binding.quickstartSwitch.isChecked = it
+        }
+
+        binding.settingsButton.setOnClickListener {
+            viewModel.cancelTorBootstrap()
+            openSettings()
+        }
+
+        binding.torBootstrapConnectButton.setOnClickListener {
+            viewModel.handleConnect(lifecycleScope = lifecycleScope)
+        }
+
+        binding.quickstartSwitch.setOnCheckedChangeListener { _, isChecked ->
+            viewModel.handleQuickstartChecked(isChecked)
+        }
+    }
+
+    private fun showConfiguring() {
+        binding.torBootstrapConnectButton.visibility = View.VISIBLE
+        binding.torBootstrapNetworkSettingsButton.text =
+            getString(R.string.connection_assist_configure_connection_button)
+        binding.torBootstrapNetworkSettingsButton.setOnClickListener {
+            openTorNetworkSettings()
+        }
+    }
+
+    private fun showBootstrapping() {
+        binding.torBootstrapConnectButton.visibility = View.INVISIBLE
+        binding.torBootstrapNetworkSettingsButton.text = getString(R.string.btn_cancel)
+        binding.torBootstrapNetworkSettingsButton.setOnClickListener {
+            viewModel.cancelTorBootstrap()
+        }
+    }
+
+    private fun openSettings(preferenceToScrollTo: String? = null) {
+        findNavController().navigate(
+            TorConnectionAssistFragmentDirections
+                .actionTorConnectionAssistFragmentToSettingsFragment(preferenceToScrollTo),
+        )
+    }
+
+    private fun openTorNetworkSettings() {
+        findNavController().navigate(
+            TorConnectionAssistFragmentDirections
+                .actionTorConnectionAssistFragmentToTorNetworkSettings(),
+        )
+    }
+
+    private fun openHome() {
+        findNavController().navigate(TorConnectionAssistFragmentDirections.actionStartupHome())
+    }
+
+}


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistViewModel.kt
=====================================
@@ -0,0 +1,86 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.fenix.tor
+
+import android.app.Application
+import android.util.Log
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.LifecycleCoroutineScope
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import org.mozilla.fenix.ext.components
+
+class TorConnectionAssistViewModel(
+    application: Application,
+) : AndroidViewModel(application), TorEvents {
+
+    private val TAG = "torConnectionAssistVM"
+    private val components = getApplication<Application>().components
+
+    private val _torController: TorControllerGV = components.torController as TorControllerGV
+
+    private val _torConnectState = MutableStateFlow(TorConnectState.Initial)
+    internal val torConnectState: StateFlow<TorConnectState> = _torConnectState
+
+    init {
+        _torController.registerTorListener(this)
+    }
+
+    private val _progress = MutableLiveData(0)
+    fun progress(): LiveData<Int> {
+        return _progress
+    }
+
+    private val _quickconnectToggle = MutableLiveData(_torController.quickstart)
+    fun quickconnectToggle(): LiveData<Boolean> {
+        return _quickconnectToggle
+    }
+
+    fun handleConnect(
+        withDebugLogging: Boolean = false,
+        lifecycleScope: LifecycleCoroutineScope? = null,
+    ) {
+        _torController.initiateTorBootstrap(
+            withDebugLogging = withDebugLogging,
+            lifecycleScope = lifecycleScope,
+        )
+    }
+
+    fun handleQuickstartChecked(checked: Boolean) {
+        _torController.quickstart = checked
+    }
+
+    fun cancelTorBootstrap() {
+        _torController.stopTor()
+        _torController.setTorStopped()
+    }
+
+    override fun onTorConnecting() {
+        Log.d(TAG, "onTorConnecting()")
+    }
+
+    override fun onTorConnected() {
+        Log.d(TAG, "onTorConnected()")
+        _torController.unregisterTorListener(this)
+        _torConnectState.value = _torController.lastKnownStatus
+    }
+
+    override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) {
+        Log.d(TAG, "onTorStatusUpdate($entry, $status, $progress)")
+        if (progress != null) {
+            _progress.value = progress.toInt()
+        }
+        _torConnectState.value = _torController.lastKnownStatus
+    }
+
+    override fun onTorStopped() {
+        Log.d(TAG, "onTorStopped()")
+        _progress.value = 0
+        _torConnectState.value = _torController.lastKnownStatus
+    }
+
+}


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt
=====================================
@@ -49,6 +49,7 @@ interface TorController: TorEvents {
     var bridgesEnabled: Boolean
     var bridgeTransport: TorBridgeTransportConfig
     var userProvidedBridges: String?
+    var quickstart: Boolean
 
     fun start()
     fun stop()


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt
=====================================
@@ -52,7 +52,7 @@ class TorControllerGV(
 
     private var torListeners = mutableListOf<TorEvents>()
 
-    private var lastKnownStatus = TorConnectState.Initial
+    internal var lastKnownStatus = TorConnectState.Initial
     private var wasTorBootstrapped = false
     private var isTorRestarting = false
 
@@ -66,6 +66,17 @@ class TorControllerGV(
     override val isBootstrapped get() = isTorBootstrapped
     override val isConnected get() = (lastKnownStatus.isStarted() && !isTorRestarting)
 
+    override var quickstart: Boolean
+        get() {
+            return getTorSettings()?.quickstart ?: false
+        }
+        set(value) {
+            getTorSettings()?.let {
+                it.quickstart = value
+                getTorIntegration().setSettings(it, true, true)
+            }
+        }
+
     private fun getTorIntegration(): TorIntegrationAndroid {
         return (context.components.core.engine as GeckoEngine).getTorIntegrationController()
     }
@@ -198,7 +209,7 @@ class TorControllerGV(
     }
 
     override fun setTorStopped() {
-        lastKnownStatus = TorConnectState.Disabled
+        lastKnownStatus = TorConnectState.Configuring
         onTorStopped()
     }
 
@@ -243,7 +254,7 @@ class TorControllerGV(
             if (isTorRestarting) {
                 initiateTorBootstrap()
             } else {
-                onTorStopped()
+                setTorStopped()
             }
         }
 
@@ -280,6 +291,7 @@ class TorControllerGV(
     // TorEventsBootstrapStateChangeListener
     override fun onBootstrapError(message: String?, details: String?) {
         lastKnownStatus = TorConnectState.Error
+        onBootstrapStateChange(TorConnectState.Error.state)
     }
 
     // TorEventsBootstrapStateChangeListener


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerTAS.kt
=====================================
@@ -19,6 +19,7 @@ class TorControllerTAS (private val context: Context): TorController {
     private val lbm: LocalBroadcastManager = LocalBroadcastManager.getInstance(context)
     private val entries = mutableListOf<Pair<String?, String?>>()
     override val logEntries get() = entries
+    override var quickstart: Boolean = false // Stub, is never used
 
     private var torListeners = mutableListOf<TorEvents>()
 


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/bootstrap/TorQuickStart.kt deleted
=====================================
@@ -1,54 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.fenix.tor.bootstrap
-
-import android.content.Context
-import android.content.SharedPreferences
-import android.os.StrictMode
-import androidx.annotation.VisibleForTesting
-import mozilla.components.support.ktx.android.content.PreferencesHolder
-import mozilla.components.support.ktx.android.content.booleanPreference
-import org.mozilla.fenix.ext.components
-
-class TorQuickStart(val context: Context) : PreferencesHolder {
-
-    override val preferences: SharedPreferences =
-        context.components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) {
-            context.getSharedPreferences(
-                PREF_NAME_TOR_BOOTSTRAP_KEY,
-                Context.MODE_PRIVATE
-            )
-        }
-
-    private var torQuickStart by booleanPreference(TOR_QUICK_START, default = false)
-
-    fun quickStartTor() =
-        context.components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) { torQuickStart }
-
-    fun enableQuickStartTor() {
-        torQuickStart = true
-    }
-    fun disableQuickStartTor() {
-        torQuickStart = false
-    }
-    fun setQuickStartTor(enabled: Boolean) = if (enabled) {
-        enableQuickStartTor()
-    } else {
-        disableQuickStartTor()
-    }
-
-    companion object {
-        /**
-         * Name of the shared preferences file.
-         */
-        private const val PREF_NAME_TOR_BOOTSTRAP_KEY = "tor.bootstrap"
-
-        /**
-         * Key for [quickStartTor].
-         */
-        @VisibleForTesting
-        internal const val TOR_QUICK_START = "tor.bootstrap.quick_start_enabled"
-    }
-}


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/view/TorBootstrapConnectViewHolder.kt
=====================================
@@ -10,7 +10,6 @@ import org.mozilla.fenix.R
 import org.mozilla.fenix.components.Components
 import org.mozilla.fenix.databinding.TorBootstrapConnectBinding
 import org.mozilla.fenix.tor.TorEvents
-import org.mozilla.fenix.tor.bootstrap.TorQuickStart
 import org.mozilla.fenix.tor.interactor.TorBootstrapInteractor
 
 class TorBootstrapConnectViewHolder(
@@ -23,17 +22,6 @@ class TorBootstrapConnectViewHolder(
 
     init {
         binding = TorBootstrapConnectBinding.bind(view)
-        val torQuickStart = TorQuickStart(view.context)
-        setQuickStartDescription(view, torQuickStart)
-
-        with(binding.quickStartToggle) {
-            setOnCheckedChangeListener { _, isChecked ->
-                torQuickStart.setQuickStartTor(isChecked)
-                setQuickStartDescription(view, torQuickStart)
-            }
-
-            isChecked = torQuickStart.quickStartTor()
-        }
 
         with(binding.torBootstrapNetworkSettingsButton) {
             setOnClickListener {
@@ -66,20 +54,6 @@ class TorBootstrapConnectViewHolder(
         components.torController.registerTorListener(this)
     }
 
-    private fun setQuickStartDescription(view: View, torQuickStart: TorQuickStart) {
-        val resources = view.context.resources
-        val appName = resources.getString(R.string.app_name)
-        if (torQuickStart.quickStartTor()) {
-            binding.torBootstrapQuickStartDescription.text = resources.getString(
-                R.string.tor_bootstrap_quick_start_enabled, appName
-            )
-        } else {
-            binding.torBootstrapQuickStartDescription.text = resources.getString(
-                R.string.tor_bootstrap_quick_start_disabled
-            )
-        }
-    }
-
     @SuppressWarnings("EmptyFunctionBlock")
     override fun onTorConnecting() {
     }


=====================================
fenix/app/src/main/res/drawable/connect.xml
=====================================
@@ -0,0 +1,17 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="40dp"
+    android:height="40dp"
+    android:viewportWidth="40"
+    android:viewportHeight="40">
+  <path
+      android:pathData="M20,1.253C9.647,1.253 1.253,9.647 1.253,20C1.253,28.967 7.547,36.46 15.96,38.307C16.84,38.5 17.733,38.633 18.653,38.693V24.373C16.787,23.8 15.427,22.06 15.427,20C15.427,17.473 17.473,15.427 20,15.427C22.527,15.427 24.573,17.473 24.573,20C24.573,22.06 23.213,23.8 21.347,24.373V38.693C22.267,38.633 23.16,38.5 24.04,38.307C32.453,36.46 38.747,28.967 38.747,20C38.747,9.647 30.353,1.253 20,1.253ZM24.04,35.293V26.32C26.12,24.987 27.5,22.653 27.5,20C27.5,15.86 24.14,12.5 20,12.5C15.86,12.5 12.5,15.86 12.5,20C12.5,22.653 13.88,24.987 15.96,26.32V35.293C9.18,33.513 4.18,27.347 4.18,20C4.18,11.26 11.26,4.18 20,4.18C28.74,4.18 35.82,11.26 35.82,20C35.82,27.347 30.82,33.513 24.04,35.293Z"
+      android:fillColor="#FBFBFE"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M20,6.873C12.753,6.873 6.873,12.753 6.873,20C6.873,25.84 10.687,30.787 15.96,32.487V29.36C12.34,27.8 9.807,24.193 9.807,20C9.807,14.367 14.367,9.807 20,9.807C25.633,9.807 30.193,14.367 30.193,20C30.193,24.193 27.66,27.8 24.04,29.36V32.487C29.313,30.787 33.127,25.84 33.127,20C33.127,12.753 27.247,6.873 20,6.873Z"
+      android:fillColor="#FBFBFE"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M20,22.1C21.16,22.1 22.1,21.159 22.1,20C22.1,18.84 21.16,17.9 20,17.9C18.84,17.9 17.9,18.84 17.9,20C17.9,21.159 18.84,22.1 20,22.1Z"
+      android:fillColor="#FBFBFE"/>
+</vector>


=====================================
fenix/app/src/main/res/drawable/progress_gradient.xml
=====================================
@@ -12,16 +12,10 @@
     <item android:id="@android:id/progress">
         <scale android:scaleWidth="100%">
             <shape>
-                <corners
-                    android:bottomLeftRadius="0dp"
-                    android:bottomRightRadius="8dp"
-                    android:topLeftRadius="0dp"
-                    android:topRightRadius="8dp"/>
                 <gradient
-                    android:angle="45"
-                    android:centerColor="#F10366"
-                    android:endColor="#FF9100"
-                    android:startColor="#6173FF" />
+                    android:angle="0"
+                    android:endColor="#00DBDE"
+                    android:startColor="#FC00FF"/>
             </shape>
         </scale>
     </item>


=====================================
fenix/app/src/main/res/layout/fragment_tor_connection_assist.xml
=====================================
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?><!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/tor_bootstrap_background_gradient">
+
+    <ProgressBar
+        android:id="@+id/tor_bootstrap_progress_bar"
+        style="?android:attr/progressBarStyleHorizontal"
+        android:layout_width="match_parent"
+        android:layout_height="6dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <ImageView
+        android:id="@+id/settings_button"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_marginTop="26dp"
+        android:layout_marginEnd="20dp"
+        android:contentDescription="@string/settings"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/mozac_ic_settings" />
+
+    <ImageView
+        android:id="@+id/tor_connect_image"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_marginStart="24dp"
+        android:contentDescription="@string/tor_bootstrap_connect"
+        android:visibility="visible"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/tor_bootstrap_progress_bar"
+        app:layout_constraintVertical_bias="0.075"
+        app:srcCompat="@drawable/connect" />
+
+    <TextView
+        android:id="@+id/title_large_text_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="24dp"
+        android:layout_marginTop="24dp"
+        android:layout_marginEnd="24dp"
+        android:text="@string/connection_assist_tor_connect_title"
+        android:textColor="#FBFBFE"
+        android:textFontWeight="400"
+        android:textSize="22sp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tor_connect_image" />
+
+    <TextView
+        android:id="@+id/connect_to_tor_description"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="24dp"
+        android:layout_marginTop="16dp"
+        android:layout_marginEnd="24dp"
+        android:text="@string/preferences_tor_network_settings_explanation"
+        android:textColor="#FBFBFE"
+        android:textFontWeight="400"
+        android:textSize="14sp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0.0"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/title_large_text_view" />
+
+    <TextView
+        android:id="@+id/connect_automatically"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="24dp"
+        android:layout_marginTop="24dp"
+        android:text="@string/connection_assist_always_connect_automatically_toggle_description"
+        android:textColor="#FBFBFE"
+        android:textSize="14sp"
+        app:layout_constraintBottom_toBottomOf="@+id/quickstart_switch"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="@+id/quickstart_switch"
+        app:layout_constraintVertical_bias="1.25" />
+
+    <com.google.android.material.switchmaterial.SwitchMaterial
+        android:id="@+id/quickstart_switch"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="24dp"
+        android:layout_marginEnd="24dp"
+        android:layout_marginBottom="24dp"
+        android:enabled="false"
+        android:gravity="center"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/connect_to_tor_description"
+        app:layout_goneMarginEnd="6dp"
+        app:layout_goneMarginTop="9dp" />
+
+    <Button
+        android:id="@+id/tor_bootstrap_connect_button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="24dp"
+        android:layout_marginEnd="24dp"
+        android:layout_marginBottom="8dp"
+        android:background="@drawable/rounded_corners"
+        android:backgroundTint="@color/connect_button_purple"
+        android:maxWidth="312dp"
+        android:text="@string/tor_bootstrap_connect"
+        android:textAllCaps="false"
+        android:textColor="#FBFBFE"
+        android:textFontWeight="500"
+        android:textSize="14sp"
+        android:textStyle="bold"
+        app:layout_constraintBottom_toTopOf="@id/tor_bootstrap_network_settings_button"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0.0"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/quickstart_switch"
+        app:layout_constraintVertical_bias="1" />
+
+
+    <Button
+        android:id="@+id/tor_bootstrap_network_settings_button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="24dp"
+        android:layout_marginEnd="24dp"
+        android:layout_marginBottom="24dp"
+        android:background="@drawable/rounded_corners"
+        android:backgroundTint="@color/configure_connection_button_white"
+        android:maxWidth="312dp"
+        android:text="@string/connection_assist_configure_connection_button"
+        android:textAllCaps="false"
+        android:textColor="#15141A"
+        android:textFontWeight="500"
+        android:textSize="14sp"
+        android:textStyle="bold"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>


=====================================
fenix/app/src/main/res/layout/tor_bootstrap_connect.xml
=====================================
@@ -44,42 +44,6 @@
         android:layout_height="wrap_content"
         android:layout_above="@id/tor_bootstrap_connect_button" />
 
-    <TextView
-        android:id="@+id/quick_start_label"
-        android:visibility="gone"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/library_item_icon_margin_horizontal"
-        android:layout_marginEnd="@dimen/library_item_icon_margin_horizontal"
-        android:layout_above="@id/tor_bootstrap_quick_start_description"
-        android:layout_toEndOf="@id/quick_start_toggle"
-        android:paddingStart="8dp"
-        android:paddingEnd="8dp"
-        android:clickable="false"
-        android:textAppearance="@style/ListItemTextStyle"
-        android:textColor="#EEEEEE"
-        android:text="@string/tor_bootstrap_quick_start_label"
-        android:textSize="18sp" />
-
-    <TextView
-        android:id="@+id/tor_bootstrap_quick_start_description"
-        android:visibility="gone"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/library_item_icon_margin_horizontal"
-        android:layout_marginEnd="@dimen/library_item_icon_margin_horizontal"
-        android:paddingStart="8dp"
-        android:paddingEnd="8dp"
-        android:clickable="false"
-        android:layout_marginBottom="20dp"
-        android:textAppearance="@style/ListItemTextStyle"
-        android:layout_toEndOf="@id/quick_start_toggle"
-        android:layout_above="@id/tor_bootstrap_connect_button"
-        android:textColor="#FFBBBBBB"
-        android:text="@string/tor_bootstrap_quick_start_disabled"
-        android:lines="3"
-        android:textSize="18sp" />
-
     <Button
         android:id="@+id/tor_bootstrap_connect_button"
         android:layout_width="wrap_content"


=====================================
fenix/app/src/main/res/layout/tor_network_settings_beta_connection_features.xml
=====================================
@@ -84,7 +84,6 @@
             android:background="?android:attr/selectableItemBackground"
             android:button="@null"
             android:drawablePadding="@dimen/radio_button_preference_drawable_padding"
-            android:enabled="false"
             android:paddingStart="@dimen/radio_button_preference_horizontal"
             android:paddingTop="@dimen/radio_button_preference_vertical"
             android:paddingEnd="@dimen/radio_button_preference_horizontal"


=====================================
fenix/app/src/main/res/navigation/nav_graph.xml
=====================================
@@ -277,6 +277,31 @@
             app:popExitAnim="@anim/slide_out_right" />
     </fragment>
 
+    <fragment
+        android:id="@+id/torConnectionAssistFragment"
+        android:name="org.mozilla.fenix.tor.TorConnectionAssistFragment"
+        tools:layout="@layout/fragment_home">
+        <action
+            android:id="@+id/action_home"
+            app:destination="@id/homeFragment"
+            app:popUpTo="@id/torConnectionAssistFragment"
+            app:popUpToInclusive="true" />
+        <action
+            android:id="@+id/action_torConnectionAssistFragment_to_SettingsFragment"
+            app:destination="@id/settingsFragment"
+            app:enterAnim="@anim/slide_in_right"
+            app:exitAnim="@anim/slide_out_left"
+            app:popEnterAnim="@anim/slide_in_left"
+            app:popExitAnim="@anim/slide_out_right" />
+        <action
+            android:id="@+id/action_torConnectionAssistFragment_to_TorNetworkSettings"
+            app:destination="@id/torNetworkSettingsFragment"
+            app:enterAnim="@anim/slide_in_right"
+            app:exitAnim="@anim/slide_out_left"
+            app:popEnterAnim="@anim/slide_in_left"
+            app:popExitAnim="@anim/slide_out_right" />
+    </fragment>
+
     <dialog
         android:id="@+id/homeOnboardingDialogFragment"
         android:name="org.mozilla.fenix.onboarding.HomeOnboardingDialogFragment" />
@@ -769,6 +794,13 @@
             app:exitAnim="@anim/slide_out_left"
             app:popEnterAnim="@anim/slide_in_left"
             app:popExitAnim="@anim/slide_out_right" />
+        <action
+            android:id="@+id/action_settingsFragment_to_TorConnectionAssistFragment"
+            app:destination="@id/torConnectionAssistFragment"
+            app:enterAnim="@anim/slide_in_right"
+            app:exitAnim="@anim/slide_out_left"
+            app:popEnterAnim="@anim/slide_in_left"
+            app:popExitAnim="@anim/slide_out_right" />
     </fragment>
     <dialog
         android:id="@+id/profilerStartDialogFragment"


=====================================
fenix/app/src/main/res/values/colors.xml
=====================================
@@ -340,4 +340,9 @@
 
     <!-- Material Design colors -->
     <color name="material_scrim_color">#52000000</color>
+
+    <!-- Connection Assist -->
+    <color name="connect_button_purple">#9059FF</color>
+    <color name="configure_connection_button_white">#E1E0E7</color>
+
 </resources>


=====================================
fenix/app/src/main/res/values/torbrowser_strings.xml
=====================================
@@ -75,4 +75,73 @@
     <!-- Onion location -->
     <string name="preferences_tor_prioritize_onions">Prioritize .onion sites</string>
 
+    <!-- Connection assist. -->
+    <string name="connection_assist_tor_connect_title">Connect to Tor</string>
+    <!-- Connection assist. -->
+    <string name="connection_assist_always_connect_automatically_toggle_description">Always connect automatically</string>
+    <!-- Connection assist. -->
+    <string name="connection_assist_configure_connection_button">Configure connection…</string>
+
+    <!-- Connection assist. -->
+    <string name="connection_assist_connecting_title">Establishing a connection…</string>
+
+    <!-- Connection assist. -->
+    <string name="connection_assist_internet_error_title">We can’t reach the internet</string>
+    <!-- Connection assist. %1$s is connection_assist_internet_error_learn_more-->
+    <string name="connection_assist_internet_error_description">This could be due to a connection issue rather than Tor being blocked. Check your internet connection, proxy, and firewall settings before trying again. %1$s</string>
+    <!-- Connection assist. -->
+    <string name="connection_assist_internet_error_learn_more">Learn more</string>
+    <!-- Connection assist. -->
+    <string name="connection_assist_internet_error_try_again">Try again</string>
+
+    <!-- Connection assist. -->
+    <string name="connection_assist_trying_again_waiting_title">Trying again…</string>
+
+    <!-- Connection assist. -->
+    <string name="connection_assist_cant_connect_to_tor_title">We can’t connect to Tor directly</string>
+    <!-- Connection assist. %1$s is connection_assist_try_a_bridge_learn_more-->
+    <string name="connection_assist_try_a_bridge_description">Try connecting via a bridge instead. By providing your location, we can look up the bridge that’s most likely to unblock the internet in your country or region. %1$s</string>
+    <!-- Connection assist. -->
+    <string name="connection_assist_unblock_the_internet_in_country_or_region">Unblock the internet in:</string>
+    <!-- Connection assist. -->
+    <string name="connection_assist_share_my_location_country_or_region">Share my location</string>
+    <!-- Connection assist. -->
+    <string name="connection_assist_try_a_bridge_button">Try a bridge</string>
+
+    <!-- Connection assist. %1$s is connection_assist_choose_a_bridge_manually_link-->
+    <string name="connection_assist_try_a_bridge_learn_more_description1">Tor Browser will need to establish a brief non-Tor connection to determine your location and look up a bridge. If you don’t want to do that, you can %1$s instead.</string>
+    <!-- Connection assist. -->
+    <string name="connection_assist_choose_a_bridge_manually_link">choose a bridge manually</string>
+    <!-- Connection assist. %s is the error code-->
+    <string name="connection_assist_try_a_bridge_learn_more_error_code">Error code: %s</string>
+
+    <!-- Connection assist. -->
+    <string name="connection_assist_trying_a_bridge_title">Trying a bridge…</string>
+
+    <!-- Connection assist. -->
+    <string name="connection_assist_location_error_title">We couldn’t find your location</string>
+    <!-- Connection assist. %1$s is connection_assist_find_bridge_location_description, %2$s is connection_assist_select_country_try_again, %3$s is connection_assist_location_error_learn_more_link-->
+    <string name="connection_assist_location_error_description" translatable="false">%1$s %2$s %3$s</string>
+    <string name="connection_assist_find_bridge_location_description">To find a bridge that can unblock your internet, we need to know where you’re connecting from.</string>
+    <string name="connection_assist_select_country_try_again">Select your country or region and try again.</string>
+    <!-- Connection assist. %1$s is connection_assist_find_bridge_location_description, %2$s is connection_assist_check_location_settings_try_again. %3$s is connection_assist_location_error_learn_more_link-->
+    <string name="connection_assist_location_error_last_try_description">%1$s %2$s %3$s</string>
+    <string name="connection_assist_check_location_settings_try_again">Please check your location settings are correct and try again.</string>
+
+    <string name="connection_assist_location_error_learn_more_link">Learn more</string>
+
+    <!-- Connection assist. -->
+    <string name="connection_assist_location_check_title">We’re still having trouble connecting</string>
+
+    <!-- Connection assist. -->
+    <string name="connection_assist_last_try_title">Trying one more time…</string>
+
+    <!-- Connection assist. -->
+    <string name="connection_assist_final_error_title">We weren’t able to connect automatically</string>
+    <!-- Connection assist. %1$s is connection_assist_final_error_troubleshoot_connection_link. %2$s is connection_assist_final_error_learn_more_link-->
+    <string name="connection_assist_final_error_description1">Despite our best efforts, we weren’t able to connect to Tor. We recommend %1$s and adding a bridge manually instead. %2$s</string>
+    <!-- Connection assist. -->
+    <string name="connection_assist_final_error_troubleshoot_connection_link">troubleshooting your connection</string>
+    <!-- Connection assist. -->
+    <string name="connection_assist_final_error_learn_more_link">Learn more</string>
 </resources>


=====================================
fenix/tools/tba-fetch-deps.sh
=====================================
@@ -14,7 +14,7 @@ fi
 
 onion_proxy_library="$(ls -1td "$TOR_BROWSER_BUILD/out/tor-onion-proxy-library/"tor-onion-proxy-library-* | head -1)"
 if [ -z "$onion_proxy_library" ]; then
-	echo "Cannot find Tor Onoin Proxy library artifacts!"
+	echo "Cannot find Tor Onion Proxy library artifacts!"
 	exit 2
 fi
 



View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/compare/16ff4ed5abb5b99da69dd1a293d8d97aafa3352b...7c1cc53976affe4388e32e75dfce3a7a64eea915

-- 
View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/compare/16ff4ed5abb5b99da69dd1a293d8d97aafa3352b...7c1cc53976affe4388e32e75dfce3a7a64eea915
You're receiving this email because of your account on gitlab.torproject.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.torproject.org/pipermail/tbb-commits/attachments/20240222/009c0f63/attachment-0001.htm>


More information about the tbb-commits mailing list