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
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
|
|
@ -42,7 +42,6 @@ import java.io.File
|
|||
open class FenixApplication : Application() {
|
||||
lateinit var fretboard: Fretboard
|
||||
lateinit var experimentLoader: Deferred<Boolean>
|
||||
var experimentLoaderComplete: Boolean = false
|
||||
|
||||
open val components by lazy { Components(this) }
|
||||
|
||||
|
@ -87,10 +86,6 @@ open class FenixApplication : Application() {
|
|||
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
|
||||
|
@ -103,8 +98,6 @@ open class FenixApplication : Application() {
|
|||
ExperimentsMetrics.activeExperiment.set(branchName)
|
||||
}
|
||||
|
||||
ExperimentsManager.initEtpExperiment(this)
|
||||
|
||||
setupLeakCanary()
|
||||
if (settings().isTelemetryEnabled) {
|
||||
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.ViewBoundFeatureWrapper
|
||||
import org.jetbrains.anko.dimen
|
||||
import org.mozilla.fenix.FeatureFlags
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.browser.readermode.DefaultReaderModeController
|
||||
|
@ -217,7 +216,6 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
|
|||
sessionId = session.id,
|
||||
url = session.url,
|
||||
isSecured = session.securityInfo.secure,
|
||||
isTrackingProtectionOn = session.trackerBlockingEnabled,
|
||||
sitePermissions = sitePermissions,
|
||||
gravity = getAppropriateLayoutGravity()
|
||||
)
|
||||
|
@ -360,9 +358,6 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
|
|||
}
|
||||
|
||||
private fun showTrackingProtectionOnboarding() {
|
||||
if (!FeatureFlags.etpCategories) {
|
||||
return
|
||||
}
|
||||
context?.let {
|
||||
val layout = LayoutInflater.from(it)
|
||||
.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.support.base.feature.LifecycleAwareFeature
|
||||
import mozilla.components.support.ktx.android.view.hideKeyboard
|
||||
import org.mozilla.fenix.FeatureFlags
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.settings
|
||||
|
@ -62,19 +61,22 @@ class ToolbarIntegration(
|
|||
val lottieDrawable = LottieDrawable()
|
||||
lottieDrawable.composition = result
|
||||
|
||||
toolbar.display.indicators = if (
|
||||
context.settings().shouldUseTrackingProtection && FeatureFlags.etpCategories
|
||||
) {
|
||||
listOf(
|
||||
DisplayToolbar.Indicators.TRACKING_PROTECTION,
|
||||
DisplayToolbar.Indicators.SECURITY,
|
||||
DisplayToolbar.Indicators.EMPTY)
|
||||
} else {
|
||||
listOf(DisplayToolbar.Indicators.SECURITY, DisplayToolbar.Indicators.EMPTY)
|
||||
}
|
||||
toolbar.display.indicators =
|
||||
if (context.settings().shouldUseTrackingProtection) {
|
||||
listOf(
|
||||
DisplayToolbar.Indicators.TRACKING_PROTECTION,
|
||||
DisplayToolbar.Indicators.SECURITY,
|
||||
DisplayToolbar.Indicators.EMPTY
|
||||
)
|
||||
} else {
|
||||
listOf(
|
||||
DisplayToolbar.Indicators.SECURITY,
|
||||
DisplayToolbar.Indicators.EMPTY
|
||||
)
|
||||
}
|
||||
|
||||
toolbar.display.displayIndicatorSeparator =
|
||||
context.settings().shouldUseTrackingProtection && FeatureFlags.etpCategories
|
||||
context.settings().shouldUseTrackingProtection
|
||||
|
||||
toolbar.display.icons = toolbar.display.icons.copy(
|
||||
emptyIcon = AppCompatResources.getDrawable(
|
||||
|
|
|
@ -18,7 +18,6 @@ import mozilla.components.browser.toolbar.display.DisplayToolbar
|
|||
import mozilla.components.feature.customtabs.CustomTabsToolbarFeature
|
||||
import mozilla.components.support.base.feature.BackHandler
|
||||
import mozilla.components.support.base.feature.LifecycleAwareFeature
|
||||
import org.mozilla.fenix.FeatureFlags
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.toolbar.ToolbarMenu
|
||||
import org.mozilla.fenix.ext.settings
|
||||
|
@ -66,7 +65,7 @@ class CustomTabsIntegration(
|
|||
lottieDrawable.composition = result
|
||||
|
||||
toolbar.display.displayIndicatorSeparator = false
|
||||
if (activity.settings().shouldUseTrackingProtection && FeatureFlags.etpCategories) {
|
||||
if (activity.settings().shouldUseTrackingProtection) {
|
||||
toolbar.display.indicators = listOf(
|
||||
DisplayToolbar.Indicators.SECURITY,
|
||||
DisplayToolbar.Indicators.TRACKING_PROTECTION
|
||||
|
|
|
@ -157,7 +157,6 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler {
|
|||
sessionId = session.id,
|
||||
url = session.url,
|
||||
isSecured = session.securityInfo.secure,
|
||||
isTrackingProtectionOn = session.trackerBlockingEnabled,
|
||||
sitePermissions = sitePermissions,
|
||||
gravity = getAppropriateLayoutGravity()
|
||||
)
|
||||
|
|
|
@ -11,7 +11,6 @@ import androidx.preference.Preference
|
|||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreference
|
||||
import org.mozilla.fenix.BrowserDirection
|
||||
import org.mozilla.fenix.FeatureFlags
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
|
@ -88,9 +87,8 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
|
|||
}
|
||||
|
||||
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.isVisible = FeatureFlags.etpCategories
|
||||
radioStrict.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
|
||||
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
|
||||
if (newValue == true) {
|
||||
|
@ -114,9 +112,8 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
|
|||
}
|
||||
|
||||
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.isVisible = FeatureFlags.etpCategories
|
||||
radioStandard.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
|
||||
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
|
||||
if (newValue == true) {
|
||||
|
|
|
@ -9,19 +9,13 @@ import androidx.annotation.VisibleForTesting
|
|||
import androidx.navigation.NavController
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.ObsoleteCoroutinesApi
|
||||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.feature.session.SessionUseCases.ReloadUrlUseCase
|
||||
import mozilla.components.feature.session.TrackingProtectionUseCases
|
||||
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||
import mozilla.components.feature.tabs.TabsUseCases.AddNewTabUseCase
|
||||
import mozilla.components.support.base.feature.OnNeedToRequestPermissions
|
||||
import org.mozilla.fenix.browser.BrowserFragment
|
||||
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.quicksettings.ext.shouldBeEnabled
|
||||
import org.mozilla.fenix.settings.toggle
|
||||
|
@ -34,29 +28,6 @@ import org.mozilla.fenix.utils.Settings
|
|||
* complex Android interactions or communication with other features.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -94,10 +65,8 @@ interface QuickSettingsController {
|
|||
* @param requestRuntimePermissions [OnNeedToRequestPermissions] callback allowing for requesting
|
||||
* specific Android runtime permissions.
|
||||
* @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 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")
|
||||
class DefaultQuickSettingsController(
|
||||
|
@ -113,55 +82,9 @@ class DefaultQuickSettingsController(
|
|||
private val addNewTab: AddNewTabUseCase,
|
||||
private val requestRuntimePermissions: OnNeedToRequestPermissions = { },
|
||||
private val reportSiteIssue: () -> Unit,
|
||||
private val displayTrackingProtection: () -> Unit,
|
||||
private val displayPermissions: () -> Unit,
|
||||
private val dismiss: () -> Unit,
|
||||
private val trackingProtectionUseCases: TrackingProtectionUseCases
|
||||
private val dismiss: () -> Unit
|
||||
) : 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() {
|
||||
displayPermissions()
|
||||
}
|
||||
|
|
|
@ -14,9 +14,9 @@ import mozilla.components.lib.state.Action
|
|||
import mozilla.components.lib.state.Reducer
|
||||
import mozilla.components.lib.state.State
|
||||
import mozilla.components.lib.state.Store
|
||||
import org.mozilla.fenix.FeatureFlags
|
||||
import org.mozilla.fenix.R
|
||||
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.shouldBeVisible
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
@ -68,8 +68,6 @@ class QuickSettingsFragmentStore(
|
|||
* @param context [Context] used for access to various Android resources.
|
||||
* @param websiteUrl [String] the URL of the current web page.
|
||||
* @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 settings [Settings] application settings.
|
||||
*/
|
||||
|
@ -78,40 +76,19 @@ class QuickSettingsFragmentStore(
|
|||
context: Context,
|
||||
websiteUrl: String,
|
||||
isSecured: Boolean,
|
||||
isTrackingProtectionOn: Boolean,
|
||||
permissions: SitePermissions?,
|
||||
settings: Settings
|
||||
) = QuickSettingsFragmentStore(
|
||||
QuickSettingsFragmentState(
|
||||
trackingProtectionState = createTrackingProtectionState(websiteUrl, isTrackingProtectionOn, settings),
|
||||
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]
|
||||
* based on the current website's status and connection.
|
||||
|
@ -149,14 +126,19 @@ class QuickSettingsFragmentStore(
|
|||
permissions: SitePermissions?,
|
||||
settings: Settings
|
||||
): WebsitePermissionsState {
|
||||
val cameraPermission = PhoneFeature.CAMERA.toWebsitePermission(context, permissions, settings)
|
||||
val microphonePermission = PhoneFeature.MICROPHONE.toWebsitePermission(context, permissions, settings)
|
||||
val notificationPermission = PhoneFeature.NOTIFICATION.toWebsitePermission(context, permissions, settings)
|
||||
val locationPermission = PhoneFeature.LOCATION.toWebsitePermission(context, permissions, settings)
|
||||
val cameraPermission =
|
||||
PhoneFeature.CAMERA.toWebsitePermission(context, permissions, settings)
|
||||
val microphonePermission =
|
||||
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 ||
|
||||
notificationPermission.isVisible || locationPermission.isVisible
|
||||
|
||||
return WebsitePermissionsState(shouldBeVisible, cameraPermission, microphonePermission,
|
||||
return WebsitePermissionsState(
|
||||
shouldBeVisible, cameraPermission, microphonePermission,
|
||||
notificationPermission, locationPermission
|
||||
)
|
||||
}
|
||||
|
@ -227,28 +209,10 @@ class QuickSettingsFragmentStore(
|
|||
* Partitioned further to contain mutiple states for each standalone View this Fragment holds.
|
||||
*/
|
||||
data class QuickSettingsFragmentState(
|
||||
val trackingProtectionState: TrackingProtectionState,
|
||||
val webInfoState: WebsiteInfoState,
|
||||
val websitePermissionsState: WebsitePermissionsState
|
||||
) : 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.
|
||||
*
|
||||
|
@ -428,16 +392,6 @@ sealed class WebsitePermission {
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -475,12 +429,6 @@ fun quickSettingsFragmentReducer(
|
|||
action: QuickSettingsFragmentAction
|
||||
): QuickSettingsFragmentState {
|
||||
return when (action) {
|
||||
is TrackingProtectionAction -> state.copy(
|
||||
trackingProtectionState = TrackingProtectionStateReducer.reduce(
|
||||
state.trackingProtectionState,
|
||||
action
|
||||
)
|
||||
)
|
||||
is WebsiteInfoAction -> state.copy(
|
||||
webInfoState = WebsiteInfoStateReducer.reduce(
|
||||
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
|
||||
object WebsiteInfoStateReducer {
|
||||
/**
|
||||
|
|
|
@ -15,24 +15,7 @@ package org.mozilla.fenix.settings.quicksettings
|
|||
*/
|
||||
class QuickSettingsInteractor(
|
||||
private val controller: QuickSettingsController
|
||||
) : WebsitePermissionInteractor, TrackingProtectionInteractor {
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
) : WebsitePermissionInteractor {
|
||||
override fun onPermissionsShown() {
|
||||
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.view.*
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import mozilla.components.feature.session.TrackingProtectionUseCases
|
||||
import mozilla.components.lib.state.ext.consumeFrom
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.IntentReceiverActivity
|
||||
|
@ -47,7 +46,6 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
|
|||
private lateinit var quickSettingsController: QuickSettingsController
|
||||
private lateinit var websiteInfoView: WebsiteInfoView
|
||||
private lateinit var websitePermissionsView: WebsitePermissionsView
|
||||
private lateinit var websiteTrackingProtectionView: TrackingProtectionView
|
||||
private lateinit var interactor: QuickSettingsInteractor
|
||||
private val safeArguments get() = requireNotNull(arguments)
|
||||
private val promptGravity: Int by lazy {
|
||||
|
@ -70,7 +68,6 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
|
|||
context = context,
|
||||
websiteUrl = args.url,
|
||||
isSecured = args.isSecured,
|
||||
isTrackingProtectionOn = args.isTrackingProtectionOn,
|
||||
permissions = args.sitePermissions,
|
||||
settings = Settings.getInstance(context)
|
||||
)
|
||||
|
@ -90,19 +87,12 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
|
|||
requestPermissions(permissions, REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS)
|
||||
},
|
||||
reportSiteIssue = ::launchIntentReceiver,
|
||||
displayTrackingProtection = ::showTrackingProtectionView,
|
||||
displayPermissions = ::showPermissionsView,
|
||||
dismiss = ::dismiss,
|
||||
trackingProtectionUseCases = TrackingProtectionUseCases(
|
||||
context.components.core.sessionManager,
|
||||
context.components.core.engine
|
||||
)
|
||||
dismiss = ::dismiss
|
||||
)
|
||||
|
||||
interactor = QuickSettingsInteractor(quickSettingsController)
|
||||
|
||||
websiteTrackingProtectionView =
|
||||
TrackingProtectionView(rootView.trackingProtectionLayout, interactor)
|
||||
websiteInfoView = WebsiteInfoView(rootView.websiteInfoLayout)
|
||||
websitePermissionsView =
|
||||
WebsitePermissionsView(rootView.websitePermissionsLayout, interactor)
|
||||
|
@ -143,7 +133,6 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
|
|||
|
||||
consumeFrom(quickSettingsStore) {
|
||||
websiteInfoView.update(it.webInfoState)
|
||||
websiteTrackingProtectionView.update(it.trackingProtectionState)
|
||||
websitePermissionsView.update(it.websitePermissionsState)
|
||||
}
|
||||
}
|
||||
|
@ -181,10 +170,6 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
|
|||
private fun arePermissionsGranted(requestCode: Int, grantResults: IntArray) =
|
||||
requestCode == REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS && grantResults.all { it == PERMISSION_GRANTED }
|
||||
|
||||
private fun showTrackingProtectionView() {
|
||||
trackingProtectionGroup.isVisible = true
|
||||
}
|
||||
|
||||
private fun showPermissionsView() {
|
||||
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(
|
||||
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_strict),
|
||||
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_strict_default),
|
||||
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(
|
||||
appContext.getPreferenceKey(R.string.pref_key_delete_browsing_data_on_quit),
|
||||
default = false
|
||||
|
|
|
@ -22,12 +22,6 @@
|
|||
android:id="@+id/websiteInfoLayout"
|
||||
android:layout_width="match_parent"
|
||||
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" />
|
||||
|
||||
<FrameLayout
|
||||
|
@ -45,23 +39,6 @@
|
|||
android:background="?neutralFaded"
|
||||
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
|
||||
android:id="@+id/websitePermissionsGroup"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -564,8 +564,7 @@
|
|||
</dialog>
|
||||
<dialog
|
||||
android:id="@+id/quickSettingsSheetDialogFragment"
|
||||
android:name="org.mozilla.fenix.settings.quicksettings.QuickSettingsSheetDialogFragment"
|
||||
android:label="QuickSettingsSheetDialogFragment">
|
||||
android:name="org.mozilla.fenix.settings.quicksettings.QuickSettingsSheetDialogFragment">
|
||||
<argument
|
||||
android:name="sessionId"
|
||||
app:argType="string" />
|
||||
|
@ -575,9 +574,6 @@
|
|||
<argument
|
||||
android:name="isSecured"
|
||||
app:argType="boolean" />
|
||||
<argument
|
||||
android:name="isTrackingProtectionOn"
|
||||
app:argType="boolean" />
|
||||
<argument
|
||||
android:name="sitePermissions"
|
||||
app:argType="mozilla.components.feature.sitepermissions.SitePermissions"
|
||||
|
@ -586,11 +582,6 @@
|
|||
android:name="gravity"
|
||||
android:defaultValue="80"
|
||||
app:argType="integer" />
|
||||
<action
|
||||
android:id="@+id/action_quickSettingsSheetDialogFragment_to_trackingProtectionFragment"
|
||||
app:destination="@id/trackingProtectionFragment"
|
||||
app:popUpTo="@id/quickSettingsSheetDialogFragment"
|
||||
app:popUpToInclusive="true" />
|
||||
</dialog>
|
||||
<fragment
|
||||
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" 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_standard" translatable="false">pref_key_tracking_protection_standard</string>
|
||||
<string name="pref_key_tracking_protection_strict" translatable="false">pref_key_tracking_protection_strict</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_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>
|
||||
|
||||
<!-- Logins Settings -->
|
||||
|
|
|
@ -18,17 +18,15 @@
|
|||
<org.mozilla.fenix.settings.RadioButtonInfoPreference
|
||||
android:defaultValue="false"
|
||||
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:title="@string/preference_enhanced_tracking_protection_standard_option"
|
||||
app:isPreferenceVisible="false" />
|
||||
android:title="@string/preference_enhanced_tracking_protection_standard_option" />
|
||||
<org.mozilla.fenix.settings.RadioButtonInfoPreference
|
||||
android:defaultValue="true"
|
||||
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:title="@string/preference_enhanced_tracking_protection_strict_default"
|
||||
app:isPreferenceVisible="false" />
|
||||
android:title="@string/preference_enhanced_tracking_protection_strict_default" />
|
||||
<Preference
|
||||
android:icon="@drawable/ic_internet"
|
||||
android:key="@string/pref_key_tracking_protection_exceptions"
|
||||
|
|
|
@ -24,7 +24,6 @@ import kotlinx.coroutines.ObsoleteCoroutinesApi
|
|||
import kotlinx.coroutines.runBlocking
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.feature.session.SessionUseCases
|
||||
import mozilla.components.feature.session.TrackingProtectionUseCases
|
||||
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||
import mozilla.components.feature.sitepermissions.SitePermissions.Status.NO_DECISION
|
||||
import mozilla.components.feature.tabs.TabsUseCases
|
||||
|
@ -32,10 +31,7 @@ import mozilla.components.support.test.robolectric.testContext
|
|||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.TestApplication
|
||||
import org.mozilla.fenix.browser.BrowserFragment
|
||||
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.quicksettings.ext.shouldBeEnabled
|
||||
import org.mozilla.fenix.settings.toggle
|
||||
|
@ -59,10 +55,8 @@ class DefaultQuickSettingsControllerTest {
|
|||
private val addNewTab = mockk<TabsUseCases.AddNewTabUseCase>(relaxed = true)
|
||||
private val requestPermissions = mockk<(Array<String>) -> 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 dismiss = mockk<() -> Unit>(relaxed = true)
|
||||
private val trackingProtectionUseCases = mockk<TrackingProtectionUseCases>(relaxed = true)
|
||||
private val controller = DefaultQuickSettingsController(
|
||||
context = context,
|
||||
quickSettingsStore = store,
|
||||
|
@ -76,99 +70,10 @@ class DefaultQuickSettingsControllerTest {
|
|||
addNewTab = addNewTab,
|
||||
requestRuntimePermissions = requestPermissions,
|
||||
reportSiteIssue = reportIssue,
|
||||
displayTrackingProtection = displayTrackingProtection,
|
||||
displayPermissions = displayPermissions,
|
||||
dismiss = dismiss,
|
||||
trackingProtectionUseCases = trackingProtectionUseCases
|
||||
dismiss = dismiss
|
||||
)
|
||||
|
||||
@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
|
||||
fun `handlePermissionsShown should delegate to an injected parameter`() {
|
||||
controller.handlePermissionsShown()
|
||||
|
|
|
@ -10,7 +10,6 @@ import assertk.assertThat
|
|||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isFalse
|
||||
import assertk.assertions.isInstanceOf
|
||||
import assertk.assertions.isNotEqualTo
|
||||
import assertk.assertions.isNotNull
|
||||
import assertk.assertions.isNotSameAs
|
||||
import assertk.assertions.isSameAs
|
||||
|
@ -56,17 +55,15 @@ class QuickSettingsFragmentStoreTest {
|
|||
fun `createStore constructs a QuickSettingsFragmentState`() {
|
||||
val settings = mockk<Settings>(relaxed = true)
|
||||
val permissions = mockk<SitePermissions>(relaxed = true)
|
||||
every { settings.shouldUseTrackingProtection } returns true
|
||||
|
||||
val store = QuickSettingsFragmentStore.createStore(
|
||||
context, "url", true, true, permissions, settings
|
||||
context, "url", true, permissions, settings
|
||||
)
|
||||
|
||||
assertAll {
|
||||
assertThat(store).isNotNull()
|
||||
assertThat(store.state).isNotNull()
|
||||
assertThat(store.state.webInfoState).isNotNull()
|
||||
assertThat(store.state.trackingProtectionState).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
|
||||
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.microphone } returns SitePermissions.Status.NO_DECISION
|
||||
every { permissions.notification } returns SitePermissions.Status.BLOCKED
|
||||
|
@ -150,7 +133,13 @@ class QuickSettingsFragmentStoreTest {
|
|||
fun `PhoneFeature#toWebsitePermission helps in constructing the right WebsitePermission`() {
|
||||
val cameraFeature = PhoneFeature.CAMERA
|
||||
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
|
||||
|
||||
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
|
||||
@ExperimentalCoroutinesApi
|
||||
fun `TogglePermission should only modify status and visibility of a specific WebsitePermissionsState`() = runBlocking {
|
||||
val cameraPermissionName = "Camera"
|
||||
val microphonePermissionName = "Microphone"
|
||||
val notificationPermissionName = "Notification"
|
||||
val locationPermissionName = "Location"
|
||||
val initialCameraStatus = "initialCameraStatus"
|
||||
val initialMicStatus = "initialMicStatus"
|
||||
val initialNotificationStatus = "initialNotificationStatus"
|
||||
val initialLocationStatus = "initialLocationStatus"
|
||||
val updatedMicrophoneStatus = "updatedNotificationStatus"
|
||||
val updatedMicrophoneEnabledStatus = false
|
||||
val defaultVisibilityStatus = true
|
||||
val defaultEnabledStatus = true
|
||||
val defaultBlockedByAndroidStatus = true
|
||||
val websiteInfoState = mockk<WebsiteInfoState>()
|
||||
val trackingProtectionState = mockk<TrackingProtectionState>()
|
||||
val initialWebsitePermissionsState = WebsitePermissionsState(
|
||||
isVisible = true,
|
||||
camera = WebsitePermission.Camera(initialCameraStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, cameraPermissionName),
|
||||
microphone = WebsitePermission.Microphone(initialMicStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, microphonePermissionName),
|
||||
notification = WebsitePermission.Notification(initialNotificationStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, notificationPermissionName),
|
||||
location = WebsitePermission.Location(initialLocationStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, locationPermissionName)
|
||||
)
|
||||
val initialState = QuickSettingsFragmentState(
|
||||
trackingProtectionState, websiteInfoState, initialWebsitePermissionsState
|
||||
)
|
||||
val store = QuickSettingsFragmentStore(initialState)
|
||||
fun `TogglePermission should only modify status and visibility of a specific WebsitePermissionsState`() =
|
||||
runBlocking {
|
||||
val cameraPermissionName = "Camera"
|
||||
val microphonePermissionName = "Microphone"
|
||||
val notificationPermissionName = "Notification"
|
||||
val locationPermissionName = "Location"
|
||||
val initialCameraStatus = "initialCameraStatus"
|
||||
val initialMicStatus = "initialMicStatus"
|
||||
val initialNotificationStatus = "initialNotificationStatus"
|
||||
val initialLocationStatus = "initialLocationStatus"
|
||||
val updatedMicrophoneStatus = "updatedNotificationStatus"
|
||||
val updatedMicrophoneEnabledStatus = false
|
||||
val defaultVisibilityStatus = true
|
||||
val defaultEnabledStatus = true
|
||||
val defaultBlockedByAndroidStatus = true
|
||||
val websiteInfoState = mockk<WebsiteInfoState>()
|
||||
val initialWebsitePermissionsState = WebsitePermissionsState(
|
||||
isVisible = true,
|
||||
camera = WebsitePermission.Camera(
|
||||
initialCameraStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, cameraPermissionName
|
||||
),
|
||||
microphone = WebsitePermission.Microphone(
|
||||
initialMicStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, microphonePermissionName
|
||||
),
|
||||
notification = WebsitePermission.Notification(
|
||||
initialNotificationStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, notificationPermissionName
|
||||
),
|
||||
location = WebsitePermission.Location(
|
||||
initialLocationStatus, defaultVisibilityStatus,
|
||||
defaultEnabledStatus, defaultBlockedByAndroidStatus, locationPermissionName
|
||||
)
|
||||
)
|
||||
val initialState = QuickSettingsFragmentState(
|
||||
websiteInfoState, initialWebsitePermissionsState
|
||||
)
|
||||
val store = QuickSettingsFragmentStore(initialState)
|
||||
|
||||
store.dispatch(WebsitePermissionAction.TogglePermission(
|
||||
mockk<WebsitePermission.Microphone>(), updatedMicrophoneStatus, updatedMicrophoneEnabledStatus)
|
||||
).join()
|
||||
store.dispatch(
|
||||
WebsitePermissionAction.TogglePermission(
|
||||
mockk<WebsitePermission.Microphone>(),
|
||||
updatedMicrophoneStatus,
|
||||
updatedMicrophoneEnabledStatus
|
||||
)
|
||||
).join()
|
||||
|
||||
assertAll {
|
||||
assertThat(store.state).isNotNull()
|
||||
assertThat(store.state).isNotSameAs(initialState)
|
||||
assertThat(store.state.websitePermissionsState).isNotSameAs(initialWebsitePermissionsState)
|
||||
assertThat(store.state.webInfoState).isSameAs(websiteInfoState)
|
||||
assertThat(store.state.trackingProtectionState).isSameAs(trackingProtectionState)
|
||||
assertAll {
|
||||
assertThat(store.state).isNotNull()
|
||||
assertThat(store.state).isNotSameAs(initialState)
|
||||
assertThat(store.state.websitePermissionsState).isNotSameAs(
|
||||
initialWebsitePermissionsState
|
||||
)
|
||||
assertThat(store.state.webInfoState).isSameAs(websiteInfoState)
|
||||
|
||||
assertThat(store.state.websitePermissionsState.camera).isNotNull()
|
||||
assertThat((store.state.websitePermissionsState.camera as WebsitePermission.Camera).name).isEqualTo(cameraPermissionName)
|
||||
assertThat(store.state.websitePermissionsState.camera.status).isEqualTo(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.camera).isNotNull()
|
||||
assertThat((store.state.websitePermissionsState.camera as WebsitePermission.Camera).name).isEqualTo(
|
||||
cameraPermissionName
|
||||
)
|
||||
assertThat(store.state.websitePermissionsState.camera.status).isEqualTo(
|
||||
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 as WebsitePermission.Microphone).name).isEqualTo(microphonePermissionName)
|
||||
// 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).isNotNull()
|
||||
assertThat((store.state.websitePermissionsState.microphone as WebsitePermission.Microphone).name).isEqualTo(
|
||||
microphonePermissionName
|
||||
)
|
||||
// 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.isBlockedByAndroid).isEqualTo(defaultBlockedByAndroidStatus)
|
||||
assertThat(store.state.websitePermissionsState.microphone.isVisible).isEqualTo(
|
||||
defaultVisibilityStatus
|
||||
)
|
||||
assertThat(store.state.websitePermissionsState.microphone.isBlockedByAndroid).isEqualTo(
|
||||
defaultBlockedByAndroidStatus
|
||||
)
|
||||
|
||||
assertThat(store.state.websitePermissionsState.notification).isNotNull()
|
||||
assertThat((store.state.websitePermissionsState.notification as WebsitePermission.Notification).name).isEqualTo(notificationPermissionName)
|
||||
assertThat(store.state.websitePermissionsState.notification.status).isEqualTo(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.notification).isNotNull()
|
||||
assertThat((store.state.websitePermissionsState.notification as WebsitePermission.Notification).name).isEqualTo(
|
||||
notificationPermissionName
|
||||
)
|
||||
assertThat(store.state.websitePermissionsState.notification.status).isEqualTo(
|
||||
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 as WebsitePermission.Location).name).isEqualTo(locationPermissionName)
|
||||
assertThat(store.state.websitePermissionsState.location.status).isEqualTo(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)
|
||||
assertThat(store.state.websitePermissionsState.location).isNotNull()
|
||||
assertThat((store.state.websitePermissionsState.location as WebsitePermission.Location).name).isEqualTo(
|
||||
locationPermissionName
|
||||
)
|
||||
assertThat(store.state.websitePermissionsState.location.status).isEqualTo(
|
||||
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
|
||||
fun `getSecuredWebsiteUiValues() should return the right values`() {
|
||||
|
|
|
@ -11,63 +11,12 @@ import assertk.assertions.isTrue
|
|||
import io.mockk.mockk
|
||||
import io.mockk.slot
|
||||
import io.mockk.verify
|
||||
import io.mockk.verifyAll
|
||||
import org.junit.Test
|
||||
|
||||
class QuickSettingsInteractorTest {
|
||||
private val controller = mockk<QuickSettingsController>(relaxed = true)
|
||||
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
|
||||
fun `onPermissionsShown should delegate the controller`() {
|
||||
interactor.onPermissionsShown()
|
||||
|
|
Loading…
Reference in New Issue