1
0
Fork 0

For #8540: Fix ETP options not being correctly applied (#8688)

master
Mihai Adrian 2020-02-26 22:25:40 +02:00 committed by GitHub
parent e2b72a9c01
commit 9612c3f16d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 539 additions and 125 deletions

View File

@ -47,7 +47,8 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
session.disableTrackingProtection()
} else {
val core = context.components.core
val policy = core.createTrackingProtectionPolicy(normalMode = true)
val policy = core.trackingProtectionPolicyFactory
.createTrackingProtectionPolicy(normalMode = true)
core.engine.settings.trackingProtectionPolicy = policy
session.enableTrackingProtection(policy)
}

View File

@ -25,9 +25,6 @@ import mozilla.components.browser.storage.sync.PlacesBookmarksStorage
import mozilla.components.browser.storage.sync.PlacesHistoryStorage
import mozilla.components.concept.engine.DefaultSettings
import mozilla.components.concept.engine.Engine
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.CookiePolicy
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.TrackingCategory
import mozilla.components.concept.engine.mediaquery.PreferredColorScheme
import mozilla.components.concept.fetch.Client
import mozilla.components.feature.customtabs.store.CustomTabsServiceStore
@ -67,7 +64,7 @@ class Core(private val context: Context) {
requestInterceptor = AppRequestInterceptor(context),
remoteDebuggingEnabled = context.settings().isRemoteDebuggingEnabled,
testingModeEnabled = false,
trackingProtectionPolicy = createTrackingProtectionPolicy(),
trackingProtectionPolicy = trackingProtectionPolicyFactory.createTrackingProtectionPolicy(),
historyTrackingDelegate = HistoryDelegate(historyStorage),
preferredColorScheme = getPreferredColorScheme(),
automaticFontSizeAdjustment = context.settings().shouldUseAutoSize,
@ -252,74 +249,7 @@ class Core(private val context: Context) {
getSecureAbove22Preferences().putString(PASSWORDS_KEY, it)
}
/**
* Constructs a [TrackingProtectionPolicy] based on current preferences.
*
* @param normalMode whether or not tracking protection should be enabled
* in normal browsing mode, defaults to the current preference value.
* @param privateMode whether or not tracking protection should be enabled
* in private browsing mode, default to the current preference value.
* @return the constructed tracking protection policy based on preferences.
*/
@Suppress("ComplexMethod")
fun createTrackingProtectionPolicy(
normalMode: Boolean = context.settings().shouldUseTrackingProtection,
privateMode: Boolean = true
): TrackingProtectionPolicy {
val trackingProtectionPolicy =
when {
context.settings().useStrictTrackingProtection -> TrackingProtectionPolicy.strict()
context.settings().useCustomTrackingProtection -> return TrackingProtectionPolicy.select(
cookiePolicy = geCustomCookiePolicy(),
trackingCategories = getCustomTrackingCategories()
).apply {
if (context.settings().blockTrackingContentSelectionInCustomTrackingProtection == "private") {
forPrivateSessionsOnly()
}
}
else -> TrackingProtectionPolicy.recommended()
}
return when {
normalMode && privateMode -> trackingProtectionPolicy
normalMode && !privateMode -> trackingProtectionPolicy.forRegularSessionsOnly()
!normalMode && privateMode -> trackingProtectionPolicy.forPrivateSessionsOnly()
else -> TrackingProtectionPolicy.none()
}
}
private fun geCustomCookiePolicy(): CookiePolicy {
return when (context.settings().blockCookiesSelectionInCustomTrackingProtection) {
"all" -> CookiePolicy.ACCEPT_NONE
"social" -> CookiePolicy.ACCEPT_NON_TRACKERS
"unvisited" -> CookiePolicy.ACCEPT_VISITED
"third-party" -> CookiePolicy.ACCEPT_ONLY_FIRST_PARTY
else -> CookiePolicy.ACCEPT_NONE
}
}
private fun getCustomTrackingCategories(): Array<TrackingCategory> {
val categories = arrayListOf(
TrackingCategory.AD,
TrackingCategory.ANALYTICS,
TrackingCategory.SOCIAL,
TrackingCategory.MOZILLA_SOCIAL
)
if (context.settings().blockTrackingContentInCustomTrackingProtection) {
categories.add(TrackingCategory.SCRIPTS_AND_SUB_RESOURCES)
}
if (context.settings().blockFingerprintersInCustomTrackingProtection) {
categories.add(TrackingCategory.FINGERPRINTING)
}
if (context.settings().blockCryptominersInCustomTrackingProtection) {
categories.add(TrackingCategory.CRYPTOMINING)
}
return categories.toTypedArray()
}
val trackingProtectionPolicyFactory = TrackingProtectionPolicyFactory(context.settings())
/**
* Sets Preferred Color scheme based on Dark/Light Theme Settings or Current Configuration

View File

@ -0,0 +1,93 @@
/* 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.components
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
import org.mozilla.fenix.utils.Settings
/**
* Handles the logic behind creating new [TrackingProtectionPolicy]s.
*/
class TrackingProtectionPolicyFactory(private val settings: Settings) {
/**
* Constructs a [TrackingProtectionPolicy] based on current preferences.
*
* @param normalMode whether or not tracking protection should be enabled
* in normal browsing mode, defaults to the current preference value.
* @param privateMode whether or not tracking protection should be enabled
* in private browsing mode, default to the current preference value.
* @return the constructed tracking protection policy based on preferences.
*/
@Suppress("ComplexMethod")
fun createTrackingProtectionPolicy(
normalMode: Boolean = settings.shouldUseTrackingProtection,
privateMode: Boolean = true
): TrackingProtectionPolicy {
val trackingProtectionPolicy =
when {
settings.useStrictTrackingProtection -> TrackingProtectionPolicy.strict()
settings.useCustomTrackingProtection -> return createCustomTrackingProtectionPolicy()
else -> TrackingProtectionPolicy.recommended()
}
return when {
normalMode && privateMode -> trackingProtectionPolicy
normalMode && !privateMode -> trackingProtectionPolicy.forRegularSessionsOnly()
!normalMode && privateMode -> trackingProtectionPolicy.forPrivateSessionsOnly()
else -> TrackingProtectionPolicy.none()
}
}
private fun createCustomTrackingProtectionPolicy(): TrackingProtectionPolicy {
return TrackingProtectionPolicy.select(
cookiePolicy = getCustomCookiePolicy(),
trackingCategories = getCustomTrackingCategories()
).let {
if (settings.blockTrackingContentSelectionInCustomTrackingProtection == "private") {
it.forPrivateSessionsOnly()
} else {
it
}
}
}
private fun getCustomCookiePolicy(): TrackingProtectionPolicy.CookiePolicy {
return if (!settings.blockCookiesInCustomTrackingProtection) {
TrackingProtectionPolicy.CookiePolicy.ACCEPT_ALL
} else {
when (settings.blockCookiesSelectionInCustomTrackingProtection) {
"all" -> TrackingProtectionPolicy.CookiePolicy.ACCEPT_NONE
"social" -> TrackingProtectionPolicy.CookiePolicy.ACCEPT_NON_TRACKERS
"unvisited" -> TrackingProtectionPolicy.CookiePolicy.ACCEPT_VISITED
"third-party" -> TrackingProtectionPolicy.CookiePolicy.ACCEPT_ONLY_FIRST_PARTY
else -> TrackingProtectionPolicy.CookiePolicy.ACCEPT_NONE
}
}
}
private fun getCustomTrackingCategories(): Array<TrackingProtectionPolicy.TrackingCategory> {
val categories = arrayListOf(
TrackingProtectionPolicy.TrackingCategory.AD,
TrackingProtectionPolicy.TrackingCategory.ANALYTICS,
TrackingProtectionPolicy.TrackingCategory.SOCIAL,
TrackingProtectionPolicy.TrackingCategory.MOZILLA_SOCIAL
)
if (settings.blockTrackingContentInCustomTrackingProtection) {
categories.add(TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES)
}
if (settings.blockFingerprintersInCustomTrackingProtection) {
categories.add(TrackingProtectionPolicy.TrackingCategory.FINGERPRINTING)
}
if (settings.blockCryptominersInCustomTrackingProtection) {
categories.add(TrackingProtectionPolicy.TrackingCategory.CRYPTOMINING)
}
return categories.toTypedArray()
}
}

View File

@ -105,7 +105,8 @@ class OnboardingTrackingProtectionViewHolder(view: View) : RecyclerView.ViewHold
private fun updateTrackingProtectionSetting(enabled: Boolean) {
itemView.context.settings().shouldUseTrackingProtection = enabled
with(itemView.context.components) {
val policy = core.createTrackingProtectionPolicy(enabled)
val policy = core.trackingProtectionPolicyFactory
.createTrackingProtectionPolicy(enabled)
useCases.settingsUseCases.updateTrackingProtection.invoke(policy)
useCases.sessionUseCases.reload.invoke()
}
@ -113,7 +114,8 @@ class OnboardingTrackingProtectionViewHolder(view: View) : RecyclerView.ViewHold
private fun updateTrackingProtectionPolicy() {
itemView.context?.components?.let {
val policy = it.core.createTrackingProtectionPolicy()
val policy = it.core.trackingProtectionPolicyFactory
.createTrackingProtectionPolicy()
it.useCases.settingsUseCases.updateTrackingProtection.invoke(policy)
it.useCases.sessionUseCases.reload.invoke()
}

View File

@ -23,8 +23,8 @@ import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.showToolbar
/**
* Displays the toggle for tracking protection and a button to open
* the tracking protection [org.mozilla.fenix.exceptions.ExceptionsFragment].
* Displays the toggle for tracking protection, options for tracking protection policy and a button
* to open info about the tracking protection [org.mozilla.fenix.exceptions.ExceptionsFragment].
*/
class TrackingProtectionFragment : PreferenceFragmentCompat() {
@ -66,7 +66,8 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
preference.context.settings().shouldUseTrackingProtection =
trackingProtectionOn
with(preference.context.components) {
val policy = core.createTrackingProtectionPolicy(trackingProtectionOn)
val policy = core.trackingProtectionPolicyFactory
.createTrackingProtectionPolicy(trackingProtectionOn)
useCases.settingsUseCases.updateTrackingProtection(policy)
useCases.sessionUseCases.reload()
}
@ -100,20 +101,17 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
radioStrict = requireNotNull(findPreference(keyStrict))
radioStrict.contentDescription =
getString(R.string.preference_enhanced_tracking_protection_strict_info_button)
radioStrict.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
if (newValue == true) {
updateTrackingProtectionPolicy()
context?.metrics?.track(
Event.TrackingProtectionSettingChanged(
Event.TrackingProtectionSettingChanged.Setting.STRICT
)
)
}
updateCustomOptionsVisibility()
return super.onPreferenceChange(preference, newValue)
}
radioStrict.onClickListener {
updateCustomOptionsVisibility()
updateTrackingProtectionPolicy()
context?.metrics?.track(
Event.TrackingProtectionSettingChanged(
Event.TrackingProtectionSettingChanged.Setting.STRICT
)
)
}
radioStrict.onInfoClickListener {
nav(
R.id.trackingProtectionFragment,
@ -130,20 +128,17 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
radioStandard = requireNotNull(findPreference(keyStandard))
radioStandard.contentDescription =
getString(R.string.preference_enhanced_tracking_protection_standard_info_button)
radioStandard.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
if (newValue == true) {
updateTrackingProtectionPolicy()
context?.metrics?.track(
Event.TrackingProtectionSettingChanged(
Event.TrackingProtectionSettingChanged.Setting.STANDARD
)
)
}
updateCustomOptionsVisibility()
return super.onPreferenceChange(preference, newValue)
}
radioStandard.onClickListener {
updateCustomOptionsVisibility()
updateTrackingProtectionPolicy()
context?.metrics?.track(
Event.TrackingProtectionSettingChanged(
Event.TrackingProtectionSettingChanged.Setting.STANDARD
)
)
}
radioStandard.onInfoClickListener {
nav(
R.id.trackingProtectionFragment,
@ -160,14 +155,10 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
radioCustom = requireNotNull(findPreference(keyCustom))
radioCustom.contentDescription =
getString(R.string.preference_enhanced_tracking_protection_custom_info_button)
radioCustom.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
if (newValue == true) {
updateTrackingProtectionPolicy()
}
updateCustomOptionsVisibility()
return super.onPreferenceChange(preference, newValue)
}
radioCustom.onClickListener {
updateCustomOptionsVisibility()
updateTrackingProtectionPolicy()
}
radioCustom.onInfoClickListener {
nav(
@ -213,34 +204,52 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
customCookies.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
updateTrackingProtectionPolicy()
customCookiesSelect.isVisible = !customCookies.isChecked
return super.onPreferenceChange(preference, newValue)
return super.onPreferenceChange(preference, newValue).also {
updateTrackingProtectionPolicy()
}
}
}
customTracking.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
updateTrackingProtectionPolicy()
customTrackingSelect.isVisible = !customTracking.isChecked
return super.onPreferenceChange(preference, newValue)
return super.onPreferenceChange(preference, newValue).also {
updateTrackingProtectionPolicy()
}
}
}
customCookiesSelect.onPreferenceChangeListener = object : StringSharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
updateTrackingProtectionPolicy()
val newValueEntry = (preference as DropDownListPreference).findEntry(key = newValue)
return super.onPreferenceChange(preference, newValueEntry)
return super.onPreferenceChange(preference, newValue).also {
updateTrackingProtectionPolicy()
}
}
}
customTrackingSelect.onPreferenceChangeListener = object : StringSharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
updateTrackingProtectionPolicy()
val newValueEntry = (preference as DropDownListPreference).findEntry(key = newValue)
return super.onPreferenceChange(preference, newValueEntry)
return super.onPreferenceChange(preference, newValue).also {
updateTrackingProtectionPolicy()
}
}
}
customCryptominers.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
return super.onPreferenceChange(preference, newValue).also {
updateTrackingProtectionPolicy()
}
}
}
customFingerprinters.onPreferenceChangeListener = object : SharedPreferenceUpdater() {
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
return super.onPreferenceChange(preference, newValue).also {
updateTrackingProtectionPolicy()
}
}
}
@ -249,7 +258,8 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
private fun updateTrackingProtectionPolicy() {
context?.components?.let {
val policy = it.core.createTrackingProtectionPolicy()
val policy = it.core.trackingProtectionPolicyFactory
.createTrackingProtectionPolicy()
it.useCases.settingsUseCases.updateTrackingProtection.invoke(policy)
it.useCases.sessionUseCases.reload.invoke()
}

View File

@ -247,9 +247,10 @@ class Settings private constructor(
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_custom_cookies),
true
)
val blockCookiesSelectionInCustomTrackingProtection by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_custom_cookies_select),
""
"social"
)
val blockTrackingContentInCustomTrackingProtection by booleanPreference(
@ -259,7 +260,7 @@ class Settings private constructor(
val blockTrackingContentSelectionInCustomTrackingProtection by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_tracking_protection_custom_tracking_content_select),
""
"all"
)
val blockCryptominersInCustomTrackingProtection by booleanPreference(

View File

@ -0,0 +1,377 @@
package org.mozilla.fenix.components
import io.mockk.every
import io.mockk.mockk
import mozilla.components.concept.engine.EngineSession
import mozilla.components.support.test.robolectric.testContext
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.R
import org.mozilla.fenix.TestApplication
import org.mozilla.fenix.utils.Settings
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(application = TestApplication::class)
class TrackingProtectionPolicyFactoryTest {
@Test
fun `WHEN useStrictMode is true then SHOULD return strict mode`() {
val expected = EngineSession.TrackingProtectionPolicy.strict()
val factory = TrackingProtectionPolicyFactory(mockSettings(useStrict = true))
val privateOnly = factory.createTrackingProtectionPolicy(normalMode = false, privateMode = true)
val normalOnly = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = false)
val always = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
val none = factory.createTrackingProtectionPolicy(normalMode = false, privateMode = false)
expected.assertPolicyEquals(privateOnly, checkPrivacy = false)
expected.assertPolicyEquals(normalOnly, checkPrivacy = false)
expected.assertPolicyEquals(always, checkPrivacy = false)
EngineSession.TrackingProtectionPolicy.none().assertPolicyEquals(none, checkPrivacy = false)
}
@Test
fun `WHEN neither use strict nor use custom is true SHOULD return recommended mode`() {
val expected = EngineSession.TrackingProtectionPolicy.recommended()
val factory = TrackingProtectionPolicyFactory(mockSettings(useStrict = false, useCustom = false))
val privateOnly = factory.createTrackingProtectionPolicy(normalMode = false, privateMode = true)
val normalOnly = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = false)
val always = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
val none = factory.createTrackingProtectionPolicy(normalMode = false, privateMode = false)
expected.assertPolicyEquals(privateOnly, checkPrivacy = false)
expected.assertPolicyEquals(normalOnly, checkPrivacy = false)
expected.assertPolicyEquals(always, checkPrivacy = false)
EngineSession.TrackingProtectionPolicy.none().assertPolicyEquals(none, checkPrivacy = false)
}
@Test
fun `GIVEN custom policy WHEN should not block cookies THEN tracking policy should not block cookies`() {
val expected = EngineSession.TrackingProtectionPolicy.select(
cookiePolicy = EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_ALL,
trackingCategories = allTrackingCategories
)
val factory = TrackingProtectionPolicyFactory(settingsForCustom(shouldBlockCookiesInCustom = false))
val privateOnly = factory.createTrackingProtectionPolicy(normalMode = false, privateMode = true)
val normalOnly = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = false)
val always = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
expected.assertPolicyEquals(privateOnly, checkPrivacy = false)
expected.assertPolicyEquals(normalOnly, checkPrivacy = false)
expected.assertPolicyEquals(always, checkPrivacy = false)
}
@Test
fun `GIVEN custom policy WHEN cookie policy block all THEN tracking policy should have cookie policy allow none`() {
val expected = EngineSession.TrackingProtectionPolicy.select(
cookiePolicy = EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_NONE,
trackingCategories = allTrackingCategories
)
val factory = TrackingProtectionPolicyFactory(settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "all"))
val privateOnly = factory.createTrackingProtectionPolicy(normalMode = false, privateMode = true)
val normalOnly = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = false)
val always = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
expected.assertPolicyEquals(privateOnly, checkPrivacy = false)
expected.assertPolicyEquals(normalOnly, checkPrivacy = false)
expected.assertPolicyEquals(always, checkPrivacy = false)
}
@Test
fun `GIVEN custom policy WHEN cookie policy social THEN tracking policy should have cookie policy allow non-trackers`() {
val expected = EngineSession.TrackingProtectionPolicy.select(
cookiePolicy = EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_NON_TRACKERS,
trackingCategories = allTrackingCategories
)
val factory = TrackingProtectionPolicyFactory(settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "social"))
val privateOnly = factory.createTrackingProtectionPolicy(normalMode = false, privateMode = true)
val normalOnly = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = false)
val always = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
expected.assertPolicyEquals(privateOnly, checkPrivacy = false)
expected.assertPolicyEquals(normalOnly, checkPrivacy = false)
expected.assertPolicyEquals(always, checkPrivacy = false)
}
@Test
fun `GIVEN custom policy WHEN cookie policy accept visited THEN tracking policy should have cookie policy allow visited`() {
val expected = EngineSession.TrackingProtectionPolicy.select(
cookiePolicy = EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_VISITED,
trackingCategories = allTrackingCategories
)
val factory = TrackingProtectionPolicyFactory(settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "unvisited"))
val privateOnly = factory.createTrackingProtectionPolicy(normalMode = false, privateMode = true)
val normalOnly = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = false)
val always = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
expected.assertPolicyEquals(privateOnly, checkPrivacy = false)
expected.assertPolicyEquals(normalOnly, checkPrivacy = false)
expected.assertPolicyEquals(always, checkPrivacy = false)
}
@Test
fun `GIVEN custom policy WHEN cookie policy block third party THEN tracking policy should have cookie policy allow first party`() {
val expected = EngineSession.TrackingProtectionPolicy.select(
cookiePolicy = EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_ONLY_FIRST_PARTY,
trackingCategories = allTrackingCategories
)
val factory = TrackingProtectionPolicyFactory(settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "third-party"))
val privateOnly = factory.createTrackingProtectionPolicy(normalMode = false, privateMode = true)
val normalOnly = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = false)
val always = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
expected.assertPolicyEquals(privateOnly, checkPrivacy = false)
expected.assertPolicyEquals(normalOnly, checkPrivacy = false)
expected.assertPolicyEquals(always, checkPrivacy = false)
}
@Test
fun `GIVEN custom policy WHEN cookie policy unrecognized THEN tracking policy should have cookie policy block all`() {
val expected = EngineSession.TrackingProtectionPolicy.select(
cookiePolicy = EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_NONE,
trackingCategories = allTrackingCategories
)
val factory = TrackingProtectionPolicyFactory(settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "some text!"))
val privateOnly = factory.createTrackingProtectionPolicy(normalMode = false, privateMode = true)
val normalOnly = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = false)
val always = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
expected.assertPolicyEquals(privateOnly, checkPrivacy = false)
expected.assertPolicyEquals(normalOnly, checkPrivacy = false)
expected.assertPolicyEquals(always, checkPrivacy = false)
}
@Test
fun `all cookies_options_entry_values values should create policies without crashing`() {
testContext.resources.getStringArray(R.array.cookies_options_entry_values).forEach {
TrackingProtectionPolicyFactory(settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = it))
.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
}
}
@Test
fun `factory should construct policies with privacy settings that match their inputs`() {
val allFactories = listOf(
TrackingProtectionPolicyFactory(mockSettings(useStrict = true)),
TrackingProtectionPolicyFactory(mockSettings(useStrict = false, useCustom = false))
)
allFactories.map {
it.createTrackingProtectionPolicy(normalMode = true, privateMode = false)
}.forEach {
assertTrue(it.useForRegularSessions)
assertFalse(it.useForPrivateSessions)
}
allFactories.map {
it.createTrackingProtectionPolicy(normalMode = false, privateMode = true)
}.forEach {
assertTrue(it.useForPrivateSessions)
assertFalse(it.useForRegularSessions)
}
allFactories.map {
it.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
}.forEach {
assertTrue(it.useForRegularSessions)
assertTrue(it.useForPrivateSessions)
}
// `normalMode = true, privateMode = true` can never be shown to the user
}
@Test
fun `custom tabs should respect their privacy rules`() {
val allSettings = listOf(
settingsForCustom(shouldBlockCookiesInCustom = false, blockTrackingContentInCustom = "all"),
settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "all", blockTrackingContentInCustom = "all"),
settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "all", blockTrackingContentInCustom = "all"),
settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "unvisited", blockTrackingContentInCustom = "all"),
settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "third-party", blockTrackingContentInCustom = "all"),
settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "some text!", blockTrackingContentInCustom = "all")
)
val privateSettings = listOf(
settingsForCustom(shouldBlockCookiesInCustom = false, blockTrackingContentInCustom = "private"),
settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "all", blockTrackingContentInCustom = "private"),
settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "all", blockTrackingContentInCustom = "private"),
settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "unvisited", blockTrackingContentInCustom = "private"),
settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "third-party", blockTrackingContentInCustom = "private"),
settingsForCustom(shouldBlockCookiesInCustom = true, blockCookiesSelection = "some text!", blockTrackingContentInCustom = "private")
)
allSettings.map { TrackingProtectionPolicyFactory(it).createTrackingProtectionPolicy(
normalMode = true,
privateMode = true
) }
.forEach {
assertTrue(it.useForRegularSessions)
assertTrue(it.useForPrivateSessions)
}
privateSettings.map { TrackingProtectionPolicyFactory(it).createTrackingProtectionPolicy(
normalMode = true,
privateMode = true
) }
.forEach {
assertFalse(it.useForRegularSessions)
assertTrue(it.useForPrivateSessions)
}
}
@Test
fun `GIVEN custom policy WHEN default tracking policies THEN tracking policies should match default`() {
val defaultTrackingCategories = arrayOf(
EngineSession.TrackingProtectionPolicy.TrackingCategory.AD,
EngineSession.TrackingProtectionPolicy.TrackingCategory.ANALYTICS,
EngineSession.TrackingProtectionPolicy.TrackingCategory.SOCIAL,
EngineSession.TrackingProtectionPolicy.TrackingCategory.MOZILLA_SOCIAL
)
val expected = EngineSession.TrackingProtectionPolicy.select(
cookiePolicy = EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_NONE,
trackingCategories = defaultTrackingCategories
)
val factory = TrackingProtectionPolicyFactory(
settingsForCustom(
shouldBlockCookiesInCustom = true,
blockTrackingContent = false,
blockFingerprinters = false,
blockCryptominers = false
)
)
val actual = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
expected.assertPolicyEquals(actual, checkPrivacy = false)
}
@Test
fun `GIVEN custom policy WHEN all tracking policies THEN tracking policies should match all`() {
val expected = EngineSession.TrackingProtectionPolicy.select(
cookiePolicy = EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_NONE,
trackingCategories = allTrackingCategories
)
val factory = TrackingProtectionPolicyFactory(
settingsForCustom(
shouldBlockCookiesInCustom = true,
blockTrackingContent = true,
blockFingerprinters = true,
blockCryptominers = true
)
)
val actual = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
expected.assertPolicyEquals(actual, checkPrivacy = false)
}
@Test
fun `GIVEN custom policy WHEN some tracking policies THEN tracking policies should match passed policies`() {
val someTrackingCategories = arrayOf(
EngineSession.TrackingProtectionPolicy.TrackingCategory.AD,
EngineSession.TrackingProtectionPolicy.TrackingCategory.ANALYTICS,
EngineSession.TrackingProtectionPolicy.TrackingCategory.SOCIAL,
EngineSession.TrackingProtectionPolicy.TrackingCategory.MOZILLA_SOCIAL,
EngineSession.TrackingProtectionPolicy.TrackingCategory.FINGERPRINTING
)
val expected = EngineSession.TrackingProtectionPolicy.select(
cookiePolicy = EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_NONE,
trackingCategories = someTrackingCategories
)
val factory = TrackingProtectionPolicyFactory(
settingsForCustom(
shouldBlockCookiesInCustom = true,
blockTrackingContent = false,
blockFingerprinters = true,
blockCryptominers = false
)
)
val actual = factory.createTrackingProtectionPolicy(normalMode = true, privateMode = true)
expected.assertPolicyEquals(actual, checkPrivacy = false)
}
}
private fun mockSettings(
useStrict: Boolean = false,
useCustom: Boolean = false
): Settings = mockk {
every { useStrictTrackingProtection } returns useStrict
every { useCustomTrackingProtection } returns useCustom
}
@Suppress("LongParameterList")
private fun settingsForCustom(
shouldBlockCookiesInCustom: Boolean,
blockTrackingContentInCustom: String = "all", // ["private", "all"]
blockCookiesSelection: String = "all", // values from R.array.cookies_options_entry_values
blockTrackingContent: Boolean = true,
blockFingerprinters: Boolean = true,
blockCryptominers: Boolean = true
): Settings = mockSettings(useStrict = false, useCustom = true).apply {
every { blockTrackingContentSelectionInCustomTrackingProtection } returns blockTrackingContentInCustom
every { blockCookiesInCustomTrackingProtection } returns shouldBlockCookiesInCustom
every { blockCookiesSelectionInCustomTrackingProtection } returns blockCookiesSelection
every { blockTrackingContentInCustomTrackingProtection } returns blockTrackingContent
every { blockFingerprintersInCustomTrackingProtection } returns blockFingerprinters
every { blockCryptominersInCustomTrackingProtection } returns blockCryptominers
}
private fun EngineSession.TrackingProtectionPolicy.assertPolicyEquals(
actual: EngineSession.TrackingProtectionPolicy,
checkPrivacy: Boolean
) {
assertEquals(this.cookiePolicy, actual.cookiePolicy)
// TODO Uncomment this assertion after the fix in AC#6079 lands
// assertEquals(this.strictSocialTrackingProtection, actual.strictSocialTrackingProtection)
// E.g., atm, RECOMMENDED == AD + ANALYTICS + SOCIAL + TEST + MOZILLA_SOCIAL + CRYPTOMINING.
// If all of these are set manually, the equality check should not fail
if (this.trackingCategories.toInt() != actual.trackingCategories.toInt()) {
assertArrayEquals(this.trackingCategories, actual.trackingCategories)
}
if (checkPrivacy) {
assertEquals(this.useForPrivateSessions, actual.useForPrivateSessions)
assertEquals(this.useForRegularSessions, actual.useForRegularSessions)
}
}
private fun Array<EngineSession.TrackingProtectionPolicy.TrackingCategory>.toInt(): Int {
return fold(initial = 0) { acc, next -> acc + next.id }
}
private val allTrackingCategories = arrayOf(
EngineSession.TrackingProtectionPolicy.TrackingCategory.AD,
EngineSession.TrackingProtectionPolicy.TrackingCategory.ANALYTICS,
EngineSession.TrackingProtectionPolicy.TrackingCategory.SOCIAL,
EngineSession.TrackingProtectionPolicy.TrackingCategory.MOZILLA_SOCIAL,
EngineSession.TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES,
EngineSession.TrackingProtectionPolicy.TrackingCategory.FINGERPRINTING,
EngineSession.TrackingProtectionPolicy.TrackingCategory.CRYPTOMINING
)