For #6354 - Removes ETP Experiment, Removes Feature Flags, Sets Strict Default
parent
1ff5a1934e
commit
d9615108ee
|
@ -1,53 +0,0 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
package org.mozilla.fenix
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import mozilla.components.service.experiments.Experiments
|
|
||||||
import org.mozilla.fenix.ext.components
|
|
||||||
import org.mozilla.fenix.ext.settings
|
|
||||||
|
|
||||||
object ExperimentsManager {
|
|
||||||
fun optOutEtpExperiment(context: Context) {
|
|
||||||
// If a user can see the ETP categories we don't want to change their settings
|
|
||||||
if (FeatureFlags.etpCategories) return
|
|
||||||
// Release user has opted out of ETP experiment, reset them to current default (strict)
|
|
||||||
context.settings().setUseStrictTrackingProtection()
|
|
||||||
context.components.useCases.settingsUseCases.updateTrackingProtection(
|
|
||||||
context.components.core.createTrackingProtectionPolicy()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun initEtpExperiment(context: Context) {
|
|
||||||
// When the `fenix-etp-5651` experiment is active, set up ETP settings and GV policy.
|
|
||||||
// Note that this will not take effect the first time the application has launched,
|
|
||||||
// since there won't be enough time for the experiments library to get a list of experiments.
|
|
||||||
// It will take effect the second time the application is launched.
|
|
||||||
Experiments.withExperiment("fenix-etp-5651") { branchName ->
|
|
||||||
when (branchName) {
|
|
||||||
"control_strict" -> {
|
|
||||||
context.settings().setUseStrictTrackingProtection()
|
|
||||||
context.components.useCases.settingsUseCases.updateTrackingProtection(
|
|
||||||
context.components.core.createTrackingProtectionPolicy()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
"treatment_standard" -> {
|
|
||||||
context.settings().setUseStandardTrackingProtection()
|
|
||||||
context.components.core.createTrackingProtectionPolicy()
|
|
||||||
context.components.useCases.settingsUseCases.updateTrackingProtection(
|
|
||||||
context.components.core.createTrackingProtectionPolicy()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
// No branch matches so we're defaulting to strict
|
|
||||||
context.settings().setUseStrictTrackingProtection()
|
|
||||||
context.components.useCases.settingsUseCases.updateTrackingProtection(
|
|
||||||
context.components.core.createTrackingProtectionPolicy()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,11 +24,6 @@ object FeatureFlags {
|
||||||
*/
|
*/
|
||||||
const val mediaIntegration = true
|
const val mediaIntegration = true
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the categories blocked by ETP in a panel in the toolbar
|
|
||||||
*/
|
|
||||||
val etpCategories = Config.channel.isNightlyOrDebug
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gives option in Settings to disable auto play media
|
* Gives option in Settings to disable auto play media
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -42,7 +42,6 @@ import java.io.File
|
||||||
open class FenixApplication : Application() {
|
open class FenixApplication : Application() {
|
||||||
lateinit var fretboard: Fretboard
|
lateinit var fretboard: Fretboard
|
||||||
lateinit var experimentLoader: Deferred<Boolean>
|
lateinit var experimentLoader: Deferred<Boolean>
|
||||||
var experimentLoaderComplete: Boolean = false
|
|
||||||
|
|
||||||
open val components by lazy { Components(this) }
|
open val components by lazy { Components(this) }
|
||||||
|
|
||||||
|
@ -87,10 +86,6 @@ open class FenixApplication : Application() {
|
||||||
httpClient = lazy(LazyThreadSafetyMode.NONE) { components.core.client }
|
httpClient = lazy(LazyThreadSafetyMode.NONE) { components.core.client }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
// We should make a better way to opt out for when we have more experiments
|
|
||||||
// See https://github.com/mozilla-mobile/fenix/issues/6278
|
|
||||||
ExperimentsManager.optOutEtpExperiment(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the `fenix-test-2019-08-05` experiment is active, record its branch in Glean
|
// When the `fenix-test-2019-08-05` experiment is active, record its branch in Glean
|
||||||
|
@ -103,8 +98,6 @@ open class FenixApplication : Application() {
|
||||||
ExperimentsMetrics.activeExperiment.set(branchName)
|
ExperimentsMetrics.activeExperiment.set(branchName)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExperimentsManager.initEtpExperiment(this)
|
|
||||||
|
|
||||||
setupLeakCanary()
|
setupLeakCanary()
|
||||||
if (settings().isTelemetryEnabled) {
|
if (settings().isTelemetryEnabled) {
|
||||||
components.analytics.metrics.start()
|
components.analytics.metrics.start()
|
||||||
|
|
|
@ -42,7 +42,6 @@ import mozilla.components.lib.state.ext.consumeFrom
|
||||||
import mozilla.components.support.base.feature.BackHandler
|
import mozilla.components.support.base.feature.BackHandler
|
||||||
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
|
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
|
||||||
import org.jetbrains.anko.dimen
|
import org.jetbrains.anko.dimen
|
||||||
import org.mozilla.fenix.FeatureFlags
|
|
||||||
import org.mozilla.fenix.HomeActivity
|
import org.mozilla.fenix.HomeActivity
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.browser.readermode.DefaultReaderModeController
|
import org.mozilla.fenix.browser.readermode.DefaultReaderModeController
|
||||||
|
@ -217,7 +216,6 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
|
||||||
sessionId = session.id,
|
sessionId = session.id,
|
||||||
url = session.url,
|
url = session.url,
|
||||||
isSecured = session.securityInfo.secure,
|
isSecured = session.securityInfo.secure,
|
||||||
isTrackingProtectionOn = session.trackerBlockingEnabled,
|
|
||||||
sitePermissions = sitePermissions,
|
sitePermissions = sitePermissions,
|
||||||
gravity = getAppropriateLayoutGravity()
|
gravity = getAppropriateLayoutGravity()
|
||||||
)
|
)
|
||||||
|
@ -360,9 +358,6 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showTrackingProtectionOnboarding() {
|
private fun showTrackingProtectionOnboarding() {
|
||||||
if (!FeatureFlags.etpCategories) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
context?.let {
|
context?.let {
|
||||||
val layout = LayoutInflater.from(it)
|
val layout = LayoutInflater.from(it)
|
||||||
.inflate(R.layout.tracking_protection_onboarding_popup, null)
|
.inflate(R.layout.tracking_protection_onboarding_popup, null)
|
||||||
|
|
|
@ -20,7 +20,6 @@ import mozilla.components.feature.toolbar.ToolbarPresenter
|
||||||
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
||||||
import mozilla.components.support.base.feature.LifecycleAwareFeature
|
import mozilla.components.support.base.feature.LifecycleAwareFeature
|
||||||
import mozilla.components.support.ktx.android.view.hideKeyboard
|
import mozilla.components.support.ktx.android.view.hideKeyboard
|
||||||
import org.mozilla.fenix.FeatureFlags
|
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
import org.mozilla.fenix.ext.settings
|
import org.mozilla.fenix.ext.settings
|
||||||
|
@ -62,19 +61,22 @@ class ToolbarIntegration(
|
||||||
val lottieDrawable = LottieDrawable()
|
val lottieDrawable = LottieDrawable()
|
||||||
lottieDrawable.composition = result
|
lottieDrawable.composition = result
|
||||||
|
|
||||||
toolbar.display.indicators = if (
|
toolbar.display.indicators =
|
||||||
context.settings().shouldUseTrackingProtection && FeatureFlags.etpCategories
|
if (context.settings().shouldUseTrackingProtection) {
|
||||||
) {
|
listOf(
|
||||||
listOf(
|
DisplayToolbar.Indicators.TRACKING_PROTECTION,
|
||||||
DisplayToolbar.Indicators.TRACKING_PROTECTION,
|
DisplayToolbar.Indicators.SECURITY,
|
||||||
DisplayToolbar.Indicators.SECURITY,
|
DisplayToolbar.Indicators.EMPTY
|
||||||
DisplayToolbar.Indicators.EMPTY)
|
)
|
||||||
} else {
|
} else {
|
||||||
listOf(DisplayToolbar.Indicators.SECURITY, DisplayToolbar.Indicators.EMPTY)
|
listOf(
|
||||||
}
|
DisplayToolbar.Indicators.SECURITY,
|
||||||
|
DisplayToolbar.Indicators.EMPTY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
toolbar.display.displayIndicatorSeparator =
|
toolbar.display.displayIndicatorSeparator =
|
||||||
context.settings().shouldUseTrackingProtection && FeatureFlags.etpCategories
|
context.settings().shouldUseTrackingProtection
|
||||||
|
|
||||||
toolbar.display.icons = toolbar.display.icons.copy(
|
toolbar.display.icons = toolbar.display.icons.copy(
|
||||||
emptyIcon = AppCompatResources.getDrawable(
|
emptyIcon = AppCompatResources.getDrawable(
|
||||||
|
|
|
@ -18,7 +18,6 @@ import mozilla.components.browser.toolbar.display.DisplayToolbar
|
||||||
import mozilla.components.feature.customtabs.CustomTabsToolbarFeature
|
import mozilla.components.feature.customtabs.CustomTabsToolbarFeature
|
||||||
import mozilla.components.support.base.feature.BackHandler
|
import mozilla.components.support.base.feature.BackHandler
|
||||||
import mozilla.components.support.base.feature.LifecycleAwareFeature
|
import mozilla.components.support.base.feature.LifecycleAwareFeature
|
||||||
import org.mozilla.fenix.FeatureFlags
|
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.components.toolbar.ToolbarMenu
|
import org.mozilla.fenix.components.toolbar.ToolbarMenu
|
||||||
import org.mozilla.fenix.ext.settings
|
import org.mozilla.fenix.ext.settings
|
||||||
|
@ -66,7 +65,7 @@ class CustomTabsIntegration(
|
||||||
lottieDrawable.composition = result
|
lottieDrawable.composition = result
|
||||||
|
|
||||||
toolbar.display.displayIndicatorSeparator = false
|
toolbar.display.displayIndicatorSeparator = false
|
||||||
if (activity.settings().shouldUseTrackingProtection && FeatureFlags.etpCategories) {
|
if (activity.settings().shouldUseTrackingProtection) {
|
||||||
toolbar.display.indicators = listOf(
|
toolbar.display.indicators = listOf(
|
||||||
DisplayToolbar.Indicators.SECURITY,
|
DisplayToolbar.Indicators.SECURITY,
|
||||||
DisplayToolbar.Indicators.TRACKING_PROTECTION
|
DisplayToolbar.Indicators.TRACKING_PROTECTION
|
||||||
|
|
|
@ -157,7 +157,6 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler {
|
||||||
sessionId = session.id,
|
sessionId = session.id,
|
||||||
url = session.url,
|
url = session.url,
|
||||||
isSecured = session.securityInfo.secure,
|
isSecured = session.securityInfo.secure,
|
||||||
isTrackingProtectionOn = session.trackerBlockingEnabled,
|
|
||||||
sitePermissions = sitePermissions,
|
sitePermissions = sitePermissions,
|
||||||
gravity = getAppropriateLayoutGravity()
|
gravity = getAppropriateLayoutGravity()
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,7 +11,6 @@ import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.SwitchPreference
|
import androidx.preference.SwitchPreference
|
||||||
import org.mozilla.fenix.BrowserDirection
|
import org.mozilla.fenix.BrowserDirection
|
||||||
import org.mozilla.fenix.FeatureFlags
|
|
||||||
import org.mozilla.fenix.HomeActivity
|
import org.mozilla.fenix.HomeActivity
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
import org.mozilla.fenix.components.metrics.Event
|
||||||
|
@ -88,9 +87,8 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindStrict() {
|
private fun bindStrict() {
|
||||||
val keyStrict = getString(R.string.pref_key_tracking_protection_strict)
|
val keyStrict = getString(R.string.pref_key_tracking_protection_strict_default)
|
||||||
radioStrict = requireNotNull(findPreference(keyStrict))
|
radioStrict = requireNotNull(findPreference(keyStrict))
|
||||||
radioStrict.isVisible = FeatureFlags.etpCategories
|
|
||||||
radioStrict.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
|
radioStrict.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
|
||||||
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
|
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
|
||||||
if (newValue == true) {
|
if (newValue == true) {
|
||||||
|
@ -114,9 +112,8 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindStandard() {
|
private fun bindStandard() {
|
||||||
val keyStandard = getString(R.string.pref_key_tracking_protection_standard)
|
val keyStandard = getString(R.string.pref_key_tracking_protection_standard_option)
|
||||||
radioStandard = requireNotNull(findPreference(keyStandard))
|
radioStandard = requireNotNull(findPreference(keyStandard))
|
||||||
radioStandard.isVisible = FeatureFlags.etpCategories
|
|
||||||
radioStandard.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
|
radioStandard.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
|
||||||
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
|
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
|
||||||
if (newValue == true) {
|
if (newValue == true) {
|
||||||
|
|
|
@ -9,19 +9,13 @@ import androidx.annotation.VisibleForTesting
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.ObsoleteCoroutinesApi
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import mozilla.components.browser.session.Session
|
import mozilla.components.browser.session.Session
|
||||||
import mozilla.components.feature.session.SessionUseCases.ReloadUrlUseCase
|
import mozilla.components.feature.session.SessionUseCases.ReloadUrlUseCase
|
||||||
import mozilla.components.feature.session.TrackingProtectionUseCases
|
|
||||||
import mozilla.components.feature.sitepermissions.SitePermissions
|
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||||
import mozilla.components.feature.tabs.TabsUseCases.AddNewTabUseCase
|
import mozilla.components.feature.tabs.TabsUseCases.AddNewTabUseCase
|
||||||
import mozilla.components.support.base.feature.OnNeedToRequestPermissions
|
import mozilla.components.support.base.feature.OnNeedToRequestPermissions
|
||||||
import org.mozilla.fenix.browser.BrowserFragment
|
|
||||||
import org.mozilla.fenix.components.PermissionStorage
|
import org.mozilla.fenix.components.PermissionStorage
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
|
||||||
import org.mozilla.fenix.ext.metrics
|
|
||||||
import org.mozilla.fenix.settings.PhoneFeature
|
import org.mozilla.fenix.settings.PhoneFeature
|
||||||
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled
|
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled
|
||||||
import org.mozilla.fenix.settings.toggle
|
import org.mozilla.fenix.settings.toggle
|
||||||
|
@ -34,29 +28,6 @@ import org.mozilla.fenix.utils.Settings
|
||||||
* complex Android interactions or communication with other features.
|
* complex Android interactions or communication with other features.
|
||||||
*/
|
*/
|
||||||
interface QuickSettingsController {
|
interface QuickSettingsController {
|
||||||
/**
|
|
||||||
* Handles turning on/off tracking protection.
|
|
||||||
*
|
|
||||||
* */
|
|
||||||
fun handleTrackingProtectionToggled(trackingEnabled: Boolean)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles showing the tracking protection settings.
|
|
||||||
*/
|
|
||||||
fun handleTrackingProtectionSettingsSelected()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles reporting a webcompat issue for the indicated website.
|
|
||||||
*
|
|
||||||
* @param websiteUrl [String] the URL of the web page for which to report a site issue.
|
|
||||||
*/
|
|
||||||
fun handleReportTrackingProblem(websiteUrl: String)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the case of the [TrackingProtectionView] needed to be displayed to the user.
|
|
||||||
*/
|
|
||||||
fun handleTrackingProtectionShown()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the case of the [WebsitePermissionsView] needed to be displayed to the user.
|
* Handles the case of the [WebsitePermissionsView] needed to be displayed to the user.
|
||||||
*/
|
*/
|
||||||
|
@ -94,10 +65,8 @@ interface QuickSettingsController {
|
||||||
* @param requestRuntimePermissions [OnNeedToRequestPermissions] callback allowing for requesting
|
* @param requestRuntimePermissions [OnNeedToRequestPermissions] callback allowing for requesting
|
||||||
* specific Android runtime permissions.
|
* specific Android runtime permissions.
|
||||||
* @param reportSiteIssue callback allowing to report an issue with the current web page.
|
* @param reportSiteIssue callback allowing to report an issue with the current web page.
|
||||||
* @param displayTrackingProtection callback for when the [TrackingProtectionView] needs to be displayed.
|
|
||||||
* @param displayPermissions callback for when [WebsitePermissionsView] needs to be displayed.
|
* @param displayPermissions callback for when [WebsitePermissionsView] needs to be displayed.
|
||||||
* @param dismiss callback allowing to request this entire Fragment to be dismissed.
|
* @param dismiss callback allowing to request this entire Fragment to be dismissed.
|
||||||
* @param trackingProtectionUseCases usecase allowing us to add or remove tracking protection exceptions
|
|
||||||
*/
|
*/
|
||||||
@Suppress("TooManyFunctions")
|
@Suppress("TooManyFunctions")
|
||||||
class DefaultQuickSettingsController(
|
class DefaultQuickSettingsController(
|
||||||
|
@ -113,55 +82,9 @@ class DefaultQuickSettingsController(
|
||||||
private val addNewTab: AddNewTabUseCase,
|
private val addNewTab: AddNewTabUseCase,
|
||||||
private val requestRuntimePermissions: OnNeedToRequestPermissions = { },
|
private val requestRuntimePermissions: OnNeedToRequestPermissions = { },
|
||||||
private val reportSiteIssue: () -> Unit,
|
private val reportSiteIssue: () -> Unit,
|
||||||
private val displayTrackingProtection: () -> Unit,
|
|
||||||
private val displayPermissions: () -> Unit,
|
private val displayPermissions: () -> Unit,
|
||||||
private val dismiss: () -> Unit,
|
private val dismiss: () -> Unit
|
||||||
private val trackingProtectionUseCases: TrackingProtectionUseCases
|
|
||||||
) : QuickSettingsController {
|
) : QuickSettingsController {
|
||||||
|
|
||||||
override fun handleTrackingProtectionToggled(
|
|
||||||
trackingEnabled: Boolean
|
|
||||||
) {
|
|
||||||
session?.let {
|
|
||||||
if (trackingEnabled) {
|
|
||||||
trackingProtectionUseCases.removeException(it)
|
|
||||||
} else {
|
|
||||||
context.metrics.track(Event.TrackingProtectionException)
|
|
||||||
trackingProtectionUseCases.addException(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reload(session)
|
|
||||||
|
|
||||||
quickSettingsStore.dispatch(
|
|
||||||
TrackingProtectionAction.TrackingProtectionToggled(trackingEnabled)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleTrackingProtectionSettingsSelected() {
|
|
||||||
val directions =
|
|
||||||
QuickSettingsSheetDialogFragmentDirections
|
|
||||||
.actionQuickSettingsSheetDialogFragmentToTrackingProtectionFragment()
|
|
||||||
navController.navigate(directions)
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExperimentalCoroutinesApi
|
|
||||||
@UseExperimental(ObsoleteCoroutinesApi::class)
|
|
||||||
override fun handleReportTrackingProblem(websiteUrl: String) {
|
|
||||||
val reportUrl = String.format(BrowserFragment.REPORT_SITE_ISSUE_URL, websiteUrl)
|
|
||||||
addNewTab(reportUrl)
|
|
||||||
|
|
||||||
if (session?.isCustomTabSession() == true) {
|
|
||||||
reportSiteIssue()
|
|
||||||
}
|
|
||||||
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleTrackingProtectionShown() {
|
|
||||||
displayTrackingProtection()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handlePermissionsShown() {
|
override fun handlePermissionsShown() {
|
||||||
displayPermissions()
|
displayPermissions()
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@ import mozilla.components.lib.state.Action
|
||||||
import mozilla.components.lib.state.Reducer
|
import mozilla.components.lib.state.Reducer
|
||||||
import mozilla.components.lib.state.State
|
import mozilla.components.lib.state.State
|
||||||
import mozilla.components.lib.state.Store
|
import mozilla.components.lib.state.Store
|
||||||
import org.mozilla.fenix.FeatureFlags
|
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.settings.PhoneFeature
|
import org.mozilla.fenix.settings.PhoneFeature
|
||||||
|
import org.mozilla.fenix.settings.quicksettings.QuickSettingsFragmentStore.Companion.createStore
|
||||||
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled
|
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled
|
||||||
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeVisible
|
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeVisible
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
@ -68,8 +68,6 @@ class QuickSettingsFragmentStore(
|
||||||
* @param context [Context] used for access to various Android resources.
|
* @param context [Context] used for access to various Android resources.
|
||||||
* @param websiteUrl [String] the URL of the current web page.
|
* @param websiteUrl [String] the URL of the current web page.
|
||||||
* @param isSecured [Boolean] whether the connection is secured (TLS) or not.
|
* @param isSecured [Boolean] whether the connection is secured (TLS) or not.
|
||||||
* @param isTrackingProtectionOn [Boolean] whether the "Standard" (as in not "Strict")
|
|
||||||
* tracking protection is enabled for the current website or not.
|
|
||||||
* @param permissions [SitePermissions]? list of website permissions and their status.
|
* @param permissions [SitePermissions]? list of website permissions and their status.
|
||||||
* @param settings [Settings] application settings.
|
* @param settings [Settings] application settings.
|
||||||
*/
|
*/
|
||||||
|
@ -78,40 +76,19 @@ class QuickSettingsFragmentStore(
|
||||||
context: Context,
|
context: Context,
|
||||||
websiteUrl: String,
|
websiteUrl: String,
|
||||||
isSecured: Boolean,
|
isSecured: Boolean,
|
||||||
isTrackingProtectionOn: Boolean,
|
|
||||||
permissions: SitePermissions?,
|
permissions: SitePermissions?,
|
||||||
settings: Settings
|
settings: Settings
|
||||||
) = QuickSettingsFragmentStore(
|
) = QuickSettingsFragmentStore(
|
||||||
QuickSettingsFragmentState(
|
QuickSettingsFragmentState(
|
||||||
trackingProtectionState = createTrackingProtectionState(websiteUrl, isTrackingProtectionOn, settings),
|
|
||||||
webInfoState = createWebsiteInfoState(websiteUrl, isSecured),
|
webInfoState = createWebsiteInfoState(websiteUrl, isSecured),
|
||||||
websitePermissionsState = createWebsitePermissionState(context, permissions, settings)
|
websitePermissionsState = createWebsitePermissionState(
|
||||||
|
context,
|
||||||
|
permissions,
|
||||||
|
settings
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct an initial [TrackingProtectionState] to be rendered by [TrackingProtectionView]
|
|
||||||
* based on the current state of the app / website.
|
|
||||||
*
|
|
||||||
* Users can modify the returned [TrackingProtectionState] after it is initially displayed.
|
|
||||||
*
|
|
||||||
* @param websiteUrl [String] the URL of the current web page.
|
|
||||||
* @param isTrackingProtectionOn [Boolean] whether the "Standard" (as in not "Strict")
|
|
||||||
* tracking protection is enabled for the current website or not.
|
|
||||||
* @param settings [Settings] application settings.
|
|
||||||
*/
|
|
||||||
@VisibleForTesting
|
|
||||||
fun createTrackingProtectionState(
|
|
||||||
websiteUrl: String,
|
|
||||||
isTrackingProtectionOn: Boolean,
|
|
||||||
settings: Settings
|
|
||||||
) = TrackingProtectionState(
|
|
||||||
isVisible = FeatureFlags.etpCategories.not(),
|
|
||||||
isTrackingProtectionEnabledPerApp = settings.shouldUseTrackingProtection,
|
|
||||||
websiteUrl = websiteUrl,
|
|
||||||
isTrackingProtectionEnabledPerWebsite = isTrackingProtectionOn
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an initial [WebsiteInfoState] to be rendered by [WebsiteInfoView]
|
* Construct an initial [WebsiteInfoState] to be rendered by [WebsiteInfoView]
|
||||||
* based on the current website's status and connection.
|
* based on the current website's status and connection.
|
||||||
|
@ -149,14 +126,19 @@ class QuickSettingsFragmentStore(
|
||||||
permissions: SitePermissions?,
|
permissions: SitePermissions?,
|
||||||
settings: Settings
|
settings: Settings
|
||||||
): WebsitePermissionsState {
|
): WebsitePermissionsState {
|
||||||
val cameraPermission = PhoneFeature.CAMERA.toWebsitePermission(context, permissions, settings)
|
val cameraPermission =
|
||||||
val microphonePermission = PhoneFeature.MICROPHONE.toWebsitePermission(context, permissions, settings)
|
PhoneFeature.CAMERA.toWebsitePermission(context, permissions, settings)
|
||||||
val notificationPermission = PhoneFeature.NOTIFICATION.toWebsitePermission(context, permissions, settings)
|
val microphonePermission =
|
||||||
val locationPermission = PhoneFeature.LOCATION.toWebsitePermission(context, permissions, settings)
|
PhoneFeature.MICROPHONE.toWebsitePermission(context, permissions, settings)
|
||||||
|
val notificationPermission =
|
||||||
|
PhoneFeature.NOTIFICATION.toWebsitePermission(context, permissions, settings)
|
||||||
|
val locationPermission =
|
||||||
|
PhoneFeature.LOCATION.toWebsitePermission(context, permissions, settings)
|
||||||
val shouldBeVisible = cameraPermission.isVisible || microphonePermission.isVisible ||
|
val shouldBeVisible = cameraPermission.isVisible || microphonePermission.isVisible ||
|
||||||
notificationPermission.isVisible || locationPermission.isVisible
|
notificationPermission.isVisible || locationPermission.isVisible
|
||||||
|
|
||||||
return WebsitePermissionsState(shouldBeVisible, cameraPermission, microphonePermission,
|
return WebsitePermissionsState(
|
||||||
|
shouldBeVisible, cameraPermission, microphonePermission,
|
||||||
notificationPermission, locationPermission
|
notificationPermission, locationPermission
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -227,28 +209,10 @@ class QuickSettingsFragmentStore(
|
||||||
* Partitioned further to contain mutiple states for each standalone View this Fragment holds.
|
* Partitioned further to contain mutiple states for each standalone View this Fragment holds.
|
||||||
*/
|
*/
|
||||||
data class QuickSettingsFragmentState(
|
data class QuickSettingsFragmentState(
|
||||||
val trackingProtectionState: TrackingProtectionState,
|
|
||||||
val webInfoState: WebsiteInfoState,
|
val webInfoState: WebsiteInfoState,
|
||||||
val websitePermissionsState: WebsitePermissionsState
|
val websitePermissionsState: WebsitePermissionsState
|
||||||
) : State
|
) : State
|
||||||
|
|
||||||
/**
|
|
||||||
* [State] to be rendered by [TrackingProtectionView] indicating the app is blocking certain tracking
|
|
||||||
* functionality or not.
|
|
||||||
*
|
|
||||||
* @param isVisible [Boolean] whether this contains data that needs to be displayed to the user.
|
|
||||||
* @param websiteUrl [String] the URL of the current web page.
|
|
||||||
* @param isTrackingProtectionEnabledPerApp [Boolean] whether tracking protection is on/off globally.
|
|
||||||
* @param isTrackingProtectionEnabledPerWebsite [Boolean] whether the "Standard" (as in not "Strict")
|
|
||||||
* tracking protection is enabled for the current website or not.
|
|
||||||
*/
|
|
||||||
data class TrackingProtectionState(
|
|
||||||
val isVisible: Boolean,
|
|
||||||
val websiteUrl: String,
|
|
||||||
val isTrackingProtectionEnabledPerApp: Boolean,
|
|
||||||
val isTrackingProtectionEnabledPerWebsite: Boolean
|
|
||||||
) : State
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [State] to be rendered by [WebsiteInfoView] indicating whether the connection is secure or not.
|
* [State] to be rendered by [WebsiteInfoView] indicating whether the connection is secure or not.
|
||||||
*
|
*
|
||||||
|
@ -428,16 +392,6 @@ sealed class WebsitePermission {
|
||||||
*/
|
*/
|
||||||
sealed class QuickSettingsFragmentAction : Action
|
sealed class QuickSettingsFragmentAction : Action
|
||||||
|
|
||||||
/**
|
|
||||||
* All possible [TrackingProtectionState] changes as result of user / system interactions.
|
|
||||||
*/
|
|
||||||
sealed class TrackingProtectionAction : QuickSettingsFragmentAction() {
|
|
||||||
/**
|
|
||||||
* Change resulting from toggling the tracking protection status for the current website.
|
|
||||||
*/
|
|
||||||
class TrackingProtectionToggled(val trackingEnabled: Boolean) : TrackingProtectionAction()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All possible [WebsiteInfoState] changes as result of user / system interactions.
|
* All possible [WebsiteInfoState] changes as result of user / system interactions.
|
||||||
*/
|
*/
|
||||||
|
@ -475,12 +429,6 @@ fun quickSettingsFragmentReducer(
|
||||||
action: QuickSettingsFragmentAction
|
action: QuickSettingsFragmentAction
|
||||||
): QuickSettingsFragmentState {
|
): QuickSettingsFragmentState {
|
||||||
return when (action) {
|
return when (action) {
|
||||||
is TrackingProtectionAction -> state.copy(
|
|
||||||
trackingProtectionState = TrackingProtectionStateReducer.reduce(
|
|
||||||
state.trackingProtectionState,
|
|
||||||
action
|
|
||||||
)
|
|
||||||
)
|
|
||||||
is WebsiteInfoAction -> state.copy(
|
is WebsiteInfoAction -> state.copy(
|
||||||
webInfoState = WebsiteInfoStateReducer.reduce(
|
webInfoState = WebsiteInfoStateReducer.reduce(
|
||||||
state.webInfoState,
|
state.webInfoState,
|
||||||
|
@ -496,22 +444,6 @@ fun quickSettingsFragmentReducer(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object TrackingProtectionStateReducer {
|
|
||||||
/**
|
|
||||||
* Handles creating a new [TrackingProtectionState] based on the specific [TrackingProtectionAction]
|
|
||||||
*/
|
|
||||||
fun reduce(
|
|
||||||
state: TrackingProtectionState,
|
|
||||||
action: TrackingProtectionAction
|
|
||||||
): TrackingProtectionState {
|
|
||||||
return when (action) {
|
|
||||||
is TrackingProtectionAction.TrackingProtectionToggled -> state.copy(
|
|
||||||
isTrackingProtectionEnabledPerWebsite = action.trackingEnabled
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER") // the action paramater is unused
|
@Suppress("UNUSED_PARAMETER") // the action paramater is unused
|
||||||
object WebsiteInfoStateReducer {
|
object WebsiteInfoStateReducer {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,24 +15,7 @@ package org.mozilla.fenix.settings.quicksettings
|
||||||
*/
|
*/
|
||||||
class QuickSettingsInteractor(
|
class QuickSettingsInteractor(
|
||||||
private val controller: QuickSettingsController
|
private val controller: QuickSettingsController
|
||||||
) : WebsitePermissionInteractor, TrackingProtectionInteractor {
|
) : WebsitePermissionInteractor {
|
||||||
|
|
||||||
override fun onReportProblemSelected(websiteUrl: String) {
|
|
||||||
controller.handleReportTrackingProblem(websiteUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onProtectionToggled(trackingEnabled: Boolean) {
|
|
||||||
controller.handleTrackingProtectionToggled(trackingEnabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onProtectionSettingsSelected() {
|
|
||||||
controller.handleTrackingProtectionSettingsSelected()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTrackingProtectionShown() {
|
|
||||||
controller.handleTrackingProtectionShown()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPermissionsShown() {
|
override fun onPermissionsShown() {
|
||||||
controller.handlePermissionsShown()
|
controller.handlePermissionsShown()
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import kotlinx.android.synthetic.main.fragment_quick_settings_dialog_sheet.*
|
import kotlinx.android.synthetic.main.fragment_quick_settings_dialog_sheet.*
|
||||||
import kotlinx.android.synthetic.main.fragment_quick_settings_dialog_sheet.view.*
|
import kotlinx.android.synthetic.main.fragment_quick_settings_dialog_sheet.view.*
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import mozilla.components.feature.session.TrackingProtectionUseCases
|
|
||||||
import mozilla.components.lib.state.ext.consumeFrom
|
import mozilla.components.lib.state.ext.consumeFrom
|
||||||
import org.mozilla.fenix.HomeActivity
|
import org.mozilla.fenix.HomeActivity
|
||||||
import org.mozilla.fenix.IntentReceiverActivity
|
import org.mozilla.fenix.IntentReceiverActivity
|
||||||
|
@ -47,7 +46,6 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
|
||||||
private lateinit var quickSettingsController: QuickSettingsController
|
private lateinit var quickSettingsController: QuickSettingsController
|
||||||
private lateinit var websiteInfoView: WebsiteInfoView
|
private lateinit var websiteInfoView: WebsiteInfoView
|
||||||
private lateinit var websitePermissionsView: WebsitePermissionsView
|
private lateinit var websitePermissionsView: WebsitePermissionsView
|
||||||
private lateinit var websiteTrackingProtectionView: TrackingProtectionView
|
|
||||||
private lateinit var interactor: QuickSettingsInteractor
|
private lateinit var interactor: QuickSettingsInteractor
|
||||||
private val safeArguments get() = requireNotNull(arguments)
|
private val safeArguments get() = requireNotNull(arguments)
|
||||||
private val promptGravity: Int by lazy {
|
private val promptGravity: Int by lazy {
|
||||||
|
@ -70,7 +68,6 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
|
||||||
context = context,
|
context = context,
|
||||||
websiteUrl = args.url,
|
websiteUrl = args.url,
|
||||||
isSecured = args.isSecured,
|
isSecured = args.isSecured,
|
||||||
isTrackingProtectionOn = args.isTrackingProtectionOn,
|
|
||||||
permissions = args.sitePermissions,
|
permissions = args.sitePermissions,
|
||||||
settings = Settings.getInstance(context)
|
settings = Settings.getInstance(context)
|
||||||
)
|
)
|
||||||
|
@ -90,19 +87,12 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
|
||||||
requestPermissions(permissions, REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS)
|
requestPermissions(permissions, REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS)
|
||||||
},
|
},
|
||||||
reportSiteIssue = ::launchIntentReceiver,
|
reportSiteIssue = ::launchIntentReceiver,
|
||||||
displayTrackingProtection = ::showTrackingProtectionView,
|
|
||||||
displayPermissions = ::showPermissionsView,
|
displayPermissions = ::showPermissionsView,
|
||||||
dismiss = ::dismiss,
|
dismiss = ::dismiss
|
||||||
trackingProtectionUseCases = TrackingProtectionUseCases(
|
|
||||||
context.components.core.sessionManager,
|
|
||||||
context.components.core.engine
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
interactor = QuickSettingsInteractor(quickSettingsController)
|
interactor = QuickSettingsInteractor(quickSettingsController)
|
||||||
|
|
||||||
websiteTrackingProtectionView =
|
|
||||||
TrackingProtectionView(rootView.trackingProtectionLayout, interactor)
|
|
||||||
websiteInfoView = WebsiteInfoView(rootView.websiteInfoLayout)
|
websiteInfoView = WebsiteInfoView(rootView.websiteInfoLayout)
|
||||||
websitePermissionsView =
|
websitePermissionsView =
|
||||||
WebsitePermissionsView(rootView.websitePermissionsLayout, interactor)
|
WebsitePermissionsView(rootView.websitePermissionsLayout, interactor)
|
||||||
|
@ -143,7 +133,6 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
|
||||||
|
|
||||||
consumeFrom(quickSettingsStore) {
|
consumeFrom(quickSettingsStore) {
|
||||||
websiteInfoView.update(it.webInfoState)
|
websiteInfoView.update(it.webInfoState)
|
||||||
websiteTrackingProtectionView.update(it.trackingProtectionState)
|
|
||||||
websitePermissionsView.update(it.websitePermissionsState)
|
websitePermissionsView.update(it.websitePermissionsState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,10 +170,6 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
|
||||||
private fun arePermissionsGranted(requestCode: Int, grantResults: IntArray) =
|
private fun arePermissionsGranted(requestCode: Int, grantResults: IntArray) =
|
||||||
requestCode == REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS && grantResults.all { it == PERMISSION_GRANTED }
|
requestCode == REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS && grantResults.all { it == PERMISSION_GRANTED }
|
||||||
|
|
||||||
private fun showTrackingProtectionView() {
|
|
||||||
trackingProtectionGroup.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showPermissionsView() {
|
private fun showPermissionsView() {
|
||||||
websitePermissionsGroup.isVisible = true
|
websitePermissionsGroup.isVisible = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
package org.mozilla.fenix.settings.quicksettings
|
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.appcompat.content.res.AppCompatResources
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import kotlinx.android.extensions.LayoutContainer
|
|
||||||
import kotlinx.android.synthetic.main.quicksettings_tracking_protection.*
|
|
||||||
import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelativeWithIntrinsicBounds
|
|
||||||
import org.mozilla.fenix.R
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contract declaring all possible user interactions with [TrackingProtectionView]
|
|
||||||
*/
|
|
||||||
interface TrackingProtectionInteractor {
|
|
||||||
/**
|
|
||||||
* Indicates the user wants to report a problem with the current website.
|
|
||||||
*/
|
|
||||||
fun onReportProblemSelected(websiteUrl: String)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates the user want to toggle the tracking protection on / off.
|
|
||||||
*/
|
|
||||||
fun onProtectionToggled(trackingEnabled: Boolean)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates the user want to see all tracking protection settings.
|
|
||||||
*/
|
|
||||||
fun onProtectionSettingsSelected()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates the tracking protection status for the current website is shown to the user.
|
|
||||||
*/
|
|
||||||
fun onTrackingProtectionShown()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MVI View that knows to display a "normal" (as in not "enhanced") tracking protection panel
|
|
||||||
* containing the tracking protection status and also allowing on / off toggling.
|
|
||||||
*
|
|
||||||
* @param containerView [ViewGroup] in which this View will inflate itself.
|
|
||||||
* @param interactor [TrackingProtectionInteractor] which will have delegated to all user interactions.
|
|
||||||
*/
|
|
||||||
class TrackingProtectionView(
|
|
||||||
override val containerView: ViewGroup,
|
|
||||||
val interactor: TrackingProtectionInteractor
|
|
||||||
) : LayoutContainer {
|
|
||||||
|
|
||||||
val view: View = LayoutInflater.from(containerView.context)
|
|
||||||
.inflate(R.layout.quicksettings_tracking_protection, containerView, true)
|
|
||||||
|
|
||||||
init {
|
|
||||||
trackingProtectionSwitch.putCompoundDrawablesRelativeWithIntrinsicBounds(
|
|
||||||
start = AppCompatResources.getDrawable(
|
|
||||||
containerView.context,
|
|
||||||
R.drawable.ic_tracking_protection
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows changing what this View displays.
|
|
||||||
*
|
|
||||||
* @param state [TrackingProtectionState] to be rendered.
|
|
||||||
*/
|
|
||||||
fun update(state: TrackingProtectionState) {
|
|
||||||
if (state.isVisible) {
|
|
||||||
interactor.onTrackingProtectionShown()
|
|
||||||
}
|
|
||||||
|
|
||||||
reportSiteIssueAction.setOnClickListener { interactor.onReportProblemSelected(state.websiteUrl) }
|
|
||||||
|
|
||||||
trackingProtectionAction.isVisible = !state.isTrackingProtectionEnabledPerApp
|
|
||||||
if (!state.isTrackingProtectionEnabledPerApp) {
|
|
||||||
trackingProtectionAction.setOnClickListener { interactor.onProtectionSettingsSelected() }
|
|
||||||
}
|
|
||||||
|
|
||||||
trackingProtectionSwitch.isChecked = state.isTrackingProtectionEnabledPerWebsite
|
|
||||||
trackingProtectionSwitch.isEnabled = state.isTrackingProtectionEnabledPerApp
|
|
||||||
if (state.isTrackingProtectionEnabledPerApp) {
|
|
||||||
trackingProtectionSwitch.setOnCheckedChangeListener { _, isChecked ->
|
|
||||||
interactor.onProtectionToggled(isChecked)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -197,36 +197,10 @@ class Settings private constructor(
|
||||||
)
|
)
|
||||||
|
|
||||||
val useStrictTrackingProtection by booleanPreference(
|
val useStrictTrackingProtection by booleanPreference(
|
||||||
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_strict),
|
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_strict_default),
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
|
||||||
fun setUseStrictTrackingProtection() {
|
|
||||||
preferences.edit()
|
|
||||||
.putBoolean(
|
|
||||||
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_standard),
|
|
||||||
false
|
|
||||||
)
|
|
||||||
.putBoolean(
|
|
||||||
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_strict),
|
|
||||||
true
|
|
||||||
)
|
|
||||||
.apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setUseStandardTrackingProtection() {
|
|
||||||
preferences.edit()
|
|
||||||
.putBoolean(
|
|
||||||
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_standard),
|
|
||||||
true
|
|
||||||
)
|
|
||||||
.putBoolean(
|
|
||||||
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_strict),
|
|
||||||
false
|
|
||||||
)
|
|
||||||
.apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
var shouldDeleteBrowsingDataOnQuit by booleanPreference(
|
var shouldDeleteBrowsingDataOnQuit by booleanPreference(
|
||||||
appContext.getPreferenceKey(R.string.pref_key_delete_browsing_data_on_quit),
|
appContext.getPreferenceKey(R.string.pref_key_delete_browsing_data_on_quit),
|
||||||
default = false
|
default = false
|
||||||
|
|
|
@ -22,12 +22,6 @@
|
||||||
android:id="@+id/websiteInfoLayout"
|
android:id="@+id/websiteInfoLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintBottom_toTopOf="@id/trackingProtectionDivider" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/trackingProtectionLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/webSitePermissionsDivider" />
|
app:layout_constraintBottom_toTopOf="@id/webSitePermissionsDivider" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
@ -45,23 +39,6 @@
|
||||||
android:background="?neutralFaded"
|
android:background="?neutralFaded"
|
||||||
app:layout_constraintBottom_toTopOf="@id/websitePermissionsLayout" />
|
app:layout_constraintBottom_toTopOf="@id/websitePermissionsLayout" />
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/trackingProtectionDivider"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="?neutralFaded"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/trackingProtectionLayout" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Group
|
|
||||||
android:id="@+id/trackingProtectionGroup"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:constraint_referenced_ids="trackingProtectionLayout,trackingProtectionDivider"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Group
|
<androidx.constraintlayout.widget.Group
|
||||||
android:id="@+id/websitePermissionsGroup"
|
android:id="@+id/websitePermissionsGroup"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -564,8 +564,7 @@
|
||||||
</dialog>
|
</dialog>
|
||||||
<dialog
|
<dialog
|
||||||
android:id="@+id/quickSettingsSheetDialogFragment"
|
android:id="@+id/quickSettingsSheetDialogFragment"
|
||||||
android:name="org.mozilla.fenix.settings.quicksettings.QuickSettingsSheetDialogFragment"
|
android:name="org.mozilla.fenix.settings.quicksettings.QuickSettingsSheetDialogFragment">
|
||||||
android:label="QuickSettingsSheetDialogFragment">
|
|
||||||
<argument
|
<argument
|
||||||
android:name="sessionId"
|
android:name="sessionId"
|
||||||
app:argType="string" />
|
app:argType="string" />
|
||||||
|
@ -575,9 +574,6 @@
|
||||||
<argument
|
<argument
|
||||||
android:name="isSecured"
|
android:name="isSecured"
|
||||||
app:argType="boolean" />
|
app:argType="boolean" />
|
||||||
<argument
|
|
||||||
android:name="isTrackingProtectionOn"
|
|
||||||
app:argType="boolean" />
|
|
||||||
<argument
|
<argument
|
||||||
android:name="sitePermissions"
|
android:name="sitePermissions"
|
||||||
app:argType="mozilla.components.feature.sitepermissions.SitePermissions"
|
app:argType="mozilla.components.feature.sitepermissions.SitePermissions"
|
||||||
|
@ -586,11 +582,6 @@
|
||||||
android:name="gravity"
|
android:name="gravity"
|
||||||
android:defaultValue="80"
|
android:defaultValue="80"
|
||||||
app:argType="integer" />
|
app:argType="integer" />
|
||||||
<action
|
|
||||||
android:id="@+id/action_quickSettingsSheetDialogFragment_to_trackingProtectionFragment"
|
|
||||||
app:destination="@id/trackingProtectionFragment"
|
|
||||||
app:popUpTo="@id/quickSettingsSheetDialogFragment"
|
|
||||||
app:popUpToInclusive="true" />
|
|
||||||
</dialog>
|
</dialog>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/accountProblemFragment"
|
android:id="@+id/accountProblemFragment"
|
||||||
|
|
|
@ -97,8 +97,8 @@
|
||||||
<string name="pref_key_tracking_protection_settings" translatable="false">pref_key_tracking_protection_settings</string>
|
<string name="pref_key_tracking_protection_settings" translatable="false">pref_key_tracking_protection_settings</string>
|
||||||
<string name="pref_key_tracking_protection" translatable="false">pref_key_tracking_protection</string>
|
<string name="pref_key_tracking_protection" translatable="false">pref_key_tracking_protection</string>
|
||||||
<string name="pref_key_tracking_protection_exceptions" translatable="false">pref_key_tracking_protection_exceptions</string>
|
<string name="pref_key_tracking_protection_exceptions" translatable="false">pref_key_tracking_protection_exceptions</string>
|
||||||
<string name="pref_key_tracking_protection_standard" translatable="false">pref_key_tracking_protection_standard</string>
|
<string name="pref_key_tracking_protection_standard_option" translatable="false">pref_key_tracking_protection_standard_option</string>
|
||||||
<string name="pref_key_tracking_protection_strict" translatable="false">pref_key_tracking_protection_strict</string>
|
<string name="pref_key_tracking_protection_strict_default" translatable="false">pref_key_tracking_protection_strict_default</string>
|
||||||
<string name="pref_key_tracking_protection_onboarding" translatable="false">pref_key_tracking_protection_onboarding</string>
|
<string name="pref_key_tracking_protection_onboarding" translatable="false">pref_key_tracking_protection_onboarding</string>
|
||||||
|
|
||||||
<!-- Logins Settings -->
|
<!-- Logins Settings -->
|
||||||
|
|
|
@ -18,17 +18,15 @@
|
||||||
<org.mozilla.fenix.settings.RadioButtonInfoPreference
|
<org.mozilla.fenix.settings.RadioButtonInfoPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:dependency="@string/pref_key_tracking_protection"
|
android:dependency="@string/pref_key_tracking_protection"
|
||||||
android:key="@string/pref_key_tracking_protection_standard"
|
android:key="@string/pref_key_tracking_protection_standard_option"
|
||||||
android:summary="@string/preference_enhanced_tracking_protection_standard_description_2"
|
android:summary="@string/preference_enhanced_tracking_protection_standard_description_2"
|
||||||
android:title="@string/preference_enhanced_tracking_protection_standard_option"
|
android:title="@string/preference_enhanced_tracking_protection_standard_option" />
|
||||||
app:isPreferenceVisible="false" />
|
|
||||||
<org.mozilla.fenix.settings.RadioButtonInfoPreference
|
<org.mozilla.fenix.settings.RadioButtonInfoPreference
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:dependency="@string/pref_key_tracking_protection"
|
android:dependency="@string/pref_key_tracking_protection"
|
||||||
android:key="@string/pref_key_tracking_protection_strict"
|
android:key="@string/pref_key_tracking_protection_strict_default"
|
||||||
android:summary="@string/preference_enhanced_tracking_protection_strict_default_description"
|
android:summary="@string/preference_enhanced_tracking_protection_strict_default_description"
|
||||||
android:title="@string/preference_enhanced_tracking_protection_strict_default"
|
android:title="@string/preference_enhanced_tracking_protection_strict_default" />
|
||||||
app:isPreferenceVisible="false" />
|
|
||||||
<Preference
|
<Preference
|
||||||
android:icon="@drawable/ic_internet"
|
android:icon="@drawable/ic_internet"
|
||||||
android:key="@string/pref_key_tracking_protection_exceptions"
|
android:key="@string/pref_key_tracking_protection_exceptions"
|
||||||
|
|
|
@ -24,7 +24,6 @@ import kotlinx.coroutines.ObsoleteCoroutinesApi
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import mozilla.components.browser.session.Session
|
import mozilla.components.browser.session.Session
|
||||||
import mozilla.components.feature.session.SessionUseCases
|
import mozilla.components.feature.session.SessionUseCases
|
||||||
import mozilla.components.feature.session.TrackingProtectionUseCases
|
|
||||||
import mozilla.components.feature.sitepermissions.SitePermissions
|
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||||
import mozilla.components.feature.sitepermissions.SitePermissions.Status.NO_DECISION
|
import mozilla.components.feature.sitepermissions.SitePermissions.Status.NO_DECISION
|
||||||
import mozilla.components.feature.tabs.TabsUseCases
|
import mozilla.components.feature.tabs.TabsUseCases
|
||||||
|
@ -32,10 +31,7 @@ import mozilla.components.support.test.robolectric.testContext
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mozilla.fenix.TestApplication
|
import org.mozilla.fenix.TestApplication
|
||||||
import org.mozilla.fenix.browser.BrowserFragment
|
|
||||||
import org.mozilla.fenix.components.PermissionStorage
|
import org.mozilla.fenix.components.PermissionStorage
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
|
||||||
import org.mozilla.fenix.ext.metrics
|
|
||||||
import org.mozilla.fenix.settings.PhoneFeature
|
import org.mozilla.fenix.settings.PhoneFeature
|
||||||
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled
|
import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled
|
||||||
import org.mozilla.fenix.settings.toggle
|
import org.mozilla.fenix.settings.toggle
|
||||||
|
@ -59,10 +55,8 @@ class DefaultQuickSettingsControllerTest {
|
||||||
private val addNewTab = mockk<TabsUseCases.AddNewTabUseCase>(relaxed = true)
|
private val addNewTab = mockk<TabsUseCases.AddNewTabUseCase>(relaxed = true)
|
||||||
private val requestPermissions = mockk<(Array<String>) -> Unit>(relaxed = true)
|
private val requestPermissions = mockk<(Array<String>) -> Unit>(relaxed = true)
|
||||||
private val reportIssue = mockk<() -> Unit>(relaxed = true)
|
private val reportIssue = mockk<() -> Unit>(relaxed = true)
|
||||||
private val displayTrackingProtection = mockk<() -> Unit>(relaxed = true)
|
|
||||||
private val displayPermissions = mockk<() -> Unit>(relaxed = true)
|
private val displayPermissions = mockk<() -> Unit>(relaxed = true)
|
||||||
private val dismiss = mockk<() -> Unit>(relaxed = true)
|
private val dismiss = mockk<() -> Unit>(relaxed = true)
|
||||||
private val trackingProtectionUseCases = mockk<TrackingProtectionUseCases>(relaxed = true)
|
|
||||||
private val controller = DefaultQuickSettingsController(
|
private val controller = DefaultQuickSettingsController(
|
||||||
context = context,
|
context = context,
|
||||||
quickSettingsStore = store,
|
quickSettingsStore = store,
|
||||||
|
@ -76,99 +70,10 @@ class DefaultQuickSettingsControllerTest {
|
||||||
addNewTab = addNewTab,
|
addNewTab = addNewTab,
|
||||||
requestRuntimePermissions = requestPermissions,
|
requestRuntimePermissions = requestPermissions,
|
||||||
reportSiteIssue = reportIssue,
|
reportSiteIssue = reportIssue,
|
||||||
displayTrackingProtection = displayTrackingProtection,
|
|
||||||
displayPermissions = displayPermissions,
|
displayPermissions = displayPermissions,
|
||||||
dismiss = dismiss,
|
dismiss = dismiss
|
||||||
trackingProtectionUseCases = trackingProtectionUseCases
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `handleTrackingProtectionToggled should toggle tracking and reload website`() {
|
|
||||||
val session = slot<Session>()
|
|
||||||
every { store.dispatch(any()) } returns mockk()
|
|
||||||
|
|
||||||
controller.handleTrackingProtectionToggled(false)
|
|
||||||
|
|
||||||
verifyOrder {
|
|
||||||
trackingProtectionUseCases.addException(capture(session))
|
|
||||||
context.metrics.track(Event.TrackingProtectionException)
|
|
||||||
reload(capture(session))
|
|
||||||
}
|
|
||||||
|
|
||||||
assertAll {
|
|
||||||
assertThat(session.isCaptured).isTrue()
|
|
||||||
assertThat(session.captured).isEqualTo(browserSession)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `handleTrackingProtectionSettingsSelected should navigate to TrackingProtectionFragment`() {
|
|
||||||
controller.handleTrackingProtectionSettingsSelected()
|
|
||||||
|
|
||||||
verify {
|
|
||||||
navController.navigate(
|
|
||||||
QuickSettingsSheetDialogFragmentDirections
|
|
||||||
.actionQuickSettingsSheetDialogFragmentToTrackingProtectionFragment()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@ObsoleteCoroutinesApi
|
|
||||||
@ExperimentalCoroutinesApi
|
|
||||||
fun `handleReportTrackingProblem should open a report issue webpage and dismiss when in normal mode`() {
|
|
||||||
val websiteWithIssuesUrl = "https://host.com/page1"
|
|
||||||
val testReportUrl =
|
|
||||||
String.format(BrowserFragment.REPORT_SITE_ISSUE_URL, websiteWithIssuesUrl)
|
|
||||||
val reportUrl = slot<String>()
|
|
||||||
// `handleReportTrackingProblem` will behave differently depending on `isCustomTabSession`
|
|
||||||
every { browserSession.isCustomTabSession() } returns false
|
|
||||||
|
|
||||||
controller.handleReportTrackingProblem(websiteWithIssuesUrl)
|
|
||||||
|
|
||||||
verify {
|
|
||||||
addNewTab(capture(reportUrl))
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
assertAll {
|
|
||||||
assertThat(reportUrl.isCaptured).isTrue()
|
|
||||||
assertThat(reportUrl.captured).isEqualTo(testReportUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@ObsoleteCoroutinesApi
|
|
||||||
@ExperimentalCoroutinesApi
|
|
||||||
fun `handleReportTrackingProblem should open a report issue in browser from custom tab and dismiss`() {
|
|
||||||
val websiteWithIssuesUrl = "https://host.com/page1"
|
|
||||||
val testReportUrl =
|
|
||||||
String.format(BrowserFragment.REPORT_SITE_ISSUE_URL, websiteWithIssuesUrl)
|
|
||||||
val reportUrl = slot<String>()
|
|
||||||
// `handleReportTrackingProblem` will behave differently depending on `isCustomTabSession`
|
|
||||||
every { browserSession.isCustomTabSession() } returns true
|
|
||||||
|
|
||||||
controller.handleReportTrackingProblem(websiteWithIssuesUrl)
|
|
||||||
|
|
||||||
verify {
|
|
||||||
addNewTab(capture(reportUrl))
|
|
||||||
reportIssue()
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
assertAll {
|
|
||||||
assertThat(reportUrl.isCaptured).isTrue()
|
|
||||||
assertThat(reportUrl.captured).isEqualTo(testReportUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `handleTrackingProtectionShown should delegate to an injected parameter`() {
|
|
||||||
controller.handleTrackingProtectionShown()
|
|
||||||
|
|
||||||
verify {
|
|
||||||
displayTrackingProtection()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `handlePermissionsShown should delegate to an injected parameter`() {
|
fun `handlePermissionsShown should delegate to an injected parameter`() {
|
||||||
controller.handlePermissionsShown()
|
controller.handlePermissionsShown()
|
||||||
|
|
|
@ -10,7 +10,6 @@ import assertk.assertThat
|
||||||
import assertk.assertions.isEqualTo
|
import assertk.assertions.isEqualTo
|
||||||
import assertk.assertions.isFalse
|
import assertk.assertions.isFalse
|
||||||
import assertk.assertions.isInstanceOf
|
import assertk.assertions.isInstanceOf
|
||||||
import assertk.assertions.isNotEqualTo
|
|
||||||
import assertk.assertions.isNotNull
|
import assertk.assertions.isNotNull
|
||||||
import assertk.assertions.isNotSameAs
|
import assertk.assertions.isNotSameAs
|
||||||
import assertk.assertions.isSameAs
|
import assertk.assertions.isSameAs
|
||||||
|
@ -56,17 +55,15 @@ class QuickSettingsFragmentStoreTest {
|
||||||
fun `createStore constructs a QuickSettingsFragmentState`() {
|
fun `createStore constructs a QuickSettingsFragmentState`() {
|
||||||
val settings = mockk<Settings>(relaxed = true)
|
val settings = mockk<Settings>(relaxed = true)
|
||||||
val permissions = mockk<SitePermissions>(relaxed = true)
|
val permissions = mockk<SitePermissions>(relaxed = true)
|
||||||
every { settings.shouldUseTrackingProtection } returns true
|
|
||||||
|
|
||||||
val store = QuickSettingsFragmentStore.createStore(
|
val store = QuickSettingsFragmentStore.createStore(
|
||||||
context, "url", true, true, permissions, settings
|
context, "url", true, permissions, settings
|
||||||
)
|
)
|
||||||
|
|
||||||
assertAll {
|
assertAll {
|
||||||
assertThat(store).isNotNull()
|
assertThat(store).isNotNull()
|
||||||
assertThat(store.state).isNotNull()
|
assertThat(store.state).isNotNull()
|
||||||
assertThat(store.state.webInfoState).isNotNull()
|
assertThat(store.state.webInfoState).isNotNull()
|
||||||
assertThat(store.state.trackingProtectionState).isNotNull()
|
|
||||||
assertThat(store.state.websitePermissionsState).isNotNull()
|
assertThat(store.state.websitePermissionsState).isNotNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,29 +100,15 @@ class QuickSettingsFragmentStoreTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `createTrackingProtectionState helps in constructing an initial TrackingProtectionState for it's Store`() {
|
|
||||||
val websiteUrl = "https://host.com/pageThatShouldUseTrackingProtection"
|
|
||||||
val trackingPerWebsiteStatus = true
|
|
||||||
val trackingPerAppStatus = true
|
|
||||||
every { appSettings.shouldUseTrackingProtection } returns trackingPerAppStatus
|
|
||||||
|
|
||||||
val state = QuickSettingsFragmentStore.createTrackingProtectionState(
|
|
||||||
websiteUrl, trackingPerWebsiteStatus, appSettings
|
|
||||||
)
|
|
||||||
|
|
||||||
assertAll {
|
|
||||||
assertThat(state).isNotNull()
|
|
||||||
assertThat(state).isNotNull()
|
|
||||||
assertThat(state.websiteUrl).isSameAs(websiteUrl)
|
|
||||||
assertThat(state.isTrackingProtectionEnabledPerWebsite).isSameAs(trackingPerWebsiteStatus)
|
|
||||||
assertThat(state.isTrackingProtectionEnabledPerApp).isEqualTo(trackingPerAppStatus)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `createWebsitePermissionState helps in constructing an initial WebsitePermissionState for it's Store`() {
|
fun `createWebsitePermissionState helps in constructing an initial WebsitePermissionState for it's Store`() {
|
||||||
every { context.checkPermission(any(), any(), any()) }.returns(PackageManager.PERMISSION_GRANTED)
|
every {
|
||||||
|
context.checkPermission(
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
any()
|
||||||
|
)
|
||||||
|
}.returns(PackageManager.PERMISSION_GRANTED)
|
||||||
every { permissions.camera } returns SitePermissions.Status.ALLOWED
|
every { permissions.camera } returns SitePermissions.Status.ALLOWED
|
||||||
every { permissions.microphone } returns SitePermissions.Status.NO_DECISION
|
every { permissions.microphone } returns SitePermissions.Status.NO_DECISION
|
||||||
every { permissions.notification } returns SitePermissions.Status.BLOCKED
|
every { permissions.notification } returns SitePermissions.Status.BLOCKED
|
||||||
|
@ -150,7 +133,13 @@ class QuickSettingsFragmentStoreTest {
|
||||||
fun `PhoneFeature#toWebsitePermission helps in constructing the right WebsitePermission`() {
|
fun `PhoneFeature#toWebsitePermission helps in constructing the right WebsitePermission`() {
|
||||||
val cameraFeature = PhoneFeature.CAMERA
|
val cameraFeature = PhoneFeature.CAMERA
|
||||||
val allowedStatus = testContext.getString(R.string.preference_option_phone_feature_allowed)
|
val allowedStatus = testContext.getString(R.string.preference_option_phone_feature_allowed)
|
||||||
every { context.checkPermission(any(), any(), any()) }.returns(PackageManager.PERMISSION_GRANTED)
|
every {
|
||||||
|
context.checkPermission(
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
any()
|
||||||
|
)
|
||||||
|
}.returns(PackageManager.PERMISSION_GRANTED)
|
||||||
every { permissions.camera } returns SitePermissions.Status.ALLOWED
|
every { permissions.camera } returns SitePermissions.Status.ALLOWED
|
||||||
|
|
||||||
val websitePermission = cameraFeature.toWebsitePermission(context, permissions, appSettings)
|
val websitePermission = cameraFeature.toWebsitePermission(context, permissions, appSettings)
|
||||||
|
@ -187,117 +176,135 @@ class QuickSettingsFragmentStoreTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExperimentalCoroutinesApi
|
|
||||||
@Test
|
|
||||||
fun `TrackingProtectionToggled should update only the tracking enabled status`() = runBlocking {
|
|
||||||
val initialUrl = "https://host.com/page1"
|
|
||||||
val initialTrackingPerApp = true
|
|
||||||
val initialTrackingPerWebsite = true
|
|
||||||
val updatedTrackingPerWebsite = false
|
|
||||||
val appSettings = mockk<Settings>()
|
|
||||||
every { appSettings.shouldUseTrackingProtection } returns initialTrackingPerApp
|
|
||||||
val initialTrackingProtectionState = QuickSettingsFragmentStore.createTrackingProtectionState(
|
|
||||||
initialUrl, initialTrackingPerWebsite, appSettings
|
|
||||||
)
|
|
||||||
val initialWebsiteInfoState = mockk<WebsiteInfoState>()
|
|
||||||
val initialWebsitePermissionsState = mockk<WebsitePermissionsState>()
|
|
||||||
val store = QuickSettingsFragmentStore(QuickSettingsFragmentState(
|
|
||||||
initialTrackingProtectionState, initialWebsiteInfoState, initialWebsitePermissionsState
|
|
||||||
))
|
|
||||||
|
|
||||||
store.dispatch(TrackingProtectionAction.TrackingProtectionToggled(updatedTrackingPerWebsite)).join()
|
|
||||||
|
|
||||||
assertAll {
|
|
||||||
assertThat(store.state.webInfoState).isSameAs(initialWebsiteInfoState)
|
|
||||||
assertThat(store.state.websitePermissionsState).isSameAs(initialWebsitePermissionsState)
|
|
||||||
assertThat(store.state.trackingProtectionState).isNotSameAs(initialTrackingProtectionState)
|
|
||||||
|
|
||||||
assertThat(store.state.trackingProtectionState.isTrackingProtectionEnabledPerWebsite)
|
|
||||||
.isNotEqualTo(initialTrackingPerWebsite)
|
|
||||||
assertThat(store.state.trackingProtectionState.isTrackingProtectionEnabledPerWebsite)
|
|
||||||
.isEqualTo(updatedTrackingPerWebsite)
|
|
||||||
assertThat(store.state.trackingProtectionState.isTrackingProtectionEnabledPerApp)
|
|
||||||
.isSameAs(initialTrackingPerApp)
|
|
||||||
assertThat(store.state.trackingProtectionState.websiteUrl).isSameAs(initialUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ExperimentalCoroutinesApi
|
@ExperimentalCoroutinesApi
|
||||||
fun `TogglePermission should only modify status and visibility of a specific WebsitePermissionsState`() = runBlocking {
|
fun `TogglePermission should only modify status and visibility of a specific WebsitePermissionsState`() =
|
||||||
val cameraPermissionName = "Camera"
|
runBlocking {
|
||||||
val microphonePermissionName = "Microphone"
|
val cameraPermissionName = "Camera"
|
||||||
val notificationPermissionName = "Notification"
|
val microphonePermissionName = "Microphone"
|
||||||
val locationPermissionName = "Location"
|
val notificationPermissionName = "Notification"
|
||||||
val initialCameraStatus = "initialCameraStatus"
|
val locationPermissionName = "Location"
|
||||||
val initialMicStatus = "initialMicStatus"
|
val initialCameraStatus = "initialCameraStatus"
|
||||||
val initialNotificationStatus = "initialNotificationStatus"
|
val initialMicStatus = "initialMicStatus"
|
||||||
val initialLocationStatus = "initialLocationStatus"
|
val initialNotificationStatus = "initialNotificationStatus"
|
||||||
val updatedMicrophoneStatus = "updatedNotificationStatus"
|
val initialLocationStatus = "initialLocationStatus"
|
||||||
val updatedMicrophoneEnabledStatus = false
|
val updatedMicrophoneStatus = "updatedNotificationStatus"
|
||||||
val defaultVisibilityStatus = true
|
val updatedMicrophoneEnabledStatus = false
|
||||||
val defaultEnabledStatus = true
|
val defaultVisibilityStatus = true
|
||||||
val defaultBlockedByAndroidStatus = true
|
val defaultEnabledStatus = true
|
||||||
val websiteInfoState = mockk<WebsiteInfoState>()
|
val defaultBlockedByAndroidStatus = true
|
||||||
val trackingProtectionState = mockk<TrackingProtectionState>()
|
val websiteInfoState = mockk<WebsiteInfoState>()
|
||||||
val initialWebsitePermissionsState = WebsitePermissionsState(
|
val initialWebsitePermissionsState = WebsitePermissionsState(
|
||||||
isVisible = true,
|
isVisible = true,
|
||||||
camera = WebsitePermission.Camera(initialCameraStatus, defaultVisibilityStatus,
|
camera = WebsitePermission.Camera(
|
||||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, cameraPermissionName),
|
initialCameraStatus, defaultVisibilityStatus,
|
||||||
microphone = WebsitePermission.Microphone(initialMicStatus, defaultVisibilityStatus,
|
defaultEnabledStatus, defaultBlockedByAndroidStatus, cameraPermissionName
|
||||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, microphonePermissionName),
|
),
|
||||||
notification = WebsitePermission.Notification(initialNotificationStatus, defaultVisibilityStatus,
|
microphone = WebsitePermission.Microphone(
|
||||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, notificationPermissionName),
|
initialMicStatus, defaultVisibilityStatus,
|
||||||
location = WebsitePermission.Location(initialLocationStatus, defaultVisibilityStatus,
|
defaultEnabledStatus, defaultBlockedByAndroidStatus, microphonePermissionName
|
||||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, locationPermissionName)
|
),
|
||||||
)
|
notification = WebsitePermission.Notification(
|
||||||
val initialState = QuickSettingsFragmentState(
|
initialNotificationStatus, defaultVisibilityStatus,
|
||||||
trackingProtectionState, websiteInfoState, initialWebsitePermissionsState
|
defaultEnabledStatus, defaultBlockedByAndroidStatus, notificationPermissionName
|
||||||
)
|
),
|
||||||
val store = QuickSettingsFragmentStore(initialState)
|
location = WebsitePermission.Location(
|
||||||
|
initialLocationStatus, defaultVisibilityStatus,
|
||||||
|
defaultEnabledStatus, defaultBlockedByAndroidStatus, locationPermissionName
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val initialState = QuickSettingsFragmentState(
|
||||||
|
websiteInfoState, initialWebsitePermissionsState
|
||||||
|
)
|
||||||
|
val store = QuickSettingsFragmentStore(initialState)
|
||||||
|
|
||||||
store.dispatch(WebsitePermissionAction.TogglePermission(
|
store.dispatch(
|
||||||
mockk<WebsitePermission.Microphone>(), updatedMicrophoneStatus, updatedMicrophoneEnabledStatus)
|
WebsitePermissionAction.TogglePermission(
|
||||||
).join()
|
mockk<WebsitePermission.Microphone>(),
|
||||||
|
updatedMicrophoneStatus,
|
||||||
|
updatedMicrophoneEnabledStatus
|
||||||
|
)
|
||||||
|
).join()
|
||||||
|
|
||||||
assertAll {
|
assertAll {
|
||||||
assertThat(store.state).isNotNull()
|
assertThat(store.state).isNotNull()
|
||||||
assertThat(store.state).isNotSameAs(initialState)
|
assertThat(store.state).isNotSameAs(initialState)
|
||||||
assertThat(store.state.websitePermissionsState).isNotSameAs(initialWebsitePermissionsState)
|
assertThat(store.state.websitePermissionsState).isNotSameAs(
|
||||||
assertThat(store.state.webInfoState).isSameAs(websiteInfoState)
|
initialWebsitePermissionsState
|
||||||
assertThat(store.state.trackingProtectionState).isSameAs(trackingProtectionState)
|
)
|
||||||
|
assertThat(store.state.webInfoState).isSameAs(websiteInfoState)
|
||||||
|
|
||||||
assertThat(store.state.websitePermissionsState.camera).isNotNull()
|
assertThat(store.state.websitePermissionsState.camera).isNotNull()
|
||||||
assertThat((store.state.websitePermissionsState.camera as WebsitePermission.Camera).name).isEqualTo(cameraPermissionName)
|
assertThat((store.state.websitePermissionsState.camera as WebsitePermission.Camera).name).isEqualTo(
|
||||||
assertThat(store.state.websitePermissionsState.camera.status).isEqualTo(initialCameraStatus)
|
cameraPermissionName
|
||||||
assertThat(store.state.websitePermissionsState.camera.isVisible).isEqualTo(defaultVisibilityStatus)
|
)
|
||||||
assertThat(store.state.websitePermissionsState.camera.isEnabled).isEqualTo(defaultEnabledStatus)
|
assertThat(store.state.websitePermissionsState.camera.status).isEqualTo(
|
||||||
assertThat(store.state.websitePermissionsState.camera.isBlockedByAndroid).isEqualTo(defaultBlockedByAndroidStatus)
|
initialCameraStatus
|
||||||
|
)
|
||||||
|
assertThat(store.state.websitePermissionsState.camera.isVisible).isEqualTo(
|
||||||
|
defaultVisibilityStatus
|
||||||
|
)
|
||||||
|
assertThat(store.state.websitePermissionsState.camera.isEnabled).isEqualTo(
|
||||||
|
defaultEnabledStatus
|
||||||
|
)
|
||||||
|
assertThat(store.state.websitePermissionsState.camera.isBlockedByAndroid).isEqualTo(
|
||||||
|
defaultBlockedByAndroidStatus
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(store.state.websitePermissionsState.microphone).isNotNull()
|
assertThat(store.state.websitePermissionsState.microphone).isNotNull()
|
||||||
assertThat((store.state.websitePermissionsState.microphone as WebsitePermission.Microphone).name).isEqualTo(microphonePermissionName)
|
assertThat((store.state.websitePermissionsState.microphone as WebsitePermission.Microphone).name).isEqualTo(
|
||||||
// Only the following two properties must have been changed!
|
microphonePermissionName
|
||||||
assertThat(store.state.websitePermissionsState.microphone.status).isEqualTo(updatedMicrophoneStatus)
|
)
|
||||||
assertThat(store.state.websitePermissionsState.microphone.isEnabled).isEqualTo(updatedMicrophoneEnabledStatus)
|
// Only the following two properties must have been changed!
|
||||||
|
assertThat(store.state.websitePermissionsState.microphone.status).isEqualTo(
|
||||||
|
updatedMicrophoneStatus
|
||||||
|
)
|
||||||
|
assertThat(store.state.websitePermissionsState.microphone.isEnabled).isEqualTo(
|
||||||
|
updatedMicrophoneEnabledStatus
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(store.state.websitePermissionsState.microphone.isVisible).isEqualTo(defaultVisibilityStatus)
|
assertThat(store.state.websitePermissionsState.microphone.isVisible).isEqualTo(
|
||||||
assertThat(store.state.websitePermissionsState.microphone.isBlockedByAndroid).isEqualTo(defaultBlockedByAndroidStatus)
|
defaultVisibilityStatus
|
||||||
|
)
|
||||||
|
assertThat(store.state.websitePermissionsState.microphone.isBlockedByAndroid).isEqualTo(
|
||||||
|
defaultBlockedByAndroidStatus
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(store.state.websitePermissionsState.notification).isNotNull()
|
assertThat(store.state.websitePermissionsState.notification).isNotNull()
|
||||||
assertThat((store.state.websitePermissionsState.notification as WebsitePermission.Notification).name).isEqualTo(notificationPermissionName)
|
assertThat((store.state.websitePermissionsState.notification as WebsitePermission.Notification).name).isEqualTo(
|
||||||
assertThat(store.state.websitePermissionsState.notification.status).isEqualTo(initialNotificationStatus)
|
notificationPermissionName
|
||||||
assertThat(store.state.websitePermissionsState.notification.isVisible).isEqualTo(defaultVisibilityStatus)
|
)
|
||||||
assertThat(store.state.websitePermissionsState.notification.isEnabled).isEqualTo(defaultEnabledStatus)
|
assertThat(store.state.websitePermissionsState.notification.status).isEqualTo(
|
||||||
assertThat(store.state.websitePermissionsState.notification.isBlockedByAndroid).isEqualTo(defaultBlockedByAndroidStatus)
|
initialNotificationStatus
|
||||||
|
)
|
||||||
|
assertThat(store.state.websitePermissionsState.notification.isVisible).isEqualTo(
|
||||||
|
defaultVisibilityStatus
|
||||||
|
)
|
||||||
|
assertThat(store.state.websitePermissionsState.notification.isEnabled).isEqualTo(
|
||||||
|
defaultEnabledStatus
|
||||||
|
)
|
||||||
|
assertThat(store.state.websitePermissionsState.notification.isBlockedByAndroid).isEqualTo(
|
||||||
|
defaultBlockedByAndroidStatus
|
||||||
|
)
|
||||||
|
|
||||||
assertThat(store.state.websitePermissionsState.location).isNotNull()
|
assertThat(store.state.websitePermissionsState.location).isNotNull()
|
||||||
assertThat((store.state.websitePermissionsState.location as WebsitePermission.Location).name).isEqualTo(locationPermissionName)
|
assertThat((store.state.websitePermissionsState.location as WebsitePermission.Location).name).isEqualTo(
|
||||||
assertThat(store.state.websitePermissionsState.location.status).isEqualTo(initialLocationStatus)
|
locationPermissionName
|
||||||
assertThat(store.state.websitePermissionsState.location.isVisible).isEqualTo(defaultVisibilityStatus)
|
)
|
||||||
assertThat(store.state.websitePermissionsState.location.isEnabled).isEqualTo(defaultEnabledStatus)
|
assertThat(store.state.websitePermissionsState.location.status).isEqualTo(
|
||||||
assertThat(store.state.websitePermissionsState.location.isBlockedByAndroid).isEqualTo(defaultBlockedByAndroidStatus)
|
initialLocationStatus
|
||||||
|
)
|
||||||
|
assertThat(store.state.websitePermissionsState.location.isVisible).isEqualTo(
|
||||||
|
defaultVisibilityStatus
|
||||||
|
)
|
||||||
|
assertThat(store.state.websitePermissionsState.location.isEnabled).isEqualTo(
|
||||||
|
defaultEnabledStatus
|
||||||
|
)
|
||||||
|
assertThat(store.state.websitePermissionsState.location.isBlockedByAndroid).isEqualTo(
|
||||||
|
defaultBlockedByAndroidStatus
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `getSecuredWebsiteUiValues() should return the right values`() {
|
fun `getSecuredWebsiteUiValues() should return the right values`() {
|
||||||
|
|
|
@ -11,63 +11,12 @@ import assertk.assertions.isTrue
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.slot
|
import io.mockk.slot
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import io.mockk.verifyAll
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class QuickSettingsInteractorTest {
|
class QuickSettingsInteractorTest {
|
||||||
private val controller = mockk<QuickSettingsController>(relaxed = true)
|
private val controller = mockk<QuickSettingsController>(relaxed = true)
|
||||||
private val interactor = QuickSettingsInteractor(controller)
|
private val interactor = QuickSettingsInteractor(controller)
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `onReportProblemSelected should delegate the controller`() {
|
|
||||||
val websiteUrl = "https://host.com/page1"
|
|
||||||
val url = slot<String>()
|
|
||||||
|
|
||||||
interactor.onReportProblemSelected(websiteUrl)
|
|
||||||
|
|
||||||
verify {
|
|
||||||
controller.handleReportTrackingProblem(capture(url))
|
|
||||||
}
|
|
||||||
assertAll {
|
|
||||||
assertThat(url.isCaptured).isTrue()
|
|
||||||
assertThat(url.captured).isEqualTo(websiteUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `onProtectionToggled should delegate the controller`() {
|
|
||||||
val trackingEnabled = true
|
|
||||||
val trackingStatus = slot<Boolean>()
|
|
||||||
|
|
||||||
interactor.onProtectionToggled(trackingEnabled)
|
|
||||||
|
|
||||||
verifyAll {
|
|
||||||
controller.handleTrackingProtectionToggled(capture(trackingStatus))
|
|
||||||
}
|
|
||||||
assertAll {
|
|
||||||
assertThat(trackingStatus.isCaptured).isTrue()
|
|
||||||
assertThat(trackingStatus.captured).isEqualTo(trackingEnabled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `onProtectionSettingsSelected should delegate the controller`() {
|
|
||||||
interactor.onProtectionSettingsSelected()
|
|
||||||
|
|
||||||
verify {
|
|
||||||
controller.handleTrackingProtectionSettingsSelected()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `onTrackingProtectionShown should delegate the controller`() {
|
|
||||||
interactor.onTrackingProtectionShown()
|
|
||||||
|
|
||||||
verify {
|
|
||||||
controller.handleTrackingProtectionShown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `onPermissionsShown should delegate the controller`() {
|
fun `onPermissionsShown should delegate the controller`() {
|
||||||
interactor.onPermissionsShown()
|
interactor.onPermissionsShown()
|
||||||
|
|
Loading…
Reference in New Issue