diff --git a/app/src/main/java/org/mozilla/fenix/BrowsingModeManager.kt b/app/src/main/java/org/mozilla/fenix/BrowsingModeManager.kt index 2dfe620a7..df87bb9a9 100644 --- a/app/src/main/java/org/mozilla/fenix/BrowsingModeManager.kt +++ b/app/src/main/java/org/mozilla/fenix/BrowsingModeManager.kt @@ -38,7 +38,7 @@ class DefaultBrowsingModeManager( override var mode: BrowsingMode get() = BrowsingMode.fromBoolean(settings.usePrivateMode) set(value) { - settings.setPrivateMode(value.isPrivate) + settings.usePrivateMode = value.isPrivate modeDidChange(value) } } diff --git a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt index e870a0b9a..ab9ee7db2 100644 --- a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt +++ b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt @@ -29,9 +29,9 @@ import mozilla.components.support.ktx.android.content.isMainProcess import mozilla.components.support.ktx.android.content.runOnlyInMainProcess import mozilla.components.support.rusthttp.RustHttpConfig import mozilla.components.support.rustlog.RustLog +import org.mozilla.fenix.GleanMetrics.ExperimentsMetrics import org.mozilla.fenix.components.Components import org.mozilla.fenix.utils.Settings -import org.mozilla.fenix.GleanMetrics.ExperimentsMetrics import java.io.File @SuppressLint("Registered") @@ -241,12 +241,12 @@ open class FenixApplication : Application() { AppCompatDelegate.setDefaultNightMode( AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM ) - settings.setFollowDeviceTheme(true) + settings.shouldFollowDeviceTheme = true } else { AppCompatDelegate.setDefaultNightMode( AppCompatDelegate.MODE_NIGHT_NO ) - settings.setLightTheme(true) + settings.shouldUseLightTheme = true } } } diff --git a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt index d3643ff68..9e0cf3b32 100644 --- a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt +++ b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt @@ -21,15 +21,15 @@ import mozilla.components.concept.sync.DeviceEvent import mozilla.components.concept.sync.DeviceEventsObserver import mozilla.components.concept.sync.DevicePushSubscription import mozilla.components.concept.sync.DeviceType -import mozilla.components.service.fxa.DeviceConfig -import mozilla.components.service.fxa.ServerConfig -import mozilla.components.service.fxa.SyncConfig import mozilla.components.concept.sync.OAuthAccount import mozilla.components.feature.push.AutoPushFeature import mozilla.components.feature.push.AutoPushSubscription import mozilla.components.feature.push.PushConfig import mozilla.components.feature.push.PushSubscriptionObserver import mozilla.components.feature.push.PushType +import mozilla.components.service.fxa.DeviceConfig +import mozilla.components.service.fxa.ServerConfig +import mozilla.components.service.fxa.SyncConfig import mozilla.components.service.fxa.manager.FxaAccountManager import mozilla.components.service.fxa.sync.GlobalSyncableStoreProvider import mozilla.components.support.base.log.logger.Logger @@ -143,7 +143,7 @@ class BackgroundServices( context.components.analytics.metrics.track(Event.SyncAuthSignOut) - Settings.instance?.setFxaSignedIn(false) + Settings.instance?.fxaSignedIn = false } override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) { @@ -156,7 +156,7 @@ class BackgroundServices( context.components.analytics.metrics.track(Event.SyncAuthSignIn) - Settings.instance?.setFxaSignedIn(true) + Settings.instance?.fxaSignedIn = true } } @@ -178,7 +178,7 @@ class BackgroundServices( // See https://github.com/mozilla-mobile/android-components/issues/3732 setOf("https://identity.mozilla.com/apps/oldsync") ).also { - Settings.instance?.setFxaHasSyncedItems(syncConfig?.syncableStores?.isNotEmpty() ?: false) + Settings.instance?.fxaHasSyncedItems = syncConfig?.syncableStores?.isNotEmpty() ?: false if (FeatureFlags.sendTabEnabled) { it.registerForDeviceEvents(deviceEventObserver, ProcessLifecycleOwner.get(), false) diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingTrackingProtectionViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingTrackingProtectionViewHolder.kt index 61f44a1f0..0a8b06e8d 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingTrackingProtectionViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingTrackingProtectionViewHolder.kt @@ -31,7 +31,7 @@ class OnboardingTrackingProtectionViewHolder(view: View) : RecyclerView.ViewHold } private fun updateTrackingProtectionSetting(enabled: Boolean) { - Settings.getInstance(itemView.context).setTrackingProtection(enabled) + Settings.getInstance(itemView.context).shouldUseTrackingProtection = enabled with(itemView.context.components) { val policy = core.createTrackingProtectionPolicy(enabled) useCases.settingsUseCases.updateTrackingProtection.invoke(policy) diff --git a/app/src/main/java/org/mozilla/fenix/settings/AccessibilityFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/AccessibilityFragment.kt index ae8d3e864..dfb2e0389 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/AccessibilityFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/AccessibilityFragment.kt @@ -25,7 +25,7 @@ class AccessibilityFragment : PreferenceFragmentCompat() { (newValue as? Int).let { // Value is mapped from 0->30 in steps of 1 so let's convert to float in range 0.5->2.0 val newTextScale = ((newValue as Int * STEP_SIZE) + MIN_SCALE_VALUE).toFloat() / PERCENT_TO_DECIMAL - Settings.getInstance(context!!).setFontSizeFactor(newTextScale) + Settings.getInstance(context!!).fontSizeFactor = newTextScale requireComponents.core.engine.settings.fontSizeFactor = newTextScale requireComponents.useCases.sessionUseCases.reload.invoke() } @@ -37,7 +37,7 @@ class AccessibilityFragment : PreferenceFragmentCompat() { val useAutoSizePreference = findPreference(getString(R.string.pref_key_accessibility_auto_size)) useAutoSizePreference?.setOnPreferenceChangeListener { _, newValue -> - Settings.getInstance(context!!).setAutoSize(newValue as Boolean) + Settings.getInstance(context!!).shouldUseAutoSize = newValue as Boolean requireComponents.core.engine.settings.automaticFontSizeAdjustment = newValue if (!newValue) { requireComponents.core.engine.settings.fontSizeFactor = Settings.getInstance(context!!).fontSizeFactor diff --git a/app/src/main/java/org/mozilla/fenix/settings/PhoneFeature.kt b/app/src/main/java/org/mozilla/fenix/settings/PhoneFeature.kt index 64cd2ada3..415d673ae 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/PhoneFeature.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/PhoneFeature.kt @@ -35,22 +35,22 @@ enum class PhoneFeature(val id: Int, val androidPermissionsList: Array) val label = when (this) { CAMERA -> { sitePermissions?.camera?.toString(context) ?: settings - ?.getSitePermissionsPhoneFeatureCameraAction() + ?.sitePermissionsPhoneFeatureCameraAction ?.toString(context) } LOCATION -> { sitePermissions?.location?.toString(context) ?: settings - ?.getSitePermissionsPhoneFeatureLocation() + ?.sitePermissionsPhoneFeatureLocation ?.toString(context) } MICROPHONE -> { sitePermissions?.microphone?.toString(context) ?: settings - ?.getSitePermissionsPhoneFeatureMicrophoneAction() + ?.sitePermissionsPhoneFeatureMicrophoneAction ?.toString(context) } NOTIFICATION -> { sitePermissions?.notification?.toString(context) ?: settings - ?.getSitePermissionsPhoneFeatureNotificationAction() + ?.sitePermissionsPhoneFeatureNotificationAction ?.toString(context) } } @@ -61,22 +61,22 @@ enum class PhoneFeature(val id: Int, val androidPermissionsList: Array) val status = when (this) { CAMERA -> { sitePermissions?.camera ?: settings - ?.getSitePermissionsPhoneFeatureCameraAction() + ?.sitePermissionsPhoneFeatureCameraAction ?.toStatus() } LOCATION -> { sitePermissions?.location ?: settings - ?.getSitePermissionsPhoneFeatureLocation() + ?.sitePermissionsPhoneFeatureLocation ?.toStatus() } MICROPHONE -> { sitePermissions?.microphone ?: settings - ?.getSitePermissionsPhoneFeatureMicrophoneAction() + ?.sitePermissionsPhoneFeatureMicrophoneAction ?.toStatus() } NOTIFICATION -> { sitePermissions?.notification ?: settings - ?.getSitePermissionsPhoneFeatureNotificationAction() + ?.sitePermissionsPhoneFeatureNotificationAction ?.toStatus() } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/RadioSearchEngineListPreference.kt b/app/src/main/java/org/mozilla/fenix/settings/RadioSearchEngineListPreference.kt index d5b98c172..4ab51584b 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/RadioSearchEngineListPreference.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/RadioSearchEngineListPreference.kt @@ -26,6 +26,6 @@ class RadioSearchEngineListPreference @JvmOverloads constructor( override fun onSearchEngineSelected(searchEngine: SearchEngine) { context.components.search.searchEngineManager.defaultSearchEngine = searchEngine - Settings.getInstance(context).setDefaultSearchEngineByName(searchEngine.name) + Settings.getInstance(context).defaultSearchEngineName = searchEngine.name } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsFragment.kt index 92b024810..3113d6933 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsFragment.kt @@ -11,10 +11,10 @@ import androidx.preference.Preference import androidx.preference.Preference.OnPreferenceClickListener import androidx.preference.PreferenceFragmentCompat import org.mozilla.fenix.R -import org.mozilla.fenix.settings.PhoneFeature.NOTIFICATION -import org.mozilla.fenix.settings.PhoneFeature.LOCATION import org.mozilla.fenix.settings.PhoneFeature.CAMERA +import org.mozilla.fenix.settings.PhoneFeature.LOCATION import org.mozilla.fenix.settings.PhoneFeature.MICROPHONE +import org.mozilla.fenix.settings.PhoneFeature.NOTIFICATION import org.mozilla.fenix.utils.Settings @SuppressWarnings("TooManyFunctions") @@ -56,19 +56,19 @@ class SitePermissionsFragment : PreferenceFragmentCompat() { val settings = Settings.getInstance(requireContext()) val cameraAction = settings - .getSitePermissionsPhoneFeatureCameraAction() + .sitePermissionsPhoneFeatureCameraAction .toString(requireContext()) val locationAction = settings - .getSitePermissionsPhoneFeatureLocation() + .sitePermissionsPhoneFeatureLocation .toString(requireContext()) val microPhoneAction = settings - .getSitePermissionsPhoneFeatureMicrophoneAction() + .sitePermissionsPhoneFeatureMicrophoneAction .toString(requireContext()) val notificationAction = settings - .getSitePermissionsPhoneFeatureNotificationAction() + .sitePermissionsPhoneFeatureNotificationAction .toString(requireContext()) initPhoneFeature(CAMERA, cameraAction) diff --git a/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsManagePhoneFeatureFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsManagePhoneFeatureFragment.kt index 2f0bb7c37..0782de3f2 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsManagePhoneFeatureFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsManagePhoneFeatureFragment.kt @@ -122,10 +122,10 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { private val PhoneFeature.action: SitePermissionsRules.Action get() { return when (phoneFeature) { - PhoneFeature.CAMERA -> settings.getSitePermissionsPhoneFeatureCameraAction() - PhoneFeature.LOCATION -> settings.getSitePermissionsPhoneFeatureLocation() - PhoneFeature.MICROPHONE -> settings.getSitePermissionsPhoneFeatureMicrophoneAction() - PhoneFeature.NOTIFICATION -> settings.getSitePermissionsPhoneFeatureNotificationAction() + PhoneFeature.CAMERA -> settings.sitePermissionsPhoneFeatureCameraAction + PhoneFeature.LOCATION -> settings.sitePermissionsPhoneFeatureLocation + PhoneFeature.MICROPHONE -> settings.sitePermissionsPhoneFeatureMicrophoneAction + PhoneFeature.NOTIFICATION -> settings.sitePermissionsPhoneFeatureNotificationAction } } @@ -145,10 +145,10 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { private fun saveActionInSettings(action: SitePermissionsRules.Action) { when (phoneFeature) { - PhoneFeature.CAMERA -> settings.setSitePermissionsPhoneFeatureCameraAction(action) - PhoneFeature.LOCATION -> settings.setSitePermissionsPhoneFeatureLocation(action) - PhoneFeature.MICROPHONE -> settings.setSitePermissionsPhoneFeatureMicrophoneAction(action) - PhoneFeature.NOTIFICATION -> settings.setSitePermissionsPhoneFeatureNotificationAction(action) + PhoneFeature.CAMERA -> settings.sitePermissionsPhoneFeatureCameraAction = action + PhoneFeature.LOCATION -> settings.sitePermissionsPhoneFeatureLocation = action + PhoneFeature.MICROPHONE -> settings.sitePermissionsPhoneFeatureMicrophoneAction = action + PhoneFeature.NOTIFICATION -> settings.sitePermissionsPhoneFeatureNotificationAction = action } } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/TrackingProtectionFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/TrackingProtectionFragment.kt index 964d14bc8..ed32399c9 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/TrackingProtectionFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/TrackingProtectionFragment.kt @@ -33,8 +33,7 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() { preferenceTP?.isChecked = Settings.getInstance(context!!).shouldUseTrackingProtection preferenceTP?.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> - Settings.getInstance(requireContext()) - .setTrackingProtection(newValue = newValue as Boolean) + Settings.getInstance(requireContext()).shouldUseTrackingProtection = newValue as Boolean with(requireComponents) { val policy = core.createTrackingProtectionPolicy(newValue) useCases.settingsUseCases.updateTrackingProtection.invoke(policy) diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsComponent.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsComponent.kt index 3692bb024..ca465da13 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsComponent.kt @@ -9,14 +9,14 @@ import android.view.ViewGroup import androidx.core.net.toUri import mozilla.components.feature.sitepermissions.SitePermissions import org.mozilla.fenix.ext.components -import org.mozilla.fenix.mvi.ViewState -import org.mozilla.fenix.mvi.Change import org.mozilla.fenix.mvi.Action import org.mozilla.fenix.mvi.ActionBusFactory +import org.mozilla.fenix.mvi.Change import org.mozilla.fenix.mvi.UIComponent import org.mozilla.fenix.mvi.UIComponentViewModelBase import org.mozilla.fenix.mvi.UIComponentViewModelProvider import org.mozilla.fenix.mvi.UIView +import org.mozilla.fenix.mvi.ViewState import org.mozilla.fenix.settings.PhoneFeature import org.mozilla.fenix.settings.toggle import org.mozilla.fenix.utils.Settings @@ -48,10 +48,10 @@ class QuickSettingsComponent( return if (sitePermissions == null) { val settings = Settings.getInstance(context) val origin = requireNotNull(url.toUri().host) - var location = settings.getSitePermissionsPhoneFeatureLocation().toStatus() - var camera = settings.getSitePermissionsPhoneFeatureCameraAction().toStatus() - var microphone = settings.getSitePermissionsPhoneFeatureMicrophoneAction().toStatus() - var notification = settings.getSitePermissionsPhoneFeatureNotificationAction().toStatus() + var location = settings.sitePermissionsPhoneFeatureLocation.toStatus() + var camera = settings.sitePermissionsPhoneFeatureCameraAction.toStatus() + var microphone = settings.sitePermissionsPhoneFeatureMicrophoneAction.toStatus() + var notification = settings.sitePermissionsPhoneFeatureNotificationAction.toStatus() when (featurePhone) { PhoneFeature.CAMERA -> camera = camera.toggle() diff --git a/app/src/main/java/org/mozilla/fenix/settings/sharedpreferences/BooleanPreference.kt b/app/src/main/java/org/mozilla/fenix/settings/sharedpreferences/BooleanPreference.kt new file mode 100644 index 000000000..e7bd1ee96 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/settings/sharedpreferences/BooleanPreference.kt @@ -0,0 +1,27 @@ +/* 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.sharedpreferences + +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +private class BooleanPreference( + private val key: String, + private val default: Boolean +) : ReadWriteProperty { + + override fun getValue(thisRef: PreferencesHolder, property: KProperty<*>): Boolean = + thisRef.preferences.getBoolean(key, default) + + override fun setValue(thisRef: PreferencesHolder, property: KProperty<*>, value: Boolean) { + thisRef.preferences.edit().putBoolean(key, value).apply() + } +} + +/** + * Property delegate for getting and setting a boolean shared preference. + */ +fun booleanPreference(key: String, default: Boolean): ReadWriteProperty = + BooleanPreference(key, default) diff --git a/app/src/main/java/org/mozilla/fenix/settings/sharedpreferences/PreferencesHolder.kt b/app/src/main/java/org/mozilla/fenix/settings/sharedpreferences/PreferencesHolder.kt new file mode 100644 index 000000000..a170985e1 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/settings/sharedpreferences/PreferencesHolder.kt @@ -0,0 +1,11 @@ +/* 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.sharedpreferences + +import android.content.SharedPreferences + +interface PreferencesHolder { + val preferences: SharedPreferences +} diff --git a/app/src/main/java/org/mozilla/fenix/settings/sharedpreferences/SitePermissionsRulesActionPreference.kt b/app/src/main/java/org/mozilla/fenix/settings/sharedpreferences/SitePermissionsRulesActionPreference.kt new file mode 100644 index 000000000..43dbe955c --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/settings/sharedpreferences/SitePermissionsRulesActionPreference.kt @@ -0,0 +1,45 @@ +/* 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.sharedpreferences + +import mozilla.components.feature.sitepermissions.SitePermissionsRules +import java.security.InvalidParameterException +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +private class SitePermissionsRulesActionPreference( + private val key: String +) : ReadWriteProperty { + + override fun getValue(thisRef: PreferencesHolder, property: KProperty<*>): SitePermissionsRules.Action = + intToAction(thisRef.preferences.getInt(key, ASK_TO_ALLOW_INT)) + + override fun setValue(thisRef: PreferencesHolder, property: KProperty<*>, value: SitePermissionsRules.Action) { + thisRef.preferences.edit().putInt(key, actionToInt(value)).apply() + } + + companion object { + private const val BLOCKED_INT = 0 + private const val ASK_TO_ALLOW_INT = 1 + + private fun actionToInt(action: SitePermissionsRules.Action) = when (action) { + SitePermissionsRules.Action.BLOCKED -> BLOCKED_INT + SitePermissionsRules.Action.ASK_TO_ALLOW -> ASK_TO_ALLOW_INT + } + + private fun intToAction(action: Int) = when (action) { + BLOCKED_INT -> SitePermissionsRules.Action.BLOCKED + ASK_TO_ALLOW_INT -> SitePermissionsRules.Action.ASK_TO_ALLOW + else -> throw InvalidParameterException("$action is not a valid SitePermissionsRules.Action") + } + } +} + +/** + * Property delegate for getting and setting a [SitePermissionsRules.Action] preference. + */ +fun sitePermissionsRulesActionPreference( + key: String +): ReadWriteProperty = SitePermissionsRulesActionPreference(key) diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index a1c027301..1a37e4925 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -14,16 +14,17 @@ import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.Config import org.mozilla.fenix.R import org.mozilla.fenix.ext.getPreferenceKey -import java.security.InvalidParameterException +import org.mozilla.fenix.settings.sharedpreferences.PreferencesHolder +import org.mozilla.fenix.settings.sharedpreferences.booleanPreference +import org.mozilla.fenix.settings.sharedpreferences.sitePermissionsRulesActionPreference /** * A simple wrapper for SharedPreferences that makes reading preference a little bit easier. */ -@SuppressWarnings("TooManyFunctions") class Settings private constructor( context: Context, private val isCrashReportEnabledInBuild: Boolean -) { +) : PreferencesHolder { companion object { const val autoBounceMaximumCount = 2 @@ -46,110 +47,80 @@ class Settings private constructor( private val appContext = context.applicationContext - val preferences: SharedPreferences = + override val preferences: SharedPreferences = appContext.getSharedPreferences(FENIX_PREFERENCES, MODE_PRIVATE) - val usePrivateMode: Boolean - get() = preferences.getBoolean(appContext.getPreferenceKey(R.string.pref_key_private_mode), false) + var usePrivateMode by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_private_mode), + default = false + ) - fun setPrivateMode(newValue: Boolean) { - preferences.edit().putBoolean(appContext.getPreferenceKey(R.string.pref_key_private_mode), newValue).apply() - } - - val defaultSearchEngineName: String + var defaultSearchEngineName: String get() = preferences.getString(appContext.getPreferenceKey(R.string.pref_key_search_engine), "") ?: "" + set(name) = preferences.edit() + .putString(appContext.getPreferenceKey(R.string.pref_key_search_engine), name) + .apply() val isCrashReportingEnabled: Boolean get() = isCrashReportEnabledInBuild && preferences.getBoolean(appContext.getPreferenceKey(R.string.pref_key_crash_reporter), true) - val isRemoteDebuggingEnabled: Boolean - get() = preferences.getBoolean(appContext.getPreferenceKey(R.string.pref_key_remote_debugging), false) + val isRemoteDebuggingEnabled by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_remote_debugging), + default = false + ) - val isTelemetryEnabled: Boolean - get() = preferences.getBoolean(appContext.getPreferenceKey(R.string.pref_key_telemetry), true) + val isTelemetryEnabled by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_telemetry), + default = true + ) val shouldAutoBounceQuickActionSheet: Boolean get() = autoBounceQuickActionSheetCount < autoBounceMaximumCount - val shouldUseLightTheme: Boolean - get() = preferences.getBoolean( - appContext.getPreferenceKey(R.string.pref_key_light_theme), - false - ) + var shouldUseLightTheme by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_light_theme), + default = false + ) - fun setLightTheme(newValue: Boolean) { - preferences.edit().putBoolean( - appContext.getPreferenceKey(R.string.pref_key_light_theme), - newValue - ).apply() - } + var shouldUseAutoSize by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_accessibility_auto_size), + default = true + ) - fun setAutoSize(newValue: Boolean) { - preferences.edit().putBoolean(appContext.getPreferenceKey(R.string.pref_key_accessibility_auto_size), newValue) - .apply() - } - - val shouldUseAutoSize: Boolean - get() = preferences.getBoolean( - appContext.getPreferenceKey(R.string.pref_key_accessibility_auto_size), - true - ) - - fun setFontSizeFactor(newValue: Float) { - preferences.edit().putFloat(appContext.getPreferenceKey(R.string.pref_key_accessibility_font_scale), newValue) - .apply() - } - - val fontSizeFactor: Float + var fontSizeFactor: Float get() = preferences.getFloat( appContext.getPreferenceKey(R.string.pref_key_accessibility_font_scale), 1f ) + set(value) = preferences.edit() + .putFloat(appContext.getPreferenceKey(R.string.pref_key_accessibility_font_scale), value) + .apply() - val shouldShowVisitedSitesBookmarks: Boolean - get() = preferences.getBoolean( - appContext.getPreferenceKey(R.string.pref_key_show_visited_sites_bookmarks), - true - ) + val shouldShowVisitedSitesBookmarks by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_show_visited_sites_bookmarks), + default = true + ) - val shouldUseDarkTheme: Boolean - get() = preferences.getBoolean( - appContext.getPreferenceKey(R.string.pref_key_dark_theme), - false - ) + val shouldUseDarkTheme by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_dark_theme), + default = false + ) - val shouldFollowDeviceTheme: Boolean - get() = preferences.getBoolean( - appContext.getPreferenceKey(R.string.pref_key_follow_device_theme), - false - ) + var shouldFollowDeviceTheme by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_follow_device_theme), + default = false + ) - fun setFollowDeviceTheme(newValue: Boolean) { - preferences.edit().putBoolean( - appContext.getPreferenceKey(R.string.pref_key_follow_device_theme), - newValue - ).apply() - } + var shouldUseTrackingProtection by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_tracking_protection), + default = true + ) - val shouldUseTrackingProtection: Boolean - get() = preferences.getBoolean( - appContext.getPreferenceKey(R.string.pref_key_tracking_protection), - true - ) - - fun setTrackingProtection(newValue: Boolean) { - preferences.edit().putBoolean( - appContext.getPreferenceKey(R.string.pref_key_tracking_protection), - newValue - ).apply() - } - - val shouldUseAutoBatteryTheme: Boolean - get() = preferences.getBoolean( - appContext.getPreferenceKey(R.string.pref_key_auto_battery_theme), - false - ) + val shouldUseAutoBatteryTheme by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_auto_battery_theme), + default = false + ) val themeSettingString: String get() = when { @@ -162,7 +133,7 @@ class Settings private constructor( @VisibleForTesting(otherwise = PRIVATE) internal val autoBounceQuickActionSheetCount: Int - get() = (preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_bounce_quick_action), 0)) + get() = preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_bounce_quick_action), 0) fun incrementAutomaticBounceQuickActionSheetCount() { preferences.edit().putInt( @@ -171,91 +142,42 @@ class Settings private constructor( ).apply() } - fun setDefaultSearchEngineByName(name: String) { - preferences.edit() - .putString(appContext.getPreferenceKey(R.string.pref_key_search_engine), name) - .apply() - } + val showSearchSuggestions by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_show_search_suggestions), + default = true + ) - val showSearchSuggestions: Boolean - get() = preferences.getBoolean( - appContext.getPreferenceKey(R.string.pref_key_show_search_suggestions), true - ) + var sitePermissionsPhoneFeatureCameraAction by sitePermissionsRulesActionPreference( + appContext.getPreferenceKey(R.string.pref_key_phone_feature_camera) + ) - fun setSitePermissionsPhoneFeatureCameraAction(action: SitePermissionsRules.Action) { - preferences.edit() - .putInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_camera), action.id) - .apply() - } + var sitePermissionsPhoneFeatureMicrophoneAction by sitePermissionsRulesActionPreference( + appContext.getPreferenceKey(R.string.pref_key_phone_feature_microphone) + ) - fun getSitePermissionsPhoneFeatureCameraAction(): SitePermissionsRules.Action { - return preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_camera), 1) - .toSitePermissionsRulesAction() - } + var sitePermissionsPhoneFeatureNotificationAction by sitePermissionsRulesActionPreference( + appContext.getPreferenceKey(R.string.pref_key_phone_feature_notification) + ) - fun setSitePermissionsPhoneFeatureMicrophoneAction(action: SitePermissionsRules.Action) { - preferences.edit() - .putInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_microphone), action.id) - .apply() - } - - fun getSitePermissionsPhoneFeatureMicrophoneAction(): SitePermissionsRules.Action { - return preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_microphone), 1) - .toSitePermissionsRulesAction() - } - - fun setSitePermissionsPhoneFeatureNotificationAction(action: SitePermissionsRules.Action) { - preferences.edit() - .putInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_notification), action.id) - .apply() - } - - fun getSitePermissionsPhoneFeatureNotificationAction(): SitePermissionsRules.Action { - return preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_notification), 1) - .toSitePermissionsRulesAction() - } - - fun setSitePermissionsPhoneFeatureLocation(action: SitePermissionsRules.Action) { - preferences.edit() - .putInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_location), action.id) - .apply() - } - - fun getSitePermissionsPhoneFeatureLocation(): SitePermissionsRules.Action { - return preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_phone_feature_location), 1) - .toSitePermissionsRulesAction() - } + var sitePermissionsPhoneFeatureLocation by sitePermissionsRulesActionPreference( + appContext.getPreferenceKey(R.string.pref_key_phone_feature_location) + ) fun getSitePermissionsCustomSettingsRules(): SitePermissionsRules { return SitePermissionsRules( - notification = getSitePermissionsPhoneFeatureNotificationAction(), - microphone = getSitePermissionsPhoneFeatureMicrophoneAction(), - location = getSitePermissionsPhoneFeatureLocation(), - camera = getSitePermissionsPhoneFeatureCameraAction() + notification = sitePermissionsPhoneFeatureNotificationAction, + microphone = sitePermissionsPhoneFeatureMicrophoneAction, + location = sitePermissionsPhoneFeatureLocation, + camera = sitePermissionsPhoneFeatureCameraAction ) } - fun setFxaSignedIn(isSignedIn: Boolean) { - preferences.edit() - .putBoolean(appContext.getPreferenceKey(R.string.pref_key_fxa_signed_in), isSignedIn) - .apply() - } + var fxaSignedIn by booleanPreference(appContext.getPreferenceKey(R.string.pref_key_fxa_signed_in), default = true) - val fxaSignedIn: Boolean - get() = preferences.getBoolean( - appContext.getPreferenceKey(R.string.pref_key_fxa_signed_in), true - ) - - fun setFxaHasSyncedItems(hasSyncedItems: Boolean) { - preferences.edit() - .putBoolean(appContext.getPreferenceKey(R.string.pref_key_fxa_has_synced_items), hasSyncedItems) - .apply() - } - - val fxaHasSyncedItems: Boolean - get() = preferences.getBoolean( - appContext.getPreferenceKey(R.string.pref_key_fxa_has_synced_items), true - ) + var fxaHasSyncedItems by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_fxa_has_synced_items), + default = true + ) fun addSearchWidgetInstalled(count: Int) { val key = appContext.getPreferenceKey(R.string.pref_key_search_widget_installed) @@ -266,23 +188,5 @@ class Settings private constructor( } val searchWidgetInstalled: Boolean - get() = 0 < preferences.getInt( - appContext.getPreferenceKey(R.string.pref_key_search_widget_installed), 0 - ) - - private val SitePermissionsRules.Action.id: Int - get() { - return when (this) { - SitePermissionsRules.Action.BLOCKED -> 0 - SitePermissionsRules.Action.ASK_TO_ALLOW -> 1 - } - } - - private fun Int.toSitePermissionsRulesAction(): SitePermissionsRules.Action { - return when (this) { - 0 -> SitePermissionsRules.Action.BLOCKED - 1 -> SitePermissionsRules.Action.ASK_TO_ALLOW - else -> throw InvalidParameterException("$this is not a valid SitePermissionsRules.Action") - } - } + get() = 0 < preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_search_widget_installed), 0) } diff --git a/app/src/test/java/org/mozilla/fenix/settings/sharedpreferences/BooleanPreferenceTest.kt b/app/src/test/java/org/mozilla/fenix/settings/sharedpreferences/BooleanPreferenceTest.kt new file mode 100644 index 000000000..12fcf955a --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/settings/sharedpreferences/BooleanPreferenceTest.kt @@ -0,0 +1,76 @@ +/* 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.sharedpreferences + +import android.content.SharedPreferences +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.runs +import io.mockk.verify +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test + +class BooleanPreferenceTest { + + private lateinit var sharedPrefs: SharedPreferences + private lateinit var editor: SharedPreferences.Editor + + @Before + fun setup() { + sharedPrefs = mockk(relaxed = true) + editor = mockk() + + every { sharedPrefs.edit() } returns editor + every { editor.putBoolean(any(), any()) } returns editor + every { editor.apply() } just runs + } + + @Test + fun `getter returns boolean from shared preferences`() { + val holder = object : PreferencesHolder { + override val preferences = sharedPrefs + val test by booleanPreference("test_pref_key", default = false) + } + every { sharedPrefs.getBoolean("test_pref_key", false) } returns true + + assertTrue(holder.test) + verify { sharedPrefs.getBoolean("test_pref_key", false) } + } + + @Test + fun `setter applies boolean to shared preferences`() { + val holder = object : PreferencesHolder { + override val preferences = sharedPrefs + var test by booleanPreference("pref", default = true) + } + holder.test = false + + verify { editor.putBoolean("pref", false) } + verify { editor.apply() } + } + + @Test + fun `getter uses default value`() { + val holderFalse = object : PreferencesHolder { + override val preferences = sharedPrefs + val test by booleanPreference("test_pref_key", default = false) + } + // Call the getter for the test + holderFalse.test + + verify { sharedPrefs.getBoolean("test_pref_key", false) } + + val holderTrue = object : PreferencesHolder { + override val preferences = sharedPrefs + val test by booleanPreference("test_pref_key", default = true) + } + // Call the getter for the test + holderTrue.test + + verify { sharedPrefs.getBoolean("test_pref_key", true) } + } +} diff --git a/app/src/test/java/org/mozilla/fenix/settings/sharedpreferences/SitePermissionsRulesActionPreferenceTest.kt b/app/src/test/java/org/mozilla/fenix/settings/sharedpreferences/SitePermissionsRulesActionPreferenceTest.kt new file mode 100644 index 000000000..30d60adbf --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/settings/sharedpreferences/SitePermissionsRulesActionPreferenceTest.kt @@ -0,0 +1,73 @@ +/* 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.sharedpreferences + +import android.content.SharedPreferences +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.runs +import io.mockk.verify +import mozilla.components.feature.sitepermissions.SitePermissionsRules +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test + +class SitePermissionsRulesActionPreferenceTest { + + private lateinit var sharedPrefs: SharedPreferences + private lateinit var editor: SharedPreferences.Editor + + @Before + fun setup() { + sharedPrefs = mockk(relaxed = true) + editor = mockk() + + every { sharedPrefs.edit() } returns editor + every { editor.putInt(any(), any()) } returns editor + every { editor.apply() } just runs + } + + @Test + fun `getter returns action from shared preferences`() { + val holder = object : PreferencesHolder { + override val preferences = sharedPrefs + val test by sitePermissionsRulesActionPreference("test_preference_key") + } + every { sharedPrefs.getInt("test_preference_key", 1) } returns 0 + + assertEquals(SitePermissionsRules.Action.BLOCKED, holder.test) + verify { sharedPrefs.getInt("test_preference_key", 1) } + } + + @Test + fun `setter applies boolean to shared preferences`() { + val holder = object : PreferencesHolder { + override val preferences = sharedPrefs + var test by sitePermissionsRulesActionPreference("pref") + } + holder.test = SitePermissionsRules.Action.BLOCKED + + verify { editor.putInt("pref", 0) } + verify { editor.apply() } + + holder.test = SitePermissionsRules.Action.ASK_TO_ALLOW + + verify { editor.putInt("pref", 1) } + verify { editor.apply() } + } + + @Test + fun `getter defaults to ASK_TO_ALLOW`() { + every { sharedPrefs.getInt("key", 1) } returns 1 + val holder = object : PreferencesHolder { + override val preferences = sharedPrefs + val action by sitePermissionsRulesActionPreference("key") + } + + assertEquals(SitePermissionsRules.Action.ASK_TO_ALLOW, holder.action) + verify { sharedPrefs.getInt("key", 1) } + } +} diff --git a/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt b/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt index d1b124aef..c69027f8f 100644 --- a/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt +++ b/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt @@ -40,13 +40,13 @@ class SettingsTest { assertFalse(settings.usePrivateMode) // When - settings.setPrivateMode(true) + settings.usePrivateMode = true // Then assertTrue(settings.usePrivateMode) // When - settings.setPrivateMode(false) + settings.usePrivateMode = false // Then assertFalse(settings.usePrivateMode) @@ -59,7 +59,7 @@ class SettingsTest { assertEquals("", settings.defaultSearchEngineName) // When - settings.setDefaultSearchEngineByName("Mozilla") + settings.defaultSearchEngineName = "Mozilla" // Then assertEquals("Mozilla", settings.defaultSearchEngineName) @@ -141,7 +141,7 @@ class SettingsTest { assertFalse(settings.shouldUseLightTheme) // When - settings.setLightTheme(true) + settings.shouldUseLightTheme = true // Then assertTrue(settings.shouldUseLightTheme) @@ -154,7 +154,7 @@ class SettingsTest { assertTrue(settings.shouldUseAutoSize) // When - settings.setAutoSize(false) + settings.shouldUseAutoSize = false // Then assertFalse(settings.shouldUseAutoSize) @@ -167,7 +167,7 @@ class SettingsTest { assertEquals(1f, settings.fontSizeFactor) // When - settings.setFontSizeFactor(2f) + settings.fontSizeFactor = 2f // Then assertEquals(2f, settings.fontSizeFactor) @@ -194,7 +194,7 @@ class SettingsTest { assertFalse(settings.shouldFollowDeviceTheme) // When - settings.setFollowDeviceTheme(true) + settings.shouldFollowDeviceTheme = true // Then assertTrue(settings.shouldFollowDeviceTheme) @@ -207,7 +207,7 @@ class SettingsTest { assertTrue(settings.shouldUseTrackingProtection) // When - settings.setTrackingProtection(false) + settings.shouldUseTrackingProtection = false // Then assertFalse(settings.shouldUseTrackingProtection) @@ -231,52 +231,52 @@ class SettingsTest { fun sitePermissionsPhoneFeatureCameraAction() { // When just created // Then - assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureCameraAction()) + assertEquals(ASK_TO_ALLOW, settings.sitePermissionsPhoneFeatureCameraAction) // When - settings.setSitePermissionsPhoneFeatureCameraAction(BLOCKED) + settings.sitePermissionsPhoneFeatureCameraAction = BLOCKED // Then - assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureCameraAction()) + assertEquals(BLOCKED, settings.sitePermissionsPhoneFeatureCameraAction) } @Test fun sitePermissionsPhoneFeatureMicrophoneAction() { // When just created // Then - assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureMicrophoneAction()) + assertEquals(ASK_TO_ALLOW, settings.sitePermissionsPhoneFeatureMicrophoneAction) // When - settings.setSitePermissionsPhoneFeatureMicrophoneAction(BLOCKED) + settings.sitePermissionsPhoneFeatureMicrophoneAction = BLOCKED // Then - assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureMicrophoneAction()) + assertEquals(BLOCKED, settings.sitePermissionsPhoneFeatureMicrophoneAction) } @Test fun sitePermissionsPhoneFeatureNotificationAction() { // When just created // Then - assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureNotificationAction()) + assertEquals(ASK_TO_ALLOW, settings.sitePermissionsPhoneFeatureNotificationAction) // When - settings.setSitePermissionsPhoneFeatureNotificationAction(BLOCKED) + settings.sitePermissionsPhoneFeatureNotificationAction = BLOCKED // Then - assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureNotificationAction()) + assertEquals(BLOCKED, settings.sitePermissionsPhoneFeatureNotificationAction) } @Test fun sitePermissionsPhoneFeatureLocation() { // When just created // Then - assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureLocation()) + assertEquals(ASK_TO_ALLOW, settings.sitePermissionsPhoneFeatureLocation) // When - settings.setSitePermissionsPhoneFeatureLocation(BLOCKED) + settings.sitePermissionsPhoneFeatureLocation = BLOCKED // Then - assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureLocation()) + assertEquals(BLOCKED, settings.sitePermissionsPhoneFeatureLocation) } @Test @@ -292,7 +292,7 @@ class SettingsTest { @Test fun getSitePermissionsCustomSettingsRules_camera() { // When - settings.setSitePermissionsPhoneFeatureCameraAction(BLOCKED) + settings.sitePermissionsPhoneFeatureCameraAction = BLOCKED // Then assertEquals( @@ -304,7 +304,7 @@ class SettingsTest { @Test fun getSitePermissionsCustomSettingsRules_notification() { // When - settings.setSitePermissionsPhoneFeatureNotificationAction(BLOCKED) + settings.sitePermissionsPhoneFeatureNotificationAction = BLOCKED // Then assertEquals( @@ -316,7 +316,7 @@ class SettingsTest { @Test fun getSitePermissionsCustomSettingsRules_location() { // When - settings.setSitePermissionsPhoneFeatureLocation(BLOCKED) + settings.sitePermissionsPhoneFeatureLocation = BLOCKED // Then assertEquals( @@ -328,7 +328,7 @@ class SettingsTest { @Test fun getSitePermissionsCustomSettingsRules_microphone() { // When - settings.setSitePermissionsPhoneFeatureMicrophoneAction(BLOCKED) + settings.sitePermissionsPhoneFeatureMicrophoneAction = BLOCKED // Then assertEquals(