Commit 7c267a64 authored by Matthew Finkel's avatar Matthew Finkel Committed by Beatriz Rizental
Browse files

TB 40026 [android]: Implement Security Level settings on Android.

Originally, fenix#40026.
parent 3632b9cc
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1444,6 +1444,14 @@ class GeckoEngine(
            get() = runtime.settings.userCharacteristicPingCurrentVersion
            set(value) { runtime.settings.setUserCharacteristicPingCurrentVersion(value) }

        override var torSecurityLevel: Int
            get() = runtime.settings.torSecurityLevel
            set(value) {
                value.let {
                    runtime.settings.torSecurityLevel = it
                }
            }

        override var spoofEnglish: Boolean
            get() = runtime.settings.spoofEnglish
            set(value) {
@@ -1517,6 +1525,7 @@ class GeckoEngine(
            this.fdlibmMathEnabled = it.fdlibmMathEnabled
            this.emailTrackerBlockingPrivateBrowsing = it.emailTrackerBlockingPrivateBrowsing
            this.userCharacteristicPingCurrentVersion = it.userCharacteristicPingCurrentVersion
            this.torSecurityLevel = it.torSecurityLevel
            this.spoofEnglish = it.spoofEnglish
            this.webContentIsolationStrategy = it.webContentIsolationStrategy
            this.fetchPriorityEnabled = it.fetchPriorityEnabled
+6 −0
Original line number Diff line number Diff line
@@ -300,6 +300,11 @@ abstract class Settings {
     */
    open var userCharacteristicPingCurrentVersion: Int by UnsupportedSetting()

    /**
     * Setting to control the current security level
     */
    open var torSecurityLevel: Int by UnsupportedSetting()

    open var spoofEnglish: Boolean by UnsupportedSetting()

    /**
@@ -401,6 +406,7 @@ data class DefaultSettings(
    override var queryParameterStrippingStripList: String = "",
    override var emailTrackerBlockingPrivateBrowsing: Boolean = false,
    override var userCharacteristicPingCurrentVersion: Int = 0,
    override var torSecurityLevel: Int = 4,
    override var spoofEnglish: Boolean = false,
    override var webContentIsolationStrategy: WebContentIsolationStrategy? =
        WebContentIsolationStrategy.ISOLATE_HIGH_VALUE,
+1 −0
Original line number Diff line number Diff line
@@ -173,6 +173,7 @@ class Core(
            cookieBannerHandlingGlobalRulesSubFrames = context.settings().shouldEnableCookieBannerGlobalRulesSubFrame,
            emailTrackerBlockingPrivateBrowsing = false,
            userCharacteristicPingCurrentVersion = FxNimbus.features.userCharacteristics.value().currentVersion,
            torSecurityLevel = context.settings().torSecurityLevel().intRepresentation,
            spoofEnglish = context.settings().spoofEnglish,
            getDesktopMode = {
                store.state.desktopMode
+19 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ import org.mozilla.fenix.perf.ProfilerViewModel
import org.mozilla.fenix.settings.account.AccountUiView
import org.mozilla.fenix.snackbar.FenixSnackbarDelegate
import org.mozilla.fenix.snackbar.SnackbarBinding
import org.mozilla.fenix.tor.SecurityLevel
import org.mozilla.fenix.utils.Settings
import kotlin.system.exitProcess
import org.mozilla.fenix.GleanMetrics.Settings as SettingsMetrics
@@ -372,6 +373,10 @@ class SettingsFragment : PreferenceFragmentCompat() {
                SettingsFragmentDirections.actionSettingsFragmentToPrivateBrowsingFragment()
            }

            resources.getString(R.string.pref_key_tor_security_level_settings) -> {
                SettingsFragmentDirections.actionSettingsFragmentToTorSecurityLevelFragment()
            }

            resources.getString(R.string.pref_key_https_only_settings) -> {
                SettingsFragmentDirections.actionSettingsFragmentToHttpsOnlyFragment()
            }
@@ -590,6 +595,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
        setupAmoCollectionOverridePreference(requireContext().settings())
        setupGeckoLogsPreference(requireContext().settings())
        setupAllowDomesticChinaFxaServerPreference()
        setupSecurityLevelPreference()
        setupHttpsOnlyPreferences()
        setupNotificationPreference()
        setupSearchPreference()
@@ -827,6 +833,19 @@ class SettingsFragment : PreferenceFragmentCompat() {
        }
    }

    @VisibleForTesting
    internal fun setupSecurityLevelPreference() {
        val securityLevelPreference =
            requirePreference<Preference>(R.string.pref_key_tor_security_level_settings)
        securityLevelPreference.summary = context?.settings()?.torSecurityLevel()?.let {
            when (it) {
                SecurityLevel.STANDARD -> getString(R.string.tor_security_level_standard_option)
                SecurityLevel.SAFER -> getString(R.string.tor_security_level_safer_option)
                SecurityLevel.SAFEST -> getString(R.string.tor_security_level_safest_option)
            }
        }
    }

    @VisibleForTesting
    internal fun setupHttpsOnlyPreferences() {
        val httpsOnlyPreference =
+81 −0
Original line number Diff line number Diff line
/* 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.preference.PreferenceFragmentCompat
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.tor.SecurityLevel
import org.mozilla.fenix.tor.SecurityLevelUtil
import org.mozilla.fenix.utils.view.GroupableRadioButton
import org.mozilla.fenix.utils.view.addToRadioGroup
import org.mozilla.fenix.utils.view.uncheckAll

/**
 * Lets the user choose their security level
 */
@Suppress("SpreadOperator")
class TorSecurityLevelFragment : PreferenceFragmentCompat() {
    private val securityLevelRadioGroups = mutableListOf<GroupableRadioButton>()
    private var previousSecurityLevel: SecurityLevel? = null

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.tor_security_level_preferences, rootKey)

        val currentLevel: SecurityLevel? = context?.components?.let {
            try {
                SecurityLevelUtil.getSecurityLevelFromInt(
                    it.core.engine.settings.torSecurityLevel
                )
            } catch (e: IllegalStateException) {
                // The default state is 0. If we get an invalid state then
                // default to Standard (4).
                SecurityLevel.STANDARD
            }
        }

        if (currentLevel == null) {
            throw IllegalStateException("context or Components is null.")
        }

        val radioSafer = bindSecurityLevelRadio(SecurityLevel.SAFER)
        val radioSafest = bindSecurityLevelRadio(SecurityLevel.SAFEST)
        val radioStandard = bindSecurityLevelRadio(SecurityLevel.STANDARD)

        securityLevelRadioGroups.addAll(mutableListOf(radioSafer, radioSafest, radioStandard))
        // `*` is Kotlin's "spread" operator, for expanding an Array as a vararg.
        addToRadioGroup(*securityLevelRadioGroups.toTypedArray())

        securityLevelRadioGroups.uncheckAll()
        val securityLevelRadioButton = requirePreference<RadioButtonPreference>(currentLevel.preferenceKey)
        // Cache this for later comparison in the OnPreferenceChangeListener
        previousSecurityLevel = currentLevel
        securityLevelRadioButton.setCheckedWithoutClickListener(true)
    }

    private fun bindSecurityLevelRadio(
        level: SecurityLevel
    ): RadioButtonPreference {
        val radio = requirePreference<RadioButtonPreference>(level.preferenceKey)

        radio.summary = getString(level.contentDescriptionRes)

        radio.apply {
            setOnPreferenceChangeListener<Boolean> { preference, isChecked ->
                if (isChecked && (previousSecurityLevel!! != level)) {
                    preference.context.components.core.engine.settings.torSecurityLevel =
                        level.intRepresentation
                    previousSecurityLevel = level
                }
                true
            }
        }

        return radio
    }
}
Loading