[tor-commits] [Git][tpo/applications/firefox-android][firefox-android-115.2.1-13.5-1] fixup! Add Tor integration and UI

Dan Ballard (@dan) git at gitlab.torproject.org
Wed Mar 27 20:32:55 UTC 2024



Dan Ballard pushed to branch firefox-android-115.2.1-13.5-1 at The Tor Project / Applications / firefox-android


Commits:
dd7c3469 by Dan Ballard at 2024-03-27T13:30:32-07:00
fixup! Add Tor integration and UI

Bug 41187: Change settings moving Network Preferences to Connections menu and readd tor logs

- - - - -


13 changed files:

- fenix/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt
- − fenix/app/src/main/java/org/mozilla/fenix/settings/TorNetworkSettingsFragment.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapFragment.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistFragment.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/TorLogsFragment.kt
- fenix/app/src/main/res/navigation/nav_graph.xml
- fenix/app/src/main/res/values/preference_keys.xml
- fenix/app/src/main/res/values/torbrowser_strings.xml
- fenix/app/src/main/res/xml/preferences.xml
- − fenix/app/src/main/res/xml/tor_network_settings_preferences.xml


Changes:

=====================================
fenix/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt
=====================================
@@ -61,6 +61,8 @@ import org.mozilla.fenix.ext.showToolbar
 import org.mozilla.fenix.nimbus.FxNimbus
 import org.mozilla.fenix.perf.ProfilerViewModel
 import org.mozilla.fenix.settings.account.AccountUiView
+import org.mozilla.fenix.tor.TorBridgeTransportConfig
+import org.mozilla.fenix.tor.TorEvents
 import org.mozilla.fenix.utils.Settings
 import kotlin.system.exitProcess
 
@@ -155,6 +157,8 @@ class SettingsFragment : PreferenceFragmentCompat() {
     }
 
     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+        //setPreferencesFromResource(R.xml.tor_network_settings_preferences, rootKey)
+        //setupConnectionPreferences()
         setPreferencesFromResource(R.xml.preferences, rootKey)
     }
 
@@ -178,7 +182,10 @@ class SettingsFragment : PreferenceFragmentCompat() {
         update(shouldUpdateAccountUIState = !creatingFragment)
 
         requireView().findViewById<RecyclerView>(R.id.recycler_view)
-            ?.hideInitialScrollBar(viewLifecycleOwner.lifecycleScope)
+            .also {
+                it?.hideInitialScrollBar(viewLifecycleOwner.lifecycleScope)
+                it?.disableHidingAnimation()
+            }
 
         if (args.preferenceToScrollTo != null) {
             scrollToPreference(args.preferenceToScrollTo)
@@ -277,9 +284,6 @@ class SettingsFragment : PreferenceFragmentCompat() {
             resources.getString(R.string.pref_key_search_settings) -> {
                 SettingsFragmentDirections.actionSettingsFragmentToSearchEngineFragment()
             }
-            resources.getString(R.string.pref_key_tor_network_settings) -> {
-                SettingsFragmentDirections.actionSettingsFragmentToTorNetworkSettingsFragment()
-            }
             resources.getString(R.string.pref_key_tor_security_level_settings) -> {
                 SettingsFragmentDirections.actionSettingsFragmentToTorSecurityLevelFragment()
             }
@@ -523,6 +527,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
             preferenceStartProfiler?.isVisible = showSecretDebugMenuThisSession &&
                 (requireContext().components.core.engine.profiler?.isProfilerActive() != null)
         }
+
         setupCookieBannerPreference()
         setupAmoCollectionOverridePreference(requireContext().settings())
         setupGeckoLogsPreference(requireContext().settings())
@@ -532,6 +537,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
         setupSearchPreference()
         setupHomepagePreference()
         setupTrackingProtectionPreference()
+        setupConnectionPreferences()
     }
 
     /**
@@ -566,6 +572,10 @@ class SettingsFragment : PreferenceFragmentCompat() {
         }
     }
 
+    private fun RecyclerView.disableHidingAnimation() {
+        this.setItemAnimator(null)
+        this.setLayoutAnimation(null)
+    }
     private fun updateFxAAllowDomesticChinaServerMenu() {
         val settings = requireContext().settings()
         val preferenceAllowDomesticChinaServer =
@@ -705,6 +715,39 @@ class SettingsFragment : PreferenceFragmentCompat() {
         }
     }
 
+    internal fun setupConnectionPreferences() {
+        // will be needed for phase2
+        //val torController = requireContext().components.torController
+
+        requirePreference<Preference>(R.string.pref_key_tor_network_settings_bridge_config).apply {
+            setOnPreferenceClickListener {
+                val directions =
+                    SettingsFragmentDirections
+                        .actionSettingsFragmentToTorBridgeConfigFragment()
+                requireView().findNavController().navigate(directions)
+                true
+            }
+        }
+
+        requirePreference<Preference>(R.string.pref_key_use_new_bootstrap).apply {
+            setOnPreferenceClickListener {
+                val directions =
+                    SettingsFragmentDirections.actionSettingsFragmentToBetaConnectionFeaturesFragment()
+                requireView().findNavController().navigate(directions)
+                true
+            }
+        }
+
+        requirePreference<Preference>(R.string.pref_key_tor_logs).apply {
+            setOnPreferenceClickListener {
+                val directions =
+                    SettingsFragmentDirections.actionSettingsFragmentToTorLogsFragment()
+                requireView().findNavController().navigate(directions)
+                true
+            }
+        }
+    }
+
     @VisibleForTesting
     internal fun setupCookieBannerPreference() {
         with(requirePreference<Preference>(R.string.pref_key_cookie_banner_settings)) {


=====================================
fenix/app/src/main/java/org/mozilla/fenix/settings/TorNetworkSettingsFragment.kt deleted
=====================================
@@ -1,172 +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.settings
-
-import android.os.Bundle
-import androidx.navigation.findNavController
-import androidx.preference.Preference
-import androidx.preference.PreferenceFragmentCompat
-import org.mozilla.fenix.R
-import org.mozilla.fenix.ext.components
-import org.mozilla.fenix.ext.nav
-import org.mozilla.fenix.ext.settings
-import org.mozilla.fenix.ext.showToolbar
-import org.mozilla.fenix.tor.TorBridgeTransportConfig
-import org.mozilla.fenix.tor.TorEvents
-
-/**
- * Lets the user configure Tor network connection settings
- */
-class TorNetworkSettingsFragment : PreferenceFragmentCompat(), TorEvents {
-    override fun onResume() {
-        super.onResume()
-
-        val torController = requireContext().components.torController
-
-        torController.registerTorListener(this)
-
-        showToolbar(getString(R.string.preferences_tor_network_settings))
-
-        val yesString = getString(R.string.preferences_tor_network_settings_yes)
-        val noString = getString(R.string.preferences_tor_network_settings_no)
-
-        requirePreference<Preference>(R.string.pref_key_tor_network_settings_bridge_config).apply {
-            setOnPreferenceClickListener {
-                val directions =
-                    TorNetworkSettingsFragmentDirections
-                        .actionTorNetworkSettingsFragmentToTorBridgeConfigFragment()
-                requireView().findNavController().navigate(directions)
-                true
-            }
-
-            if (torController.bridgesEnabled) {
-                if (torController.bridgeTransport == TorBridgeTransportConfig.USER_PROVIDED) {
-                    summary =
-                        getString(
-                            R
-                            .string
-                            .preferences_tor_network_settings_bridge_config_description_user_provided_enabled
-                        )
-                } else {
-                    summary =
-                        getString(
-                            R
-                            .string
-                            .preferences_tor_network_settings_bridge_config_description_builtin_transport_enabled
-                        )
-                }
-            } else {
-                summary =
-                    getString(
-                        R
-                        .string
-                        .preferences_tor_network_settings_bridge_config_description
-                    )
-            }
-        }
-
-        requirePreference<Preference>(R.string.pref_key_tor_network_settings_bridges_enabled).apply {
-            val formatStringRes = R.string.preferences_tor_network_settings_bridges_enabled
-            title = if (torController.bridgesEnabled) {
-                getString(formatStringRes, yesString)
-            } else {
-                getString(formatStringRes, noString)
-            }
-        }
-
-        requirePreference<Preference>(R.string.pref_key_use_new_bootstrap).apply {
-            setOnPreferenceClickListener {
-                val directions =
-                    TorNetworkSettingsFragmentDirections.actionTorNetworkSettingsFragmentToBetaConnectionFeaturesFragment()
-                requireView().findNavController().navigate(directions)
-                true
-            }
-        }
-
-        setStatus()
-    }
-
-    private fun setStatus() {
-        val torController = requireContext().components.torController
-        val yesString = getString(R.string.preferences_tor_network_settings_yes)
-        val noString = getString(R.string.preferences_tor_network_settings_no)
-
-        requirePreference<Preference>(R.string.pref_key_tor_network_settings_tor_ready).apply {
-            val formatStringRes = R.string.preferences_tor_network_settings_tor_ready
-            @SuppressWarnings("ComplexCondition")
-            title = if (!torController.isStarting &&
-                torController.isConnected &&
-                torController.isBootstrapped &&
-                !torController.isRestarting) {
-                getString(formatStringRes, yesString)
-            } else {
-                getString(formatStringRes, noString)
-            }
-        }
-
-        requirePreference<Preference>(R.string.pref_key_tor_network_settings_state).apply {
-            val formatStringRes = R.string.preferences_tor_network_settings_state
-
-            title = if (torController.isRestarting) {
-                getString(formatStringRes,
-                    getString(
-                        R
-                        .string
-                        .preferences_tor_network_settings_restarting
-                    )
-                )
-            } else if (torController.isStarting) {
-                getString(formatStringRes,
-                    getString(
-                        R
-                        .string
-                        .preferences_tor_network_settings_connecting
-                    )
-                )
-            } else if (torController.isConnected) {
-                getString(formatStringRes,
-                    getString(
-                        R
-                        .string
-                        .preferences_tor_network_settings_connected
-                    )
-                )
-            } else {
-                getString(formatStringRes,
-                    getString(
-                        R
-                        .string
-                        .preferences_tor_network_settings_disconnected
-                    )
-                )
-            }
-        }
-    }
-
-    override fun onStop() {
-        super.onStop()
-        requireContext().components.torController.unregisterTorListener(this)
-    }
-
-    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
-        setPreferencesFromResource(R.xml.tor_network_settings_preferences, rootKey)
-    }
-
-    @SuppressWarnings("EmptyFunctionBlock")
-    override fun onTorConnecting() {
-    }
-
-    @SuppressWarnings("EmptyFunctionBlock")
-    override fun onTorConnected() {
-    }
-
-    @SuppressWarnings("EmptyFunctionBlock")
-    override fun onTorStopped() {
-    }
-
-    override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) {
-        setStatus()
-    }
-}


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorBootstrapFragment.kt
=====================================
@@ -19,6 +19,7 @@ import org.mozilla.fenix.tor.interactor.TorBootstrapInteractor
 import androidx.navigation.fragment.findNavController
 import com.google.android.material.appbar.AppBarLayout
 import org.mozilla.fenix.HomeActivity
+import org.mozilla.fenix.R
 import org.mozilla.fenix.ext.components
 import org.mozilla.fenix.ext.hideToolbar
 import org.mozilla.fenix.ext.settings
@@ -182,7 +183,9 @@ class TorBootstrapFragment : Fragment() {
 
     private fun openTorNetworkSettings() {
         val directions =
-            TorBootstrapFragmentDirections.actionTorbootstrapFragmentToTorNetworkSettingsFragment()
+            TorBootstrapFragmentDirections.actionTorbootstrapFragmentToSettingsFragment(
+                requireContext().getString(R.string.pref_key_connection)
+            )
         findNavController().navigate(directions)
     }
 


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistFragment.kt
=====================================
@@ -147,7 +147,7 @@ class TorConnectionAssistFragment : Fragment() {
             getString(R.string.connection_assist_configure_connection_button)
         binding.torBootstrapButton2.setOnClickListener {
             viewModel.cancelTorBootstrap()
-            openTorNetworkSettings()
+            openTorConnectionSettings()
         }
     }
 
@@ -235,7 +235,7 @@ class TorConnectionAssistFragment : Fragment() {
         binding.torBootstrapButton2.text =
             getString(R.string.connection_assist_configure_connection_button)
         binding.torBootstrapButton2.setOnClickListener {
-            openTorNetworkSettings()
+            openTorConnectionSettings()
         }
     }
 
@@ -376,9 +376,11 @@ class TorConnectionAssistFragment : Fragment() {
         )
     }
 
-    private fun openTorNetworkSettings() {
+    private fun openTorConnectionSettings() {
         findNavController().navigate(
-            TorConnectionAssistFragmentDirections.actionTorConnectionAssistFragmentToTorNetworkSettings(),
+            TorConnectionAssistFragmentDirections.actionTorConnectionAssistFragmentToSettingsFragment(
+                requireContext().getString(R.string.pref_key_connection)
+            ),
         )
     }
 }


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt
=====================================
@@ -17,6 +17,10 @@ class TorError(
     var details: String
 ) { }
 
+interface TorLogs {
+    fun onLog(type: String?, message: String?)
+}
+
 internal enum class TorStatus(val status: String) {
     OFF("OFF"),
     STARTING("STARTING"),
@@ -68,6 +72,9 @@ interface TorController: TorEvents {
     fun registerTorListener(l: TorEvents)
     fun unregisterTorListener(l: TorEvents)
 
+    fun registerTorLogListener(l: TorLogs)
+    fun unregisterTorLogListener(l: TorLogs)
+
     fun initiateTorBootstrap(lifecycleScope: LifecycleCoroutineScope? = null, withDebugLogging: Boolean = false)
     fun stopTor()
     fun setTorStopped()


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt
=====================================
@@ -8,6 +8,7 @@ import mozilla.components.browser.engine.gecko.GeckoEngine
 import org.mozilla.fenix.ext.components
 import org.mozilla.geckoview.TorIntegrationAndroid
 import org.mozilla.geckoview.TorIntegrationAndroid.BootstrapStateChangeListener
+import org.mozilla.geckoview.TorIntegrationAndroid.TorLogListener
 import org.mozilla.geckoview.TorSettings
 import org.mozilla.geckoview.TorSettings.BridgeBuiltinType
 import org.mozilla.geckoview.TorSettings.BridgeSource
@@ -46,11 +47,12 @@ internal enum class TorConnectState(val state: String) {
 
 class TorControllerGV(
     private val context: Context,
-) : TorController, TorEvents, BootstrapStateChangeListener {
+) : TorController, TorEvents, BootstrapStateChangeListener, TorLogListener {
 
     private val TAG = "TorControllerGV"
 
     private var torListeners = mutableListOf<TorEvents>()
+    private var torLogListeners = mutableListOf<TorLogs>()
 
     internal var lastKnownStatus = TorConnectState.Initial
     internal var lastKnownError: TorError? = null
@@ -146,10 +148,12 @@ class TorControllerGV(
 
     override fun start() {
         getTorIntegration().registerBootstrapStateChangeListener(this)
+        getTorIntegration().registerLogListener(this)
     }
 
     override fun stop() {
         getTorIntegration().unregisterBootstrapStateChangeListener(this)
+        getTorIntegration().unregisterLogListener(this)
     }
 
     // TorEvents
@@ -180,6 +184,13 @@ class TorControllerGV(
         }
     }
 
+    override fun onLog(type: String?, message: String?) {
+        synchronized(torLogListeners) {
+            entries.add(Pair(type, message))
+            torLogListeners.toList().forEach { it.onLog(type, message) }
+        }
+    }
+
     override fun registerTorListener(l: TorEvents) {
         synchronized(torListeners) {
             if (torListeners.contains(l)) {
@@ -198,6 +209,23 @@ class TorControllerGV(
         }
     }
 
+    override fun registerTorLogListener(l: TorLogs) {
+        synchronized(torLogListeners) {
+            if (torLogListeners.contains(l)) {
+                return
+            }
+            torLogListeners.add(l)
+        }
+    }
+    override fun unregisterTorLogListener(l: TorLogs) {
+        synchronized(torLogListeners) {
+            if (!torLogListeners.contains(l)) {
+                return
+            }
+            torLogListeners.remove(l)
+        }
+    }
+
     override fun initiateTorBootstrap(
         lifecycleScope: LifecycleCoroutineScope?,
         withDebugLogging: Boolean,
@@ -284,7 +312,6 @@ class TorControllerGV(
             onTorConnecting()
 
         }
-        entries.add(Pair(status, lastKnownStatus.toTorStatus().status))
         onTorStatusUpdate(status, lastKnownStatus.toTorStatus().status, progress)
     }
 


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerTAS.kt
=====================================
@@ -211,6 +211,9 @@ class TorControllerTAS (private val context: Context): TorController {
         }
     }
 
+    override fun registerTorLogListener(l: TorLogs) {}
+    override fun unregisterTorLogListener(l: TorLogs) {}
+
     private fun handlePendingRegistrationChanges() {
         pendingRegisterChangeList.forEach {
             if (it.second) {


=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorLogsFragment.kt
=====================================
@@ -0,0 +1,79 @@
+package org.mozilla.fenix.tor
+
+import android.os.Bundle
+import android.text.method.ScrollingMovementMethod
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import org.mozilla.fenix.R
+import org.mozilla.fenix.components.Components
+import org.mozilla.fenix.databinding.FragmentHomeBinding
+import org.mozilla.fenix.databinding.FragmentTorConnectionAssistBinding
+import org.mozilla.fenix.databinding.TorBootstrapLoggerBinding
+import org.mozilla.fenix.databinding.TorNetworkSettingsBetaConnectionFeaturesBinding
+import org.mozilla.fenix.ext.components
+import org.mozilla.fenix.ext.requireComponents
+import org.mozilla.fenix.tor.view.TorBootstrapLoggerViewHolder
+
+class TorLogsFragment(): Fragment(), TorLogs {
+
+    private var entries = mutableListOf<String>()
+    internal var _binding: TorBootstrapLoggerBinding? = null
+    private val binding get() = _binding!!
+
+    private var _components: Components? = null
+    private val components get() = _components!!
+
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?,
+    ): View {
+        _binding = TorBootstrapLoggerBinding.inflate(inflater)
+        _components = requireComponents
+
+        components.torController.registerTorLogListener(this)
+
+        val currentEntries = components.torController.logEntries
+            .filter { it.second != null }
+            .filter { !(it.second!!.startsWith("Circuit") && it.first == "ON") }
+            // Keep synchronized with format in onTorStatusUpdate
+            .flatMap { listOf("(${it.first}) '${it.second}'") }
+        val entriesLen = currentEntries.size
+        val subListOffset = if (entriesLen > TorBootstrapLoggerViewHolder.MAX_NEW_ENTRIES) TorBootstrapLoggerViewHolder.MAX_NEW_ENTRIES else entriesLen
+        entries = currentEntries.subList((entriesLen - subListOffset), entriesLen) as MutableList<String>
+        val initLog = "---------------" + getString(R.string.tor_initializing_log) + "---------------"
+        entries.add(0, initLog)
+
+        with(binding.torBootstrapLogEntries) {
+            movementMethod = ScrollingMovementMethod()
+            text = formatLogEntries(entries)
+        }
+
+
+        return binding.root
+    }
+
+    // TODO on destroy unregiuster
+
+    private fun formatLogEntries(entries: List<String>) = entries.joinToString("\n")
+
+    override fun onLog(type: String?, message: String?) {
+        if (message == null || type == null) return
+        if (type == "ON" && type.startsWith("Circuit")) return
+
+        if (entries.size > TorBootstrapLoggerViewHolder.MAX_LINES) {
+            entries = entries.drop(1) as MutableList<String>
+        }
+        entries.add("($type) '$message'")
+
+        binding.torBootstrapLogEntries.text = formatLogEntries(entries)
+    }
+
+    override fun onStop() {
+        super.onStop()
+        components.torController.unregisterTorLogListener(this)
+    }
+
+}


=====================================
fenix/app/src/main/res/navigation/nav_graph.xml
=====================================
@@ -239,13 +239,6 @@
             android:name="scrollToCollection"
             android:defaultValue="false"
             app:argType="boolean" />
-        <action
-            android:id="@+id/action_homeFragment_to_torNetworkSettingsFragment"
-            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>
 
     <fragment
@@ -269,12 +262,13 @@
             app:popUpTo="@id/torbootstrapFragment"
             app:popUpToInclusive="true" />
         <action
-            android:id="@+id/action_torbootstrapFragment_to_torNetworkSettingsFragment"
-            app:destination="@id/torNetworkSettingsFragment"
+            android:id="@+id/action_torbootstrapFragment_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" />
+
     </fragment>
 
     <fragment
@@ -294,8 +288,8 @@
             app:popEnterAnim="@anim/slide_in_left"
             app:popExitAnim="@anim/slide_out_right" />
         <action
-            android:id="@+id/action_torConnectionAssistFragment_to_TorNetworkSettings"
-            app:destination="@id/torNetworkSettingsFragment"
+            android:id="@+id/action_torConnectionAssistFragment_to_TorConnectionSettings"
+            app:destination="@id/settingsFragment"
             app:enterAnim="@anim/slide_in_right"
             app:exitAnim="@anim/slide_out_left"
             app:popEnterAnim="@anim/slide_in_left"
@@ -702,8 +696,22 @@
             app:popEnterAnim="@anim/slide_in_left"
             app:popExitAnim="@anim/slide_out_right" />
         <action
-            android:id="@+id/action_settingsFragment_to_torNetworkSettingsFragment"
-            app:destination="@id/torNetworkSettingsFragment"
+            android:id="@+id/action_settingsFragment_to_torBridgeConfigFragment"
+            app:destination="@id/torBridgeConfigFragment"
+            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_settingsFragment_to_torLogsFragment"
+            app:destination="@+id/torLogsFragment"
+            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_settingsFragment_to_BetaConnectionFeaturesFragment"
+            app:destination="@+id/torBetaConnectionFeaturesFragment"
             app:enterAnim="@anim/slide_in_right"
             app:exitAnim="@anim/slide_out_left"
             app:popEnterAnim="@anim/slide_in_left"
@@ -965,24 +973,6 @@
         android:id="@+id/sponsoredStoriesSettings"
         android:name="org.mozilla.fenix.settings.SponsoredStoriesSettingsFragment"
         android:label="@string/preferences_debug_settings_custom_sponsored_stories_parameters" />
-    <fragment
-        android:id="@+id/torNetworkSettingsFragment"
-        android:name="org.mozilla.fenix.settings.TorNetworkSettingsFragment">
-        <action
-            android:id="@+id/action_torNetworkSettingsFragment_to_torBridgeConfigFragment"
-            app:destination="@id/torBridgeConfigFragment"
-            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_torNetworkSettingsFragment_to_BetaConnectionFeaturesFragment"
-            app:destination="@+id/torBetaConnectionFeaturesFragment"
-            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>
     <fragment
         android:id="@+id/torBridgeConfigFragment"
         android:name="org.mozilla.fenix.settings.TorBridgeConfigFragment"
@@ -993,6 +983,11 @@
         android:name="org.mozilla.fenix.tor.TorBetaConnectionFeaturesFragment"
         android:label="Enable beta connection features"
         tools:layout="@layout/tor_network_settings_beta_connection_features" />
+    <fragment
+        android:id="@+id/torLogsFragment"
+        android:name="org.mozilla.fenix.tor.TorLogsFragment"
+        android:label="Tor Logs"
+        tools:layout="@layout/tor_bootstrap_logger" />
 
     <fragment
         android:id="@+id/trackingProtectionFragment"


=====================================
fenix/app/src/main/res/values/preference_keys.xml
=====================================
@@ -14,6 +14,8 @@
     <string name="pref_key_accessibility" translatable="false">pref_key_accessibility</string>
     <string name="pref_key_accessibility_auto_size" translatable="false">pref_key_accessibility_auto_size</string>
     <string name="pref_key_accessibility_font_scale" translatable="false">pref_key_accessibility_font_scale</string>
+    <string name="pref_key_privacy" translatable="false">pref_key_privacy</string>
+    <string name="pref_key_connection" translatable="false">pref_key_connection</string>
     <string name="pref_key_accessibility_force_enable_zoom" translatable="false">pref_key_accessibility_force_enable_zoom</string>
     <string name="pref_key_advanced" translatable="false">pref_key_advanced</string>
     <string name="pref_key_language" translatable="false">pref_key_language</string>
@@ -373,10 +375,10 @@
     <string name="pref_key_tor_security_level_safer_option" translatable="false">pref_key_tor_security_level_safer_option</string>
     <string name="pref_key_tor_security_level_safest_option" translatable="false">pref_key_tor_security_level_safest_option</string>
 
-    <string name="pref_key_tor_network_settings" translatable="false">pref_key_tor_network_settings</string>
     <string name="pref_key_tor_network_settings_explanation" translatable="false">pref_key_tor_network_settings_explanation</string>
     <string name="pref_key_tor_network_settings_bridge_config" translatable="false">pref_key_tor_network_settings_bridge_config</string>
     <string name="pref_key_use_new_bootstrap" translatable="false">pref_key_use_new_bootstrap</string>
+    <string name="pref_key_tor_logs" translatable="false">pref_key_tor_logs</string>
     <string name="pref_key_use_new_bootstrap_with_android_native" translatable="false">pref_key_use_new_bootstrap_with_android_native</string>
     <string name="pref_key_use_new_bootstrap_with_html" translatable="false">pref_key_use_new_bootstrap_with_html</string>
     <string name="pref_key_tor_network_settings_bridge_config_explanation" translatable="false">pref_key_tor_network_settings_bridge_config_explanation</string>


=====================================
fenix/app/src/main/res/values/torbrowser_strings.xml
=====================================
@@ -31,6 +31,7 @@
 
     <string name="tor_explore_privately">Explore. Privately.</string>
 
+    <string name="preferences_tor_connection_settings_title">Connection</string>
     <string name="preferences_tor_network_settings">Tor Network</string>
     <string name="preferences_tor_network_settings_explanation">Tor Browser routes your traffic over the Tor Network, run by thousands of volunteers around the world.</string>
     <string name="preferences_tor_network_settings_bridge_config">Config Bridge</string>
@@ -57,6 +58,8 @@
     <string name="preferences_tor_network_settings_connected">Connected</string>
     <string name="preferences_tor_network_settings_restarting">Restarting</string>
     <string name="preferences_tor_network_settings_bridges_enabled">Bridges are enabled: %s</string>
+    <string name="preferences_tor_logs">Tor Logs</string>
+    <string name="preferences_tor_logs_description">View and copy your Tor logs</string>
 
     <!-- Preference title for security level settings -->
     <string name="preferences_tor_security_level_settings">Security Settings</string>


=====================================
fenix/app/src/main/res/xml/preferences.xml
=====================================
@@ -93,6 +93,7 @@
 
     <androidx.preference.PreferenceCategory
         android:title="@string/preferences_category_privacy_security"
+        android:key="@string/pref_key_privacy"
         android:layout="@layout/preference_category_no_icon_style">
 
         <androidx.preference.Preference
@@ -117,11 +118,6 @@
             android:title="@string/preferences_cookie_banner_reduction"
             app:isPreferenceVisible="false" />
 
-        <androidx.preference.Preference
-            android:key="@string/pref_key_tor_network_settings"
-            app:iconSpaceReserved="false"
-            android:title="@string/preferences_tor_network_settings" />
-
         <androidx.preference.Preference
             android:key="@string/pref_key_tracking_protection_settings"
             app:iconSpaceReserved="false"
@@ -156,6 +152,41 @@
 
     </androidx.preference.PreferenceCategory>
 
+    <!-- title="@string/preferences_category_advanced"
+         key="@string/pref_key_advanced"-->
+    <PreferenceCategory
+        android:title="@string/preferences_tor_connection_settings_title"
+        android:key="@string/pref_key_connection"
+        android:layout="@layout/preference_category_no_icon_style">
+
+        <Preference
+            android:key="@string/pref_key_tor_network_settings_explanation"
+            app:iconSpaceReserved="false"
+            android:title="@string/preferences_tor_network_settings_explanation" />
+
+        <Preference
+            android:key="@string/pref_key_tor_network_settings_bridge_config"
+            app:iconSpaceReserved="false"
+            android:title="@string/preferences_tor_network_settings_bridge_config"
+            android:summary="@string/preferences_tor_network_settings_bridge_config_description" />
+
+        <Preference
+            android:key="@string/pref_key_use_new_bootstrap"
+            app:iconSpaceReserved="false"
+            android:title="Enable beta connection features" />
+
+        <Preference
+            android:key="@string/pref_key_tor_logs"
+            app:iconSpaceReserved="false"
+            android:title="@string/preferences_tor_logs"
+            android:summary="@string/preferences_tor_logs_description" />
+
+        <!-- Auto connect -->
+
+        <!-- Tor Logs -->
+
+    </PreferenceCategory>
+
     <PreferenceCategory
         android:title="@string/preferences_category_advanced"
         android:key="@string/pref_key_advanced"


=====================================
fenix/app/src/main/res/xml/tor_network_settings_preferences.xml deleted
=====================================
@@ -1,35 +0,0 @@
-<?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.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto">
-    <Preference
-        android:key="@string/pref_key_tor_network_settings_explanation"
-        android:title="@string/preferences_tor_network_settings_explanation" />
-    <androidx.preference.PreferenceCategory
-        android:key="@string/pref_key_tor_network_settings_status"
-        android:title="@string/preferences_tor_network_settings_status"
-        app:iconSpaceReserved="false"
-        android:layout="@layout/preference_cat_style" >
-        <Preference
-            android:key="@string/pref_key_tor_network_settings_tor_ready"
-            android:title="@string/preferences_tor_network_settings_tor_ready" />
-        <Preference
-            android:key="@string/pref_key_tor_network_settings_state"
-            android:title="@string/preferences_tor_network_settings_state" />
-        <Preference
-            android:key="@string/pref_key_tor_network_settings_bridges_enabled"
-            android:title="@string/preferences_tor_network_settings_bridges_enabled" />
-    </androidx.preference.PreferenceCategory>
-    <Preference
-        android:icon="@drawable/ic_tor_config_bridge"
-        android:key="@string/pref_key_tor_network_settings_bridge_config"
-        android:title="@string/preferences_tor_network_settings_bridge_config"
-        android:summary="@string/preferences_tor_network_settings_bridge_config_description"
-        app:allowDividerAbove="true" />
-    <Preference
-        android:key="@string/pref_key_use_new_bootstrap"
-        android:title="Enable beta connection features"
-        app:allowDividerAbove="true" />
-
-</androidx.preference.PreferenceScreen>



View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/commit/dd7c3469dd3880592c6700ebcc2e40b4346eaa62

-- 
View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/commit/dd7c3469dd3880592c6700ebcc2e40b4346eaa62
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/tor-commits/attachments/20240327/0ae9d065/attachment-0001.htm>


More information about the tor-commits mailing list