Pier Angelo Vendrame pushed to branch firefox-android-115.2.1-13.5-1 at The Tor Project / Applications / firefox-android
Commits:
- 
48593938
by clairehurst at 2023-12-21T14:48:46-07:00
13 changed files:
- android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt
- android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/Settings.kt
- fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt
- fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt
- fenix/app/src/main/java/org/mozilla/fenix/components/Core.kt
- fenix/app/src/main/java/org/mozilla/fenix/settings/TorNetworkSettingsFragment.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/utils/Settings.kt
- + 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/preference_keys.xml
- fenix/app/src/main/res/xml/tor_network_settings_preferences.xml
Changes:
| ... | ... | @@ -799,6 +799,11 @@ class GeckoEngine( | 
| 799 | 799 |          override var prioritizeOnions: Boolean
 | 
| 800 | 800 |              get() = runtime.settings.prioritizeOnions
 | 
| 801 | 801 |              set(value) { runtime.settings.prioritizeOnions = value }
 | 
| 802 | +        override var useNewBootstrap: Boolean
 | |
| 803 | +            get() = runtime.settings.useNewBootstrap
 | |
| 804 | +            set(value) {
 | |
| 805 | +                runtime.settings.useNewBootstrap = value
 | |
| 806 | +            }
 | |
| 802 | 807 |      }.apply {
 | 
| 803 | 808 |          defaultSettings?.let {
 | 
| 804 | 809 |              this.javascriptEnabled = it.javascriptEnabled
 | 
| ... | ... | @@ -824,6 +829,7 @@ class GeckoEngine( | 
| 824 | 829 |              this.torSecurityLevel = it.torSecurityLevel
 | 
| 825 | 830 |              this.spoofEnglish = it.spoofEnglish
 | 
| 826 | 831 |              this.prioritizeOnions = it.prioritizeOnions
 | 
| 832 | +            this.useNewBootstrap = it.useNewBootstrap
 | |
| 827 | 833 |          }
 | 
| 828 | 834 |      }
 | 
| 829 | 835 | |
| ... | ... | @@ -929,6 +935,8 @@ class GeckoEngine( | 
| 929 | 935 |              unBlockedBySmartBlock = this.blockingData.any { it.unBlockedBySmartBlock() },
 | 
| 930 | 936 |          )
 | 
| 931 | 937 |      }
 | 
| 938 | + | |
| 939 | +    fun getTorIntegrationController() = runtime.getTorIntegrationController()
 | |
| 932 | 940 |  }
 | 
| 933 | 941 | |
| 934 | 942 |  internal fun ContentBlockingController.LogEntry.BlockingData.hasBlockedCookies(): Boolean {
 | 
| ... | ... | @@ -214,6 +214,8 @@ abstract class Settings { | 
| 214 | 214 |      open var spoofEnglish: Boolean by UnsupportedSetting()
 | 
| 215 | 215 | |
| 216 | 216 |      open var prioritizeOnions: Boolean by UnsupportedSetting()
 | 
| 217 | + | |
| 218 | +    open var useNewBootstrap: Boolean by UnsupportedSetting()
 | |
| 217 | 219 |  }
 | 
| 218 | 220 | |
| 219 | 221 |  /**
 | 
| ... | ... | @@ -259,6 +261,7 @@ data class DefaultSettings( | 
| 259 | 261 |      override var torSecurityLevel: Int = 4,
 | 
| 260 | 262 |      override var spoofEnglish: Boolean = false,
 | 
| 261 | 263 |      override var prioritizeOnions: Boolean = false,
 | 
| 264 | +    override var useNewBootstrap: Boolean = false,
 | |
| 262 | 265 |  ) : Settings()
 | 
| 263 | 266 | |
| 264 | 267 |  class UnsupportedSetting<T> {
 | 
| ... | ... | @@ -164,6 +164,11 @@ import org.mozilla.fenix.utils.Settings | 
| 164 | 164 |  import java.lang.ref.WeakReference
 | 
| 165 | 165 |  import java.util.Locale
 | 
| 166 | 166 | |
| 167 | +import androidx.navigation.fragment.findNavController
 | |
| 168 | +import mozilla.components.browser.engine.gecko.GeckoEngine
 | |
| 169 | +import mozilla.components.browser.state.selector.findCustomTab
 | |
| 170 | +import org.mozilla.geckoview.TorIntegrationAndroid
 | |
| 171 | + | |
| 167 | 172 |  /**
 | 
| 168 | 173 |   * The main activity of the application. The application is primarily a single Activity (this one)
 | 
| 169 | 174 |   * with fragments switching out to display different views. The most important views shown here are the:
 | 
| ... | ... | @@ -171,7 +176,7 @@ import java.util.Locale | 
| 171 | 176 |   * - browser screen
 | 
| 172 | 177 |   */
 | 
| 173 | 178 |  @SuppressWarnings("TooManyFunctions", "LargeClass", "LongParameterList", "LongMethod")
 | 
| 174 | -open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
 | |
| 179 | +open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, TorIntegrationAndroid.BootstrapStateChangeListener {
 | |
| 175 | 180 |      // DO NOT MOVE ANYTHING ABOVE THIS, GETTING INIT TIME IS CRITICAL
 | 
| 176 | 181 |      // we need to store startup timestamp for warm startup. we cant directly store
 | 
| 177 | 182 |      // inside AppStartupTelemetry since that class lives inside components and
 | 
| ... | ... | @@ -201,7 +206,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { | 
| 201 | 206 | |
| 202 | 207 |      private var inflater: LayoutInflater? = null
 | 
| 203 | 208 | |
| 204 | -    private val navHost by lazy {
 | |
| 209 | +    val navHost by lazy {
 | |
| 205 | 210 |          supportFragmentManager.findFragmentById(R.id.container) as NavHostFragment
 | 
| 206 | 211 |      }
 | 
| 207 | 212 | |
| ... | ... | @@ -396,6 +401,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { | 
| 396 | 401 | |
| 397 | 402 |          components.notificationsDelegate.bindToActivity(this)
 | 
| 398 | 403 | |
| 404 | +        val engine = components.core.engine
 | |
| 405 | +        if (engine is GeckoEngine) {
 | |
| 406 | +            val torIntegration = engine.getTorIntegrationController()
 | |
| 407 | +            torIntegration.registerBootstrapStateChangeListener(this)
 | |
| 408 | +        }
 | |
| 409 | + | |
| 399 | 410 |          StartupTimeline.onActivityCreateEndHome(this) // DO NOT MOVE ANYTHING BELOW HERE.
 | 
| 400 | 411 |      }
 | 
| 401 | 412 | |
| ... | ... | @@ -609,6 +620,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { | 
| 609 | 620 |              // underlying Application, as well.
 | 
| 610 | 621 |              (application as FenixApplication).terminate()
 | 
| 611 | 622 |          }
 | 
| 623 | + | |
| 624 | +        val engine = components.core.engine
 | |
| 625 | +        if (engine is GeckoEngine) {
 | |
| 626 | +            val torIntegration = engine.getTorIntegrationController()
 | |
| 627 | +            torIntegration.unregisterBootstrapStateChangeListener(this)
 | |
| 628 | +        }
 | |
| 612 | 629 |      }
 | 
| 613 | 630 | |
| 614 | 631 |      override fun onConfigurationChanged(newConfig: Configuration) {
 | 
| ... | ... | @@ -1163,7 +1180,20 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { | 
| 1163 | 1180 |      }
 | 
| 1164 | 1181 | |
| 1165 | 1182 |      open fun navigateToHome() {
 | 
| 1166 | -        navHost.navController.navigate(NavGraphDirections.actionStartupTorbootstrap())
 | |
| 1183 | +        if (settings().useNewBootstrap) {
 | |
| 1184 | +            if (settings().useNewBootstrapNativeUi) {
 | |
| 1185 | +                navHost.navController.navigate(NavGraphDirections.actionStartupTorConnectionAssist())
 | |
| 1186 | +            } else {
 | |
| 1187 | +                navHost.navController.navigate(NavGraphDirections.actionStartupHome())
 | |
| 1188 | +                openToBrowserAndLoad(
 | |
| 1189 | +                    searchTermOrURL = "about:torconnect",
 | |
| 1190 | +                    newTab = true,
 | |
| 1191 | +                    from = BrowserDirection.FromHome,
 | |
| 1192 | +                )
 | |
| 1193 | +            }
 | |
| 1194 | +        } else {
 | |
| 1195 | +            navHost.navController.navigate(NavGraphDirections.actionStartupTorbootstrap())
 | |
| 1196 | +        }
 | |
| 1167 | 1197 |      }
 | 
| 1168 | 1198 | |
| 1169 | 1199 |      override fun attachBaseContext(base: Context) {
 | 
| ... | ... | @@ -1341,4 +1371,15 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { | 
| 1341 | 1371 |          // telemetry purposes.
 | 
| 1342 | 1372 |          const val PWA_RECENTLY_USED_THRESHOLD = DateUtils.DAY_IN_MILLIS * 30L
 | 
| 1343 | 1373 |      }
 | 
| 1374 | + | |
| 1375 | +    override fun onBootstrapStateChange(state: String) = Unit
 | |
| 1376 | +    override fun onBootstrapProgress(progress: Double, status: String, hasWarnings: Boolean) = Unit
 | |
| 1377 | +    override fun onBootstrapComplete() {
 | |
| 1378 | +        components.useCases.tabsUseCases.removeAllTabs()
 | |
| 1379 | +        navHost.navController.navigate(NavGraphDirections.actionStartupHome())
 | |
| 1380 | +    }
 | |
| 1381 | +    override fun onBootstrapError(message: String, details: String) = Unit
 | |
| 1382 | +    override fun onSettingsRequested() {
 | |
| 1383 | +        navHost.navController.navigate(NavGraphDirections.actionGlobalSettingsFragment())
 | |
| 1384 | +    }
 | |
| 1344 | 1385 |  } | 
| ... | ... | @@ -1189,6 +1189,9 @@ abstract class BaseBrowserFragment : | 
| 1189 | 1189 |                  val context = requireContext()
 | 
| 1190 | 1190 |                  resumeDownloadDialogState(selectedTab.id, context.components.core.store, context, toolbarHeight)
 | 
| 1191 | 1191 |                  it.announceForAccessibility(selectedTab.toDisplayTitle())
 | 
| 1192 | +                if (getCurrentTab()?.content?.url == "about:torconnect") {
 | |
| 1193 | +                    browserToolbarView.view.visibility = View.GONE
 | |
| 1194 | +                }
 | |
| 1192 | 1195 |              }
 | 
| 1193 | 1196 |          } else {
 | 
| 1194 | 1197 |              view?.let { view -> initializeUI(view) }
 | 
| ... | ... | @@ -1206,6 +1209,24 @@ abstract class BaseBrowserFragment : | 
| 1206 | 1209 |              components.useCases.sessionUseCases.reload()
 | 
| 1207 | 1210 |          }
 | 
| 1208 | 1211 |          hideToolbar()
 | 
| 1212 | +        handleBetaHtmlTorConnect()
 | |
| 1213 | +    }
 | |
| 1214 | + | |
| 1215 | +    private fun handleBetaHtmlTorConnect() {
 | |
| 1216 | +        if (getCurrentTab()?.content?.url == "about:torconnect") {
 | |
| 1217 | +            if (!requireActivity().settings().useNewBootstrap) {
 | |
| 1218 | +                requireContext().components.useCases.tabsUseCases.removeAllTabs()
 | |
| 1219 | +                (requireActivity() as HomeActivity).navHost.navController.navigate(
 | |
| 1220 | +                    NavGraphDirections.actionStartupTorbootstrap(),
 | |
| 1221 | +                )
 | |
| 1222 | +            } else if (!requireActivity().settings().useNewBootstrapHtmlUi) {
 | |
| 1223 | +                requireContext().components.useCases.tabsUseCases.removeAllTabs()
 | |
| 1224 | +                (requireActivity() as HomeActivity).navigateToHome()
 | |
| 1225 | +            } else {
 | |
| 1226 | +                // This just makes it not flash (be visible for a split second) before handleTabSelected() hides it again
 | |
| 1227 | +                browserToolbarView.view.visibility = View.GONE
 | |
| 1228 | +            }
 | |
| 1229 | +        }
 | |
| 1209 | 1230 |      }
 | 
| 1210 | 1231 | |
| 1211 | 1232 |      @CallSuper
 | 
| ... | ... | @@ -146,6 +146,7 @@ class Core( | 
| 146 | 146 |              torSecurityLevel = context.settings().torSecurityLevel().intRepresentation,
 | 
| 147 | 147 |              spoofEnglish = context.settings().spoofEnglish,
 | 
| 148 | 148 |              prioritizeOnions = context.settings().prioritizeOnions,
 | 
| 149 | +            useNewBootstrap = context.settings().useNewBootstrap,
 | |
| 149 | 150 |          )
 | 
| 150 | 151 | |
| 151 | 152 |          GeckoEngine(
 | 
| ... | ... | @@ -76,6 +76,15 @@ class TorNetworkSettingsFragment : PreferenceFragmentCompat(), TorEvents { | 
| 76 | 76 |              }
 | 
| 77 | 77 |          }
 | 
| 78 | 78 | |
| 79 | +        requirePreference<Preference>(R.string.pref_key_use_new_bootstrap).apply {
 | |
| 80 | +            setOnPreferenceClickListener {
 | |
| 81 | +                val directions =
 | |
| 82 | +                    TorNetworkSettingsFragmentDirections.actionTorNetworkSettingsFragmentToBetaConnectionFeaturesFragment()
 | |
| 83 | +                requireView().findNavController().navigate(directions)
 | |
| 84 | +                true
 | |
| 85 | +            }
 | |
| 86 | +        }
 | |
| 87 | + | |
| 79 | 88 |          setStatus()
 | 
| 80 | 89 |      }
 | 
| 81 | 90 | 
| 1 | +/* This Source Code Form is subject to the terms of the Mozilla Public
 | |
| 2 | + * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
| 3 | + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 4 | + | |
| 5 | +package org.mozilla.fenix.tor
 | |
| 6 | + | |
| 7 | +import android.os.Bundle
 | |
| 8 | +import android.view.LayoutInflater
 | |
| 9 | +import android.view.View
 | |
| 10 | +import android.view.ViewGroup
 | |
| 11 | +import androidx.core.view.children
 | |
| 12 | +import androidx.fragment.app.Fragment
 | |
| 13 | +import org.mozilla.fenix.databinding.TorNetworkSettingsBetaConnectionFeaturesBinding
 | |
| 14 | +import org.mozilla.fenix.ext.components
 | |
| 15 | +import org.mozilla.fenix.ext.settings
 | |
| 16 | + | |
| 17 | +/**
 | |
| 18 | + * Lets the user customize beta connection features mode.
 | |
| 19 | + */
 | |
| 20 | +class TorBetaConnectionFeaturesFragment : Fragment() {
 | |
| 21 | +    override fun onCreateView(
 | |
| 22 | +        inflater: LayoutInflater,
 | |
| 23 | +        container: ViewGroup?,
 | |
| 24 | +        savedInstanceState: Bundle?,
 | |
| 25 | +    ): View {
 | |
| 26 | +        val binding = TorNetworkSettingsBetaConnectionFeaturesBinding.inflate(inflater)
 | |
| 27 | + | |
| 28 | +        binding.enableBetaConnectionFeaturesSwitch.run {
 | |
| 29 | +            isChecked = context.settings().useNewBootstrap
 | |
| 30 | +            setConnectionAssistUI(binding, isChecked)
 | |
| 31 | + | |
| 32 | +            setOnCheckedChangeListener { _, isConnectionAssistEnabled ->
 | |
| 33 | +                context.settings().useNewBootstrap = isConnectionAssistEnabled
 | |
| 34 | +                setConnectionAssistUI(binding, isConnectionAssistEnabled)
 | |
| 35 | +                updateEngineConnectionAssistMode()
 | |
| 36 | +            }
 | |
| 37 | +        }
 | |
| 38 | + | |
| 39 | +        // Since the beta connection features modes are in a RadioGroup we only need one listener to know of all their changes.
 | |
| 40 | +        binding.useNewBootstrapWithNativeUiRadioButton.setOnCheckedChangeListener { _, _ ->
 | |
| 41 | +            updateEngineConnectionAssistMode()
 | |
| 42 | +        }
 | |
| 43 | + | |
| 44 | +        return binding.root
 | |
| 45 | +    }
 | |
| 46 | + | |
| 47 | +    private fun setConnectionAssistUI(
 | |
| 48 | +        binding: TorNetworkSettingsBetaConnectionFeaturesBinding,
 | |
| 49 | +        isBetaConnectionAssistEnabled: Boolean,
 | |
| 50 | +    ) {
 | |
| 51 | +        if (!isBetaConnectionAssistEnabled) {
 | |
| 52 | +            binding.enableBetaConnectionFeaturesModes.apply {
 | |
| 53 | +                clearCheck()
 | |
| 54 | +                children.forEach { it.isEnabled = false }
 | |
| 55 | +            }
 | |
| 56 | +        } else {
 | |
| 57 | +            // Do not enable the native UI until it is actually available.
 | |
| 58 | +            // binding.enableBetaConnectionFeaturesModes.children.forEach { it.isEnabled = true }
 | |
| 59 | +            binding.useNewBootstrapWithHtmlUiRadioButton.isEnabled = true
 | |
| 60 | +            binding.useNewBootstrapWithNativeUiRadioButton.isEnabled = false
 | |
| 61 | +        }
 | |
| 62 | +    }
 | |
| 63 | + | |
| 64 | +    private fun updateEngineConnectionAssistMode() {
 | |
| 65 | +        requireContext().components.core.engine.settings.useNewBootstrap =
 | |
| 66 | +            requireContext().settings().useNewBootstrap
 | |
| 67 | +    }
 | |
| 68 | + | |
| 69 | +} | 
| ... | ... | @@ -20,8 +20,10 @@ import org.mozilla.fenix.tor.interactor.DefaultTorBootstrapInteractor | 
| 20 | 20 |  import org.mozilla.fenix.tor.interactor.TorBootstrapInteractor
 | 
| 21 | 21 |  import androidx.navigation.fragment.findNavController
 | 
| 22 | 22 |  import com.google.android.material.appbar.AppBarLayout
 | 
| 23 | +import org.mozilla.fenix.HomeActivity
 | |
| 23 | 24 |  import org.mozilla.fenix.ext.components
 | 
| 24 | 25 |  import org.mozilla.fenix.ext.hideToolbar
 | 
| 26 | +import org.mozilla.fenix.ext.settings
 | |
| 25 | 27 |  import org.mozilla.fenix.tor.controller.DefaultTorBootstrapController
 | 
| 26 | 28 |  import org.mozilla.fenix.tor.view.TorBootstrapView
 | 
| 27 | 29 | |
| ... | ... | @@ -169,6 +171,9 @@ class TorBootstrapFragment : Fragment() { | 
| 169 | 171 |          // triggered to cause an automatic update on warm start (no tab selection occurs). So we
 | 
| 170 | 172 |          // update it manually here.
 | 
| 171 | 173 |          requireComponents.useCases.sessionUseCases.updateLastAccess()
 | 
| 174 | +        if (requireContext().settings().useNewBootstrap){
 | |
| 175 | +            (requireActivity() as HomeActivity).navigateToHome()
 | |
| 176 | +        }
 | |
| 172 | 177 |      }
 | 
| 173 | 178 | |
| 174 | 179 |      private fun handleTorBootstrapConnect() {
 | 
| ... | ... | @@ -1859,4 +1859,19 @@ class Settings(private val appContext: Context) : PreferencesHolder { | 
| 1859 | 1859 |       * Indicates if the new Search settings UI is enabled.
 | 
| 1860 | 1860 |       */
 | 
| 1861 | 1861 |      var enableUnifiedSearchSettingsUI: Boolean = showUnifiedSearchFeature && FeatureFlags.unifiedSearchSettings
 | 
| 1862 | + | |
| 1863 | +    var useNewBootstrap by booleanPreference(
 | |
| 1864 | +        appContext.getPreferenceKey(R.string.pref_key_use_new_bootstrap),
 | |
| 1865 | +        default = false,
 | |
| 1866 | +    )
 | |
| 1867 | + | |
| 1868 | +    var useNewBootstrapNativeUi by booleanPreference(
 | |
| 1869 | +        appContext.getPreferenceKey(R.string.pref_key_use_new_bootstrap_with_android_native),
 | |
| 1870 | +        default = false,
 | |
| 1871 | +    )
 | |
| 1872 | + | |
| 1873 | +    var useNewBootstrapHtmlUi by booleanPreference(
 | |
| 1874 | +        appContext.getPreferenceKey(R.string.pref_key_use_new_bootstrap_with_html),
 | |
| 1875 | +        default = true
 | |
| 1876 | +    )
 | |
| 1862 | 1877 |  } | 
| 1 | +<?xml version="1.0" encoding="utf-8"?><!-- This Source Code Form is subject to the terms of the Mozilla Public
 | |
| 2 | +   - License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
| 3 | +   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 | |
| 4 | +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | |
| 5 | +    xmlns:app="http://schemas.android.com/apk/res-auto"
 | |
| 6 | +    android:layout_width="match_parent"
 | |
| 7 | +    android:layout_height="wrap_content">
 | |
| 8 | + | |
| 9 | +    <TextView
 | |
| 10 | +        android:id="@+id/enable_beta_connection_features_title"
 | |
| 11 | +        android:layout_width="0dp"
 | |
| 12 | +        android:layout_height="wrap_content"
 | |
| 13 | +        android:layout_marginStart="16dp"
 | |
| 14 | +        android:layout_marginTop="16dp"
 | |
| 15 | +        android:layout_marginBottom="2dp"
 | |
| 16 | +        android:clickable="false"
 | |
| 17 | +        android:text="Enable beta connection features"
 | |
| 18 | +        android:textAppearance="@style/ListItemTextStyle"
 | |
| 19 | +        android:textSize="16sp"
 | |
| 20 | +        app:layout_constraintBottom_toTopOf="@id/enable_beta_connection_features_summary"
 | |
| 21 | +        app:layout_constraintEnd_toStartOf="@id/enable_beta_connection_features_switch"
 | |
| 22 | +        app:layout_constraintStart_toStartOf="parent"
 | |
| 23 | +        app:layout_constraintTop_toTopOf="parent"
 | |
| 24 | +        app:lineHeight="24.sp" />
 | |
| 25 | + | |
| 26 | +    <TextView
 | |
| 27 | +        android:id="@+id/enable_beta_connection_features_summary"
 | |
| 28 | +        android:layout_width="0dp"
 | |
| 29 | +        android:layout_height="wrap_content"
 | |
| 30 | +        android:text="Help us test our new connection assist features which focuses on a streamlined connection with better integration with bridges"
 | |
| 31 | +        android:textColor="?attr/textSecondary"
 | |
| 32 | +        android:textColorLink="?attr/textSecondary"
 | |
| 33 | +        android:textSize="12sp"
 | |
| 34 | +        app:layout_constraintBottom_toTopOf="@id/enable_beta_connection_features_modes"
 | |
| 35 | +        app:layout_constraintEnd_toEndOf="@id/enable_beta_connection_features_title"
 | |
| 36 | +        app:layout_constraintStart_toStartOf="@id/enable_beta_connection_features_title"
 | |
| 37 | +        app:layout_constraintTop_toBottomOf="@id/enable_beta_connection_features_title"
 | |
| 38 | +        app:lineHeight="16.sp" />
 | |
| 39 | + | |
| 40 | +    <androidx.appcompat.widget.SwitchCompat
 | |
| 41 | +        android:id="@+id/enable_beta_connection_features_switch"
 | |
| 42 | +        android:layout_width="wrap_content"
 | |
| 43 | +        android:layout_height="wrap_content"
 | |
| 44 | +        android:minHeight="48dp"
 | |
| 45 | +        android:paddingStart="18dp"
 | |
| 46 | +        android:paddingEnd="18dp"
 | |
| 47 | +        android:textColor="@color/state_list_text_color"
 | |
| 48 | +        android:textOff="@string/studies_off"
 | |
| 49 | +        android:textOn="@string/studies_on"
 | |
| 50 | +        app:layout_constraintEnd_toEndOf="parent"
 | |
| 51 | +        app:layout_constraintTop_toTopOf="@id/enable_beta_connection_features_title" />
 | |
| 52 | + | |
| 53 | +    <RadioGroup
 | |
| 54 | +        android:id="@+id/enable_beta_connection_features_modes"
 | |
| 55 | +        android:layout_width="match_parent"
 | |
| 56 | +        android:layout_height="wrap_content"
 | |
| 57 | +        android:layout_marginTop="10dp"
 | |
| 58 | +        app:layout_constraintEnd_toEndOf="parent"
 | |
| 59 | +        app:layout_constraintStart_toStartOf="parent"
 | |
| 60 | +        app:layout_constraintTop_toBottomOf="@id/enable_beta_connection_features_summary">
 | |
| 61 | + | |
| 62 | +        <org.mozilla.fenix.settings.PreferenceBackedRadioButton
 | |
| 63 | +            android:id="@+id/use_new_bootstrap_with_html_ui_radio_button"
 | |
| 64 | +            android:layout_width="match_parent"
 | |
| 65 | +            android:layout_height="wrap_content"
 | |
| 66 | +            android:background="?android:attr/selectableItemBackground"
 | |
| 67 | +            android:button="@null"
 | |
| 68 | +            android:drawablePadding="@dimen/radio_button_preference_drawable_padding"
 | |
| 69 | +            android:paddingStart="@dimen/radio_button_preference_horizontal"
 | |
| 70 | +            android:paddingTop="@dimen/radio_button_preference_vertical"
 | |
| 71 | +            android:paddingEnd="@dimen/radio_button_preference_horizontal"
 | |
| 72 | +            android:paddingBottom="@dimen/radio_button_preference_vertical"
 | |
| 73 | +            android:text="HTML UI"
 | |
| 74 | +            android:textAppearance="?android:attr/textAppearanceListItem"
 | |
| 75 | +            android:textSize="16sp"
 | |
| 76 | +            app:drawableStartCompat="?android:attr/listChoiceIndicatorSingle"
 | |
| 77 | +            app:preferenceKey="@string/pref_key_use_new_bootstrap_with_html"
 | |
| 78 | +            app:preferenceKeyDefaultValue="true" />
 | |
| 79 | + | |
| 80 | +        <org.mozilla.fenix.settings.PreferenceBackedRadioButton
 | |
| 81 | +            android:id="@+id/use_new_bootstrap_with_native_ui_radio_button"
 | |
| 82 | +            android:layout_width="match_parent"
 | |
| 83 | +            android:layout_height="48dp"
 | |
| 84 | +            android:background="?android:attr/selectableItemBackground"
 | |
| 85 | +            android:button="@null"
 | |
| 86 | +            android:drawablePadding="@dimen/radio_button_preference_drawable_padding"
 | |
| 87 | +            android:enabled="false"
 | |
| 88 | +            android:paddingStart="@dimen/radio_button_preference_horizontal"
 | |
| 89 | +            android:paddingTop="@dimen/radio_button_preference_vertical"
 | |
| 90 | +            android:paddingEnd="@dimen/radio_button_preference_horizontal"
 | |
| 91 | +            android:paddingBottom="@dimen/radio_button_preference_vertical"
 | |
| 92 | +            android:text="Native Android UI"
 | |
| 93 | +            android:textAppearance="?android:attr/textAppearanceListItem"
 | |
| 94 | +            android:textSize="16sp"
 | |
| 95 | +            app:drawableStartCompat="?android:attr/listChoiceIndicatorSingle"
 | |
| 96 | +            app:preferenceKey="@string/pref_key_use_new_bootstrap_with_android_native"
 | |
| 97 | +            app:preferenceKeyDefaultValue="false" />
 | |
| 98 | +    </RadioGroup>
 | |
| 99 | + | |
| 100 | +</androidx.constraintlayout.widget.ConstraintLayout> | 
| ... | ... | @@ -27,6 +27,12 @@ | 
| 27 | 27 |          app:popUpTo="@id/startupFragment"
 | 
| 28 | 28 |          app:popUpToInclusive="true" />
 | 
| 29 | 29 | |
| 30 | +    <action
 | |
| 31 | +        android:id="@+id/action_startup_tor_connection_assist"
 | |
| 32 | +        app:destination="@+id/torConnectionAssistFragment"
 | |
| 33 | +        app:popUpTo="@id/startupFragment"
 | |
| 34 | +        app:popUpToInclusive="true" />
 | |
| 35 | + | |
| 30 | 36 |      <action
 | 
| 31 | 37 |          android:id="@+id/action_global_home"
 | 
| 32 | 38 |          app:destination="@id/homeFragment"
 | 
| ... | ... | @@ -941,12 +947,25 @@ | 
| 941 | 947 |              app:exitAnim="@anim/slide_out_left"
 | 
| 942 | 948 |              app:popEnterAnim="@anim/slide_in_left"
 | 
| 943 | 949 |              app:popExitAnim="@anim/slide_out_right" />
 | 
| 950 | +        <action
 | |
| 951 | +            android:id="@+id/action_torNetworkSettingsFragment_to_BetaConnectionFeaturesFragment"
 | |
| 952 | +            app:destination="@+id/torBetaConnectionFeaturesFragment"
 | |
| 953 | +            app:enterAnim="@anim/slide_in_right"
 | |
| 954 | +            app:exitAnim="@anim/slide_out_left"
 | |
| 955 | +            app:popEnterAnim="@anim/slide_in_left"
 | |
| 956 | +            app:popExitAnim="@anim/slide_out_right" />
 | |
| 944 | 957 |      </fragment>
 | 
| 945 | 958 |      <fragment
 | 
| 946 | 959 |          android:id="@+id/torBridgeConfigFragment"
 | 
| 947 | 960 |          android:name="org.mozilla.fenix.settings.TorBridgeConfigFragment"
 | 
| 948 | 961 |          android:label="@string/preferences_tor_network_settings_bridge_config"
 | 
| 949 | 962 |          tools:layout="@layout/fragment_tor_bridge_config" />
 | 
| 963 | +    <fragment
 | |
| 964 | +        android:id="@+id/torBetaConnectionFeaturesFragment"
 | |
| 965 | +        android:name="org.mozilla.fenix.tor.TorBetaConnectionFeaturesFragment"
 | |
| 966 | +        android:label="Enable beta connection features"
 | |
| 967 | +        tools:layout="@layout/tor_network_settings_beta_connection_features" />
 | |
| 968 | + | |
| 950 | 969 |      <fragment
 | 
| 951 | 970 |          android:id="@+id/trackingProtectionFragment"
 | 
| 952 | 971 |          android:name="org.mozilla.fenix.settings.TrackingProtectionFragment">
 | 
| ... | ... | @@ -376,6 +376,9 @@ | 
| 376 | 376 |      <string name="pref_key_tor_network_settings" translatable="false">pref_key_tor_network_settings</string>
 | 
| 377 | 377 |      <string name="pref_key_tor_network_settings_explanation" translatable="false">pref_key_tor_network_settings_explanation</string>
 | 
| 378 | 378 |      <string name="pref_key_tor_network_settings_bridge_config" translatable="false">pref_key_tor_network_settings_bridge_config</string>
 | 
| 379 | +    <string name="pref_key_use_new_bootstrap" translatable="false">pref_key_use_new_bootstrap</string>
 | |
| 380 | +    <string name="pref_key_use_new_bootstrap_with_android_native" translatable="false">pref_key_use_new_bootstrap_with_android_native</string>
 | |
| 381 | +    <string name="pref_key_use_new_bootstrap_with_html" translatable="false">pref_key_use_new_bootstrap_with_html</string>
 | |
| 379 | 382 |      <string name="pref_key_tor_network_settings_bridge_config_explanation" translatable="false">pref_key_tor_network_settings_bridge_config_explanation</string>
 | 
| 380 | 383 |      <string name="pref_key_tor_network_settings_bridge_config_toggle" translatable="false">pref_key_tor_network_settings_bridge_config_toggle</string>
 | 
| 381 | 384 |      <string name="pref_key_tor_network_settings_bridge_config_builtin_bridge_obfs4" translatable="false">pref_key_tor_network_settings_bridge_config_builtin_bridge_obfs4</string>
 | 
| ... | ... | @@ -27,4 +27,9 @@ | 
| 27 | 27 |          android:title="@string/preferences_tor_network_settings_bridge_config"
 | 
| 28 | 28 |          android:summary="@string/preferences_tor_network_settings_bridge_config_description"
 | 
| 29 | 29 |          app:allowDividerAbove="true" />
 | 
| 30 | +    <Preference
 | |
| 31 | +        android:key="@string/pref_key_use_new_bootstrap"
 | |
| 32 | +        android:title="Enable beta connection features"
 | |
| 33 | +        app:allowDividerAbove="true" />
 | |
| 34 | + | |
| 30 | 35 |  </androidx.preference.PreferenceScreen> |