diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSitePermissionsCommonRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSitePermissionsCommonRobot.kt index dd129d4793..5665088376 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSitePermissionsCommonRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSitePermissionsCommonRobot.kt @@ -129,12 +129,19 @@ private fun assertVideoAndAudioBlockedRecommended() = onView(withId(R.id.fourth_ private fun assertCheckAutoPayRadioButtonDefault() { + // Allow audio and video onView(withId(R.id.block_radio)) .assertIsChecked(isChecked = false) + // Block audio and video on cellular data only + onView(withId(R.id.block_radio)) + .assertIsChecked(isChecked = false) + + // Block audio only onView(withId(R.id.third_radio)) .assertIsChecked(isChecked = false) + // Block audio and video onView(withId(R.id.fourth_radio)) .assertIsChecked(isChecked = true) } diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index 58ff3b3cd6..78eb832706 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -852,12 +852,6 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit view: View ): List - @CallSuper - override fun onStart() { - super.onStart() - sitePermissionWifiIntegration.get()?.maybeAddWifiConnectedListener() - } - @VisibleForTesting internal fun observeRestoreComplete(store: BrowserStore, navController: NavController) { val activity = activity as HomeActivity diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt index d839459fcd..be5fba99e1 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt @@ -602,7 +602,7 @@ sealed class Event { data class AutoPlaySettingChanged(val setting: AutoplaySetting) : Event() { enum class AutoplaySetting { - BLOCK_CELLULAR, BLOCK_AUDIO, BLOCK_ALL + BLOCK_CELLULAR, BLOCK_AUDIO, BLOCK_ALL, ALLOW_ALL } override val extras: Map? 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 e46b6ae524..dc1579f745 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/PhoneFeature.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/PhoneFeature.kt @@ -48,7 +48,7 @@ enum class PhoneFeature(val androidPermissionsList: Array) : Parcelable @StringRes val stringRes = if (isAndroidPermissionGranted(context)) { when (this) { AUTOPLAY_AUDIBLE -> - when (settings?.getAutoplayUserSetting(default = AUTOPLAY_BLOCK_ALL) ?: AUTOPLAY_BLOCK_ALL) { + when (settings?.getAutoplayUserSetting() ?: AUTOPLAY_BLOCK_ALL) { AUTOPLAY_ALLOW_ALL -> R.string.preference_option_autoplay_allowed2 AUTOPLAY_ALLOW_ON_WIFI -> R.string.preference_option_autoplay_allowed_wifi_only2 AUTOPLAY_BLOCK_AUDIBLE -> R.string.preference_option_autoplay_block_audio2 diff --git a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsFragment.kt index a87f1041ea..ce03bf9782 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsFragment.kt @@ -59,17 +59,8 @@ class SitePermissionsFragment : PreferenceFragmentCompat() { val context = requireContext() val settings = context.settings() - val summary = phoneFeature.getActionLabel(context, settings = settings) - // Remove autoplaySummary after https://bugzilla.mozilla.org/show_bug.cgi?id=1621825 is fixed - val autoplaySummary = - if (summary == context.getString(R.string.preference_option_autoplay_allowed2)) { - context.getString(R.string.preference_option_autoplay_allowed_wifi_only2) - } else { - null - } - val cameraPhoneFeatures = requirePreference(phoneFeature.getPreferenceId()) - cameraPhoneFeatures.summary = autoplaySummary ?: summary + cameraPhoneFeatures.summary = phoneFeature.getActionLabel(context, settings = settings) cameraPhoneFeatures.onPreferenceClickListener = OnPreferenceClickListener { navigateToPhoneFeature(phoneFeature) diff --git a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsManagePhoneFeatureFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsManagePhoneFeatureFragment.kt index 2644e8ac98..a5f1bd0a64 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsManagePhoneFeatureFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsManagePhoneFeatureFragment.kt @@ -79,14 +79,12 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { private fun initFirstRadio(rootView: View) { with(rootView.ask_to_allow_radio) { if (args.phoneFeature == AUTOPLAY_AUDIBLE) { - // Disabled because GV does not allow this setting. TODO Reenable after - // https://bugzilla.mozilla.org/show_bug.cgi?id=1621825 is fixed -// text = getString(R.string.preference_option_autoplay_allowed2) -// setOnClickListener { -// saveActionInSettings(it.context, AUTOPLAY_ALLOW_ALL) -// } -// restoreState(AUTOPLAY_ALLOW_ALL) - visibility = View.GONE + text = getString(R.string.preference_option_autoplay_allowed2) + setOnClickListener { + saveActionInSettings(AUTOPLAY_ALLOW_ALL) + } + restoreState(AUTOPLAY_ALLOW_ALL) + visibility = View.VISIBLE } else { text = getCombinedLabel( getString(R.string.preference_option_phone_feature_ask_to_allow), @@ -109,10 +107,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { getString(R.string.preference_option_autoplay_allowed_wifi_subtext) ) setOnClickListener { - // TODO replace with AUTOPLAY_ALLOW_ON_WIFI when - // https://bugzilla.mozilla.org/show_bug.cgi?id=1621825 is fixed. This GV bug - // makes ALLOW_ALL behave as ALLOW_ON_WIFI - saveActionInSettings(AUTOPLAY_ALLOW_ALL) + saveActionInSettings(AUTOPLAY_ALLOW_ON_WIFI) } restoreState(AUTOPLAY_ALLOW_ON_WIFI) } else { @@ -129,7 +124,10 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { with(rootView.third_radio) { if (args.phoneFeature == AUTOPLAY_AUDIBLE) { visibility = View.VISIBLE - text = getString(R.string.preference_option_autoplay_block_audio2) + text = getCombinedLabel( + getString(R.string.preference_option_autoplay_block_audio2), + getString(R.string.phone_feature_recommended) + ) setOnClickListener { saveActionInSettings(AUTOPLAY_BLOCK_AUDIBLE) } @@ -151,10 +149,8 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { with(rootView.fourth_radio) { if (args.phoneFeature == AUTOPLAY_AUDIBLE) { visibility = View.VISIBLE - text = getCombinedLabel( - getString(R.string.preference_option_autoplay_blocked3), - getString(R.string.phone_feature_recommended) - ) + text = getString(R.string.preference_option_autoplay_blocked3) + setOnClickListener { saveActionInSettings(AUTOPLAY_BLOCK_ALL) } @@ -173,7 +169,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { } private fun RadioButton.restoreState(buttonAutoplaySetting: Int) { - if (settings.getAutoplayUserSetting(AUTOPLAY_BLOCK_ALL) == buttonAutoplaySetting) { + if (settings.getAutoplayUserSetting() == buttonAutoplaySetting) { this.isChecked = true this.setStartCheckedIndicator() } @@ -194,9 +190,11 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { val setting: Event.AutoPlaySettingChanged.AutoplaySetting val (audible, inaudible) = when (autoplaySetting) { - AUTOPLAY_ALLOW_ALL, + AUTOPLAY_ALLOW_ALL -> { + setting = Event.AutoPlaySettingChanged.AutoplaySetting.ALLOW_ALL + ALLOWED to ALLOWED + } AUTOPLAY_ALLOW_ON_WIFI -> { - settings.setAutoplayUserSetting(AUTOPLAY_ALLOW_ON_WIFI) setting = Event.AutoPlaySettingChanged.AutoplaySetting.BLOCK_CELLULAR BLOCKED to BLOCKED } 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 b7a12696dd..81d80ddee7 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -40,6 +40,7 @@ import org.mozilla.fenix.settings.deletebrowsingdata.DeleteBrowsingDataOnQuitTyp import org.mozilla.fenix.settings.logins.SavedLoginsSortingStrategyMenu import org.mozilla.fenix.settings.logins.SortingStrategy import org.mozilla.fenix.settings.registerOnSharedPreferenceChangeListener +import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_BLOCK_ALL import java.security.InvalidParameterException private const val AUTOPLAY_USER_SETTING = "AUTOPLAY_USER_SETTING" @@ -744,9 +745,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { * either [AUTOPLAY_ALLOW_ALL] or [AUTOPLAY_BLOCK_ALL]. Because of this, we are forced to save * the user selected setting as well. */ - fun getAutoplayUserSetting( - default: Int - ) = preferences.getInt(AUTOPLAY_USER_SETTING, default) + fun getAutoplayUserSetting() = preferences.getInt(AUTOPLAY_USER_SETTING, AUTOPLAY_BLOCK_ALL) private fun getSitePermissionsPhoneFeatureAutoplayAction( feature: PhoneFeature, diff --git a/app/src/main/java/org/mozilla/fenix/wifi/SitePermissionsWifiIntegration.kt b/app/src/main/java/org/mozilla/fenix/wifi/SitePermissionsWifiIntegration.kt index eec7d25e6b..603c76bdc5 100644 --- a/app/src/main/java/org/mozilla/fenix/wifi/SitePermissionsWifiIntegration.kt +++ b/app/src/main/java/org/mozilla/fenix/wifi/SitePermissionsWifiIntegration.kt @@ -4,11 +4,12 @@ package org.mozilla.fenix.wifi -import mozilla.components.feature.sitepermissions.SitePermissionsRules +import androidx.annotation.VisibleForTesting +import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.ALLOWED +import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.BLOCKED import mozilla.components.support.base.feature.LifecycleAwareFeature import org.mozilla.fenix.settings.PhoneFeature import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_ALLOW_ON_WIFI -import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_BLOCK_ALL import org.mozilla.fenix.utils.Settings /** @@ -24,11 +25,11 @@ class SitePermissionsWifiIntegration( * Adds listener for autoplay setting [AUTOPLAY_ALLOW_ON_WIFI]. Sets all autoplay to allowed when * WIFI is connected, blocked otherwise. */ - private val wifiConnectedListener: ((Boolean) -> Unit) by lazy { + @VisibleForTesting + internal val wifiConnectedListener: ((Boolean) -> Unit) by lazy { { connected: Boolean -> - val setting = - if (connected) SitePermissionsRules.Action.ALLOWED else SitePermissionsRules.Action.BLOCKED - if (settings.getAutoplayUserSetting(default = AUTOPLAY_BLOCK_ALL) == AUTOPLAY_ALLOW_ON_WIFI) { + if (settings.getAutoplayUserSetting() == AUTOPLAY_ALLOW_ON_WIFI) { + val setting = if (connected) ALLOWED else BLOCKED settings.setSitePermissionsPhoneFeatureAction( PhoneFeature.AUTOPLAY_AUDIBLE, setting @@ -39,21 +40,11 @@ class SitePermissionsWifiIntegration( ) } else { // The autoplay setting has changed, we can remove the listener - removeWifiConnectedListener() + stop() } } } - /** - * If autoplay is only enabled on WIFI, sets a WIFI listener to set them accordingly. Otherwise - * noop. - */ - fun maybeAddWifiConnectedListener() { - if (settings.getAutoplayUserSetting(default = AUTOPLAY_BLOCK_ALL) == AUTOPLAY_ALLOW_ON_WIFI) { - addWifiConnectedListener() - } - } - fun addWifiConnectedListener() { wifiConnectionMonitor.addOnWifiConnectedChangedListener(wifiConnectedListener) } @@ -62,15 +53,15 @@ class SitePermissionsWifiIntegration( wifiConnectionMonitor.removeOnWifiConnectedChangedListener(wifiConnectedListener) } - // Until https://bugzilla.mozilla.org/show_bug.cgi?id=1621825 is fixed, AUTOPLAY_ALLOW_ALL - // only works while WIFI is active, so we are not using AUTOPLAY_ALLOW_ON_WIFI (or this class). - // Once that is fixed, [start] and [maybeAddWifiConnectedListener] will need to be called on - // activity startup. override fun start() { - wifiConnectionMonitor.start() + if (settings.getAutoplayUserSetting() == AUTOPLAY_ALLOW_ON_WIFI) { + wifiConnectionMonitor.start() + addWifiConnectedListener() + } } override fun stop() { wifiConnectionMonitor.stop() + removeWifiConnectedListener() } } diff --git a/app/src/main/java/org/mozilla/fenix/wifi/WifiConnectionMonitor.kt b/app/src/main/java/org/mozilla/fenix/wifi/WifiConnectionMonitor.kt index 4d3b636aa3..682a2f1e0f 100644 --- a/app/src/main/java/org/mozilla/fenix/wifi/WifiConnectionMonitor.kt +++ b/app/src/main/java/org/mozilla/fenix/wifi/WifiConnectionMonitor.kt @@ -10,6 +10,7 @@ import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest +import androidx.annotation.VisibleForTesting /** * Attaches itself to the [Application] and listens for WIFI available/not available events. This @@ -26,14 +27,22 @@ import android.net.NetworkRequest * ``` */ class WifiConnectionMonitor(app: Application) { - private val callbacks = mutableListOf<(Boolean) -> Unit>() - private val connectivityManager = app.getSystemService(Context.CONNECTIVITY_SERVICE) as + @VisibleForTesting + internal val callbacks = mutableListOf<(Boolean) -> Unit>() + + @VisibleForTesting + internal var connectivityManager = app.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - private var lastKnownStateWasAvailable: Boolean? = null - private var isRegistered = false + @VisibleForTesting + internal var lastKnownStateWasAvailable: Boolean? = null + + @VisibleForTesting + internal var isRegistered = false + @Synchronized set - private val frameworkListener = object : ConnectivityManager.NetworkCallback() { + @VisibleForTesting + internal val frameworkListener = object : ConnectivityManager.NetworkCallback() { override fun onLost(network: Network) { notifyListeners(false) lastKnownStateWasAvailable = false @@ -86,6 +95,8 @@ class WifiConnectionMonitor(app: Application) { if (!isRegistered) return connectivityManager.unregisterNetworkCallback(frameworkListener) isRegistered = false + lastKnownStateWasAvailable = null + callbacks.clear() } /** diff --git a/app/src/test/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsFragmentStoreTest.kt b/app/src/test/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsFragmentStoreTest.kt index 0a790ce049..a5cff8b24d 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsFragmentStoreTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsFragmentStoreTest.kt @@ -125,7 +125,7 @@ class QuickSettingsFragmentStoreTest { every { permissions.mediaKeySystemAccess } returns SitePermissions.Status.NO_DECISION every { permissions.autoplayAudible } returns SitePermissions.AutoplayStatus.ALLOWED every { permissions.autoplayInaudible } returns SitePermissions.AutoplayStatus.BLOCKED - every { appSettings.getAutoplayUserSetting(any()) } returns AUTOPLAY_BLOCK_ALL + every { appSettings.getAutoplayUserSetting() } returns AUTOPLAY_BLOCK_ALL val state = QuickSettingsFragmentStore.createWebsitePermissionState( context, permissions, permissionHighlights, appSettings diff --git a/app/src/test/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsWifiIntegrationTest.kt b/app/src/test/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsWifiIntegrationTest.kt new file mode 100644 index 0000000000..61e9c7484a --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsWifiIntegrationTest.kt @@ -0,0 +1,132 @@ +/* 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.sitepermissions + +import io.mockk.every +import io.mockk.verify +import io.mockk.mockk +import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.ALLOWED +import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.BLOCKED +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner +import org.mozilla.fenix.settings.PhoneFeature.AUTOPLAY_AUDIBLE +import org.mozilla.fenix.settings.PhoneFeature.AUTOPLAY_INAUDIBLE +import org.mozilla.fenix.utils.Settings +import org.mozilla.fenix.wifi.SitePermissionsWifiIntegration +import org.mozilla.fenix.wifi.WifiConnectionMonitor + +@RunWith(FenixRobolectricTestRunner::class) +class SitePermissionsWifiIntegrationTest { + lateinit var settings: Settings + lateinit var wifiIntegration: SitePermissionsWifiIntegration + lateinit var wifiConnectionMonitor: WifiConnectionMonitor + + @Before + fun setUp() { + settings = mockk(relaxed = true) + wifiConnectionMonitor = mockk(relaxed = true) + wifiIntegration = SitePermissionsWifiIntegration(settings, wifiConnectionMonitor) + } + + @Test + fun `GIVEN auto play is set to be on allow only on wifi WHEN the feature starts THEN listen for wifi changes`() { + every { settings.getAutoplayUserSetting() } returns AUTOPLAY_ALLOW_ON_WIFI + + wifiIntegration.start() + + verify(exactly = 1) { + wifiConnectionMonitor.start() + } + verify(exactly = 1) { + wifiConnectionMonitor.addOnWifiConnectedChangedListener(wifiIntegration.wifiConnectedListener) + } + } + + @Test + fun `GIVEN auto play is not set to allow only on wifi WHEN the feature starts THEN will not listen for wifi changes`() { + val autoPlaySettings = + listOf(AUTOPLAY_BLOCK_ALL, AUTOPLAY_BLOCK_AUDIBLE, AUTOPLAY_ALLOW_ALL) + + autoPlaySettings.forEach { autoPlaySetting -> + every { settings.getAutoplayUserSetting() } returns autoPlaySetting + + wifiIntegration.start() + + verify(exactly = 0) { + wifiConnectionMonitor.addOnWifiConnectedChangedListener(wifiIntegration.wifiConnectedListener) + } + verify(exactly = 0) { + wifiConnectionMonitor.addOnWifiConnectedChangedListener(wifiIntegration.wifiConnectedListener) + } + } + } + + @Test + fun `WHEN stopping the feature THEN all listeners will be removed`() { + wifiIntegration.stop() + + verify(exactly = 1) { + wifiConnectionMonitor.stop() + } + verify(exactly = 1) { + wifiConnectionMonitor.removeOnWifiConnectedChangedListener(wifiIntegration.wifiConnectedListener) + } + } + + @Test + fun `GIVEN wifi is connected and autoplay is set to allow only on wifi WHEN wifi changes to connected THEN the autoplay setting must be allowed`() { + every { settings.getAutoplayUserSetting() } returns AUTOPLAY_ALLOW_ON_WIFI + + wifiIntegration.wifiConnectedListener(true) + + verify(exactly = 1) { + settings.setSitePermissionsPhoneFeatureAction(AUTOPLAY_AUDIBLE, ALLOWED) + } + verify(exactly = 1) { + settings.setSitePermissionsPhoneFeatureAction(AUTOPLAY_INAUDIBLE, ALLOWED) + } + } + + @Test + fun `GIVEN wifi is connected and autoplay is set to allow only on wifi WHEN wifi changes to not connected THEN the autoplay setting must be blocked`() { + every { settings.getAutoplayUserSetting() } returns AUTOPLAY_ALLOW_ON_WIFI + + wifiIntegration.wifiConnectedListener(false) + + verify(exactly = 1) { + settings.setSitePermissionsPhoneFeatureAction(AUTOPLAY_AUDIBLE, BLOCKED) + } + + verify(exactly = 1) { + settings.setSitePermissionsPhoneFeatureAction(AUTOPLAY_INAUDIBLE, BLOCKED) + } + } + + @Test + fun `GIVEN wifi is connected and autoplay is different from allow on wifi WHEN wifi changes THEN all the wifi listener will be stopped`() { + val autoPlaySettings = listOf(AUTOPLAY_BLOCK_ALL, AUTOPLAY_BLOCK_AUDIBLE, AUTOPLAY_ALLOW_ALL) + + autoPlaySettings.forEach { autoPlaySetting -> + every { settings.getAutoplayUserSetting() } returns autoPlaySetting + + wifiIntegration.wifiConnectedListener(true) + wifiIntegration.wifiConnectedListener(false) + + verify(atLeast = 1) { + wifiConnectionMonitor.stop() + wifiConnectionMonitor.removeOnWifiConnectedChangedListener(wifiIntegration.wifiConnectedListener) + } + verify(atLeast = 1) { + wifiConnectionMonitor.removeOnWifiConnectedChangedListener(wifiIntegration.wifiConnectedListener) + } + + verify(exactly = 0) { + settings.setSitePermissionsPhoneFeatureAction(any(), any()) + } + } + } +} 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 26c5ec4e71..a726b0bcb5 100644 --- a/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt +++ b/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt @@ -593,6 +593,21 @@ class SettingsTest { ) } + @Test + fun getSitePermissionsCustomSettingsRules_autoplay_defaults() { + val settings = Settings(testContext) + + assertEquals( + AutoplayAction.BLOCKED, + settings.getSitePermissionsCustomSettingsRules().autoplayAudible + ) + + assertEquals( + AutoplayAction.BLOCKED, + settings.getSitePermissionsCustomSettingsRules().autoplayInaudible + ) + } + @Test fun getSitePermissionsCustomSettingsRules_persistentStorage() { settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.PERSISTENT_STORAGE, ALLOWED) diff --git a/app/src/test/java/org/mozilla/fenix/wifi/WifiConnectionMonitorTest.kt b/app/src/test/java/org/mozilla/fenix/wifi/WifiConnectionMonitorTest.kt new file mode 100644 index 0000000000..3f688fc544 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/wifi/WifiConnectionMonitorTest.kt @@ -0,0 +1,193 @@ +/* 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.wifi + +import android.app.Application +import android.net.ConnectivityManager +import io.mockk.mockk +import io.mockk.spyk +import io.mockk.verify +import mozilla.components.support.test.mock +import mozilla.components.support.test.robolectric.testContext +import org.junit.Assert.assertTrue +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNull +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner +import org.mozilla.fenix.utils.Settings + +@RunWith(FenixRobolectricTestRunner::class) +class WifiConnectionMonitorTest { + lateinit var settings: Settings + lateinit var connectivityManager: ConnectivityManager + lateinit var wifiConnectionMonitor: WifiConnectionMonitor + + @Before + fun setUp() { + settings = mockk(relaxed = true) + wifiConnectionMonitor = WifiConnectionMonitor(testContext as Application) + connectivityManager = spyk(wifiConnectionMonitor.connectivityManager) + wifiConnectionMonitor.connectivityManager = connectivityManager + } + + @Test + fun `WHEN the feature starts THEN all the network callbacks must be registered`() { + val spyWifiConnectionMonitor = spyk(wifiConnectionMonitor) + + spyWifiConnectionMonitor.connectivityManager = connectivityManager + + spyWifiConnectionMonitor.start() + + verify(exactly = 1) { + connectivityManager.registerNetworkCallback( + any(), + wifiConnectionMonitor.frameworkListener + ) + } + + verify(exactly = 1) { + spyWifiConnectionMonitor.notifyListeners(false) + } + + assertTrue(spyWifiConnectionMonitor.isRegistered) + assertFalse(spyWifiConnectionMonitor.lastKnownStateWasAvailable!!) + } + + @Test + fun `WHEN the feature starts multiple times THEN the network callbacks must be registered once`() { + wifiConnectionMonitor.isRegistered = true + + wifiConnectionMonitor.start() + wifiConnectionMonitor.start() + + verify(exactly = 0) { + connectivityManager.registerNetworkCallback( + any(), + wifiConnectionMonitor.frameworkListener + ) + } + } + + @Test + fun `WHEN the feature stops THEN the network callbacks must be unregistered`() { + wifiConnectionMonitor.start() + wifiConnectionMonitor.stop() + + verify { + wifiConnectionMonitor.connectivityManager.unregisterNetworkCallback( + wifiConnectionMonitor.frameworkListener + ) + } + + assertFalse(wifiConnectionMonitor.isRegistered) + assertTrue(wifiConnectionMonitor.callbacks.isEmpty()) + assertNull(wifiConnectionMonitor.lastKnownStateWasAvailable) + } + + @Test + fun `WHEN the feature gets stopped multiple time THEN the network callbacks must be unregistered once`() { + wifiConnectionMonitor.isRegistered = false + + wifiConnectionMonitor.stop() + + verify(exactly = 0) { + connectivityManager.unregisterNetworkCallback(wifiConnectionMonitor.frameworkListener) + } + } + + @Test + fun `WHEN adding a listener THEN should be added to the callback queue`() { + + wifiConnectionMonitor.addOnWifiConnectedChangedListener({}) + + assertFalse(wifiConnectionMonitor.callbacks.isEmpty()) + } + + @Test + fun `GIVEN a network status is known WHEN adding a new listener THEN the listener will be notified`() { + var wasNotified: Boolean? = null + wifiConnectionMonitor.lastKnownStateWasAvailable = false + + wifiConnectionMonitor.addOnWifiConnectedChangedListener { + wasNotified = it + } + + assertFalse(wasNotified!!) + assertFalse(wifiConnectionMonitor.callbacks.isEmpty()) + } + + @Test + fun `WHEN removing a listener THEN it will be removed from the listeners queue`() { + + assertTrue(wifiConnectionMonitor.callbacks.isEmpty()) + + val callback: (Boolean) -> Unit = {} + wifiConnectionMonitor.addOnWifiConnectedChangedListener(callback) + + assertFalse(wifiConnectionMonitor.callbacks.isEmpty()) + + wifiConnectionMonitor.removeOnWifiConnectedChangedListener(callback) + + assertTrue(wifiConnectionMonitor.callbacks.isEmpty()) + } + + @Test + fun `WHEN the connection is lost THEN listeners will be notified`() { + var wasNotified: Boolean? = null + + val callback: (Boolean) -> Unit = { wasNotified = it } + + wifiConnectionMonitor.addOnWifiConnectedChangedListener(callback) + wifiConnectionMonitor.frameworkListener.onLost(mock()) + + assertFalse(wasNotified!!) + } + + @Test + fun `WHEN the connection is available THEN listeners will be notified`() { + var wasNotified: Boolean? = null + + val callback: (Boolean) -> Unit = { wasNotified = it } + + wifiConnectionMonitor.addOnWifiConnectedChangedListener(callback) + wifiConnectionMonitor.frameworkListener.onAvailable(mock()) + + assertTrue(wasNotified!!) + } + + @Test + fun `GIVEN multiple listeners were added WHEN there is an update THEN all listeners must be notified`() { + var wasNotified1: Boolean? = null + var wasNotified2: Boolean? = null + + val callback1: (Boolean) -> Unit = { wasNotified1 = it } + val callback2: (Boolean) -> Unit = { wasNotified2 = it } + + wifiConnectionMonitor.addOnWifiConnectedChangedListener(callback1) + wifiConnectionMonitor.addOnWifiConnectedChangedListener(callback2) + wifiConnectionMonitor.notifyListeners(true) + + assertTrue(wasNotified1!!) + assertTrue(wasNotified2!!) + } + + @Test + fun `GIVEN multiple listeners are are added and notify THEN a ConcurrentModificationException must not be thrown`() { + repeat(100) { + + // Adding to callbacks. + wifiConnectionMonitor.addOnWifiConnectedChangedListener { + // Altering callbacks while looping. + if (wifiConnectionMonitor.callbacks.isNotEmpty()) + wifiConnectionMonitor.callbacks.removeFirst() + } + + // Looping over callbacks. + wifiConnectionMonitor.notifyListeners(true) + } + } +}