Loading components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/ext/TrackingProtectionPolicy.kt 0 → 100644 +53 −0 Original line number Diff line number Diff line /* 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 mozilla.components.browser.engine.gecko.ext import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.TrackingCategory import org.mozilla.geckoview.ContentBlocking import org.mozilla.geckoview.GeckoRuntimeSettings /** * Converts a [TrackingProtectionPolicy] into a GeckoView setting that can be used with [GeckoRuntimeSettings.Builder]. */ fun TrackingProtectionPolicy.toContentBlockingSetting( safeBrowsingPolicy: Array<EngineSession.SafeBrowsingPolicy> = arrayOf(EngineSession.SafeBrowsingPolicy.RECOMMENDED) ) = ContentBlocking.Settings.Builder().apply { enhancedTrackingProtectionLevel(getEtpLevel()) antiTracking(getAntiTrackingPolicy()) cookieBehavior(cookiePolicy.id) safeBrowsing(safeBrowsingPolicy.sumBy { it.id }) // This will be fixed on merge day when strictSocialTrackingProtection will be available on beta // strictSocialTrackingProtection(getStrictSocialTrackingProtection()) }.build() /** * Returns the [TrackingProtectionPolicy] categories as an Enhanced Tracking Protection level for GeckoView. */ internal fun TrackingProtectionPolicy.getEtpLevel(): Int { return when { trackingCategories.contains(TrackingCategory.NONE) -> ContentBlocking.EtpLevel.NONE else -> ContentBlocking.EtpLevel.STRICT } } /** * Returns the [TrackingProtectionPolicy] as a tracking policy for GeckoView. */ internal fun TrackingProtectionPolicy.getAntiTrackingPolicy(): Int { /** * The [TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES] is an * artificial category, created with the sole purpose of going around this bug * https://bugzilla.mozilla.org/show_bug.cgi?id=1579264, for this reason we have to * remove its value from the valid anti tracking categories, when is present. */ val total = trackingCategories.sumBy { it.id } return if (contains(TrackingCategory.SCRIPTS_AND_SUB_RESOURCES)) { total - TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id } else { total } } components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/ext/TrackingProtectionPolicyKtTest.kt 0 → 100644 +41 −0 Original line number Diff line number Diff line /* * 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 mozilla.components.browser.engine.gecko.ext import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy import org.junit.Assert.assertEquals import org.junit.Test import org.mozilla.geckoview.ContentBlocking.EtpLevel class TrackingProtectionPolicyKtTest { private val defaultSafeBrowsing = arrayOf(EngineSession.SafeBrowsingPolicy.RECOMMENDED) @Test fun `transform the policy to a GeckoView ContentBlockingSetting`() { val policy = TrackingProtectionPolicy.recommended() val setting = policy.toContentBlockingSetting() assertEquals(policy.getEtpLevel(), setting.enhancedTrackingProtectionLevel) assertEquals(policy.getAntiTrackingPolicy(), setting.antiTrackingCategories) assertEquals(policy.cookiePolicy.id, setting.cookieBehavior) assertEquals(defaultSafeBrowsing.sumBy { it.id }, setting.safeBrowsingCategories) // TODO Add this when we have it from GV; https://bugzilla.mozilla.org/show_bug.cgi?id=1651454 // assertEquals(policy.getStrictSocialTrackingProtection(), setting.strictSocialTrackingProtection) val policyWithSafeBrowsing = TrackingProtectionPolicy.recommended().toContentBlockingSetting(emptyArray()) assertEquals(0, policyWithSafeBrowsing.safeBrowsingCategories) } @Test fun `getEtpLevel is always Strict unless None`() { assertEquals(EtpLevel.STRICT, TrackingProtectionPolicy.recommended().getEtpLevel()) assertEquals(EtpLevel.STRICT, TrackingProtectionPolicy.strict().getEtpLevel()) assertEquals(EtpLevel.NONE, TrackingProtectionPolicy.none().getEtpLevel()) } } components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt +20 −30 Original line number Diff line number Diff line Loading @@ -7,6 +7,9 @@ package mozilla.components.browser.engine.gecko import android.content.Context import android.util.AttributeSet import androidx.annotation.VisibleForTesting import mozilla.components.browser.engine.gecko.ext.getAntiTrackingPolicy import mozilla.components.browser.engine.gecko.ext.getEtpLevel import mozilla.components.browser.engine.gecko.ext.getStrictSocialTrackingProtection import mozilla.components.browser.engine.gecko.integration.LocaleSettingUpdater import mozilla.components.browser.engine.gecko.mediaquery.from import mozilla.components.browser.engine.gecko.mediaquery.toGeckoValue Loading Loading @@ -519,39 +522,26 @@ class GeckoEngine( override var trackingProtectionPolicy: TrackingProtectionPolicy? = null set(value) { value?.let { policy -> val activateStrictSocialTracking = policy.strictSocialTrackingProtection ?: policy.trackingCategories.contains( TrackingCategory.STRICT ) val etpLevel = when { policy.trackingCategories.contains(TrackingCategory.NONE) -> ContentBlocking.EtpLevel.NONE else -> ContentBlocking.EtpLevel.STRICT } runtime.settings.contentBlocking.setEnhancedTrackingProtectionLevel(etpLevel) runtime.settings.contentBlocking.setStrictSocialTrackingProtection( activateStrictSocialTracking ) runtime.settings.contentBlocking.setAntiTracking(policy.getAntiTrackingPolicy()) runtime.settings.contentBlocking.setCookieBehavior(policy.cookiePolicy.id) defaultSettings?.trackingProtectionPolicy = value field = value with(runtime.settings.contentBlocking) { if (enhancedTrackingProtectionLevel != value.getEtpLevel()) { enhancedTrackingProtectionLevel = value.getEtpLevel() } if (strictSocialTrackingProtection != value.getStrictSocialTrackingProtection()) { strictSocialTrackingProtection = policy.getStrictSocialTrackingProtection() } private fun TrackingProtectionPolicy.getAntiTrackingPolicy(): Int { /** * The [TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES] is an * artificial category, created with the sole purpose of going around this bug * https://bugzilla.mozilla.org/show_bug.cgi?id=1579264, for this reason we have to * remove its value from the valid anti tracking categories, when is present. */ val total = trackingCategories.sumBy { it.id } return if (contains(TrackingCategory.SCRIPTS_AND_SUB_RESOURCES)) { total - TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id } else { total if (antiTrackingCategories != value.getAntiTrackingPolicy()) { setAntiTracking(policy.getAntiTrackingPolicy()) } if (cookieBehavior != value.cookiePolicy.id) { cookieBehavior = value.cookiePolicy.id } } defaultSettings?.trackingProtectionPolicy = value field = value } } Loading components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/ext/TrackingProtectionPolicy.kt 0 → 100644 +59 −0 Original line number Diff line number Diff line /* 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 mozilla.components.browser.engine.gecko.ext import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.TrackingCategory import org.mozilla.geckoview.ContentBlocking import org.mozilla.geckoview.GeckoRuntimeSettings /** * Converts a [TrackingProtectionPolicy] into a GeckoView setting that can be used with [GeckoRuntimeSettings.Builder]. */ fun TrackingProtectionPolicy.toContentBlockingSetting( safeBrowsingPolicy: Array<EngineSession.SafeBrowsingPolicy> = arrayOf(EngineSession.SafeBrowsingPolicy.RECOMMENDED) ) = ContentBlocking.Settings.Builder().apply { enhancedTrackingProtectionLevel(getEtpLevel()) antiTracking(getAntiTrackingPolicy()) cookieBehavior(cookiePolicy.id) safeBrowsing(safeBrowsingPolicy.sumBy { it.id }) strictSocialTrackingProtection(getStrictSocialTrackingProtection()) }.build() /** * Returns whether [TrackingCategory.STRICT] is enabled in the [TrackingProtectionPolicy]. */ internal fun TrackingProtectionPolicy.getStrictSocialTrackingProtection(): Boolean { return strictSocialTrackingProtection ?: trackingCategories.contains(TrackingCategory.STRICT) } /** * Returns the [TrackingProtectionPolicy] categories as an Enhanced Tracking Protection level for GeckoView. */ internal fun TrackingProtectionPolicy.getEtpLevel(): Int { return when { trackingCategories.contains(TrackingCategory.NONE) -> ContentBlocking.EtpLevel.NONE else -> ContentBlocking.EtpLevel.STRICT } } /** * Returns the [TrackingProtectionPolicy] as a tracking policy for GeckoView. */ internal fun TrackingProtectionPolicy.getAntiTrackingPolicy(): Int { /** * The [TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES] is an * artificial category, created with the sole purpose of going around this bug * https://bugzilla.mozilla.org/show_bug.cgi?id=1579264, for this reason we have to * remove its value from the valid anti tracking categories, when is present. */ val total = trackingCategories.sumBy { it.id } return if (contains(TrackingCategory.SCRIPTS_AND_SUB_RESOURCES)) { total - TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id } else { total } } components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt +98 −14 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ package mozilla.components.browser.engine.gecko import android.app.Activity import android.content.Context import androidx.test.ext.junit.runners.AndroidJUnit4 import mozilla.components.browser.engine.gecko.ext.getAntiTrackingPolicy import mozilla.components.browser.engine.gecko.mediaquery.toGeckoValue import mozilla.components.concept.engine.DefaultSettings import mozilla.components.concept.engine.Engine Loading Loading @@ -43,11 +44,13 @@ import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyFloat import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.spy import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mozilla.gecko.util.GeckoBundle import org.mozilla.geckoview.ContentBlocking import org.mozilla.geckoview.ContentBlocking.CookieBehavior import org.mozilla.geckoview.ContentBlockingController import org.mozilla.geckoview.ContentBlockingController.Event import org.mozilla.geckoview.GeckoResult Loading Loading @@ -252,7 +255,7 @@ class GeckoEngineTest { val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } val artificialCategory = TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id assertEquals( trackingStrictCategories - artificialCategory, contentBlockingSettings.antiTrackingCategories Loading Loading @@ -280,29 +283,30 @@ class GeckoEngineTest { @Test fun `the SCRIPTS_AND_SUB_RESOURCES tracking protection category must not be passed to gecko view`() { val mockRuntime = mock<GeckoRuntime>() val settings = spy(ContentBlocking.Settings.Builder().build()) whenever(mockRuntime.settings).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(settings) val geckoRunTime = GeckoRuntime.getDefault(testContext) val engine = GeckoEngine(testContext, runtime = geckoRunTime) val engine = GeckoEngine(testContext, runtime = mockRuntime) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } val artificialCategory = TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id val artificialCategory = TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id assertEquals( trackingStrictCategories - artificialCategory, geckoRunTime.settings.contentBlocking.antiTrackingCategories mockRuntime.settings.contentBlocking.antiTrackingCategories ) geckoRunTime.settings.contentBlocking.setAntiTracking(0) mockRuntime.settings.contentBlocking.setAntiTracking(0) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.select( arrayOf(TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES) arrayOf(TrackingCategory.SCRIPTS_AND_SUB_RESOURCES) ) assertEquals(0, geckoRunTime.settings.contentBlocking.antiTrackingCategories) assertEquals(0, mockRuntime.settings.contentBlocking.antiTrackingCategories) } @Test Loading Loading @@ -333,11 +337,63 @@ class GeckoEngineTest { ) } @Test fun `setAntiTracking is only invoked when the value is changed`() { val mockRuntime = mock<GeckoRuntime>() val settings = spy(ContentBlocking.Settings.Builder().build()) whenever(mockRuntime.settings).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(settings) val engine = GeckoEngine(testContext, runtime = mockRuntime) val policy = TrackingProtectionPolicy.recommended() engine.settings.trackingProtectionPolicy = policy verify(mockRuntime.settings.contentBlocking).setAntiTracking( policy.getAntiTrackingPolicy() ) reset(settings) engine.settings.trackingProtectionPolicy = policy verify(mockRuntime.settings.contentBlocking, never()).setAntiTracking( policy.getAntiTrackingPolicy() ) } @Test fun `setCookieBehavior is only invoked when the value is changed`() { val mockRuntime = mock<GeckoRuntime>() val settings = spy(ContentBlocking.Settings.Builder().build()) whenever(mockRuntime.settings).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(settings) whenever(mockRuntime.settings.contentBlocking.cookieBehavior).thenReturn(CookieBehavior.ACCEPT_NONE) val engine = GeckoEngine(testContext, runtime = mockRuntime) val policy = TrackingProtectionPolicy.recommended() engine.settings.trackingProtectionPolicy = policy verify(mockRuntime.settings.contentBlocking).setCookieBehavior( policy.cookiePolicy.id ) reset(settings) engine.settings.trackingProtectionPolicy = policy verify(mockRuntime.settings.contentBlocking, never()).setCookieBehavior( policy.cookiePolicy.id ) } @Test fun `setEnhancedTrackingProtectionLevel MUST always be set to STRICT unless the tracking protection policy is none`() { val mockRuntime = mock<GeckoRuntime>() val settings = spy(ContentBlocking.Settings.Builder().build()) whenever(mockRuntime.settings).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(settings) val engine = GeckoEngine(testContext, runtime = mockRuntime) Loading @@ -347,17 +403,43 @@ class GeckoEngineTest { ContentBlocking.EtpLevel.STRICT ) reset(settings) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.recommended() verify(mockRuntime.settings.contentBlocking, never()).setEnhancedTrackingProtectionLevel( ContentBlocking.EtpLevel.STRICT ) reset(settings) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() verify(mockRuntime.settings.contentBlocking, times(2)).setEnhancedTrackingProtectionLevel( verify(mockRuntime.settings.contentBlocking, never()).setEnhancedTrackingProtectionLevel( ContentBlocking.EtpLevel.STRICT ) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.none() reset(settings) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.none() verify(mockRuntime.settings.contentBlocking).setEnhancedTrackingProtectionLevel( ContentBlocking.EtpLevel.NONE ) reset(settings) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.none() verify(mockRuntime.settings.contentBlocking, never()).setEnhancedTrackingProtectionLevel( ContentBlocking.EtpLevel.NONE ) reset(settings) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() verify(mockRuntime.settings.contentBlocking).setEnhancedTrackingProtectionLevel( ContentBlocking.EtpLevel.STRICT ) } @Test Loading @@ -365,6 +447,7 @@ class GeckoEngineTest { val mockRuntime = mock<GeckoRuntime>() whenever(mockRuntime.settings).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking.strictSocialTrackingProtection).thenReturn(true) val engine = GeckoEngine(testContext, runtime = mockRuntime) Loading Loading @@ -393,6 +476,7 @@ class GeckoEngineTest { val mockRuntime = mock<GeckoRuntime>() whenever(mockRuntime.settings).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking.strictSocialTrackingProtection).thenReturn(true) val engine = GeckoEngine(testContext, runtime = mockRuntime) Loading Loading @@ -439,7 +523,7 @@ class GeckoEngineTest { val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } val artificialCategory = TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id assertEquals( trackingStrictCategories - artificialCategory, contentBlockingSettings.antiTrackingCategories Loading Loading
components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/ext/TrackingProtectionPolicy.kt 0 → 100644 +53 −0 Original line number Diff line number Diff line /* 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 mozilla.components.browser.engine.gecko.ext import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.TrackingCategory import org.mozilla.geckoview.ContentBlocking import org.mozilla.geckoview.GeckoRuntimeSettings /** * Converts a [TrackingProtectionPolicy] into a GeckoView setting that can be used with [GeckoRuntimeSettings.Builder]. */ fun TrackingProtectionPolicy.toContentBlockingSetting( safeBrowsingPolicy: Array<EngineSession.SafeBrowsingPolicy> = arrayOf(EngineSession.SafeBrowsingPolicy.RECOMMENDED) ) = ContentBlocking.Settings.Builder().apply { enhancedTrackingProtectionLevel(getEtpLevel()) antiTracking(getAntiTrackingPolicy()) cookieBehavior(cookiePolicy.id) safeBrowsing(safeBrowsingPolicy.sumBy { it.id }) // This will be fixed on merge day when strictSocialTrackingProtection will be available on beta // strictSocialTrackingProtection(getStrictSocialTrackingProtection()) }.build() /** * Returns the [TrackingProtectionPolicy] categories as an Enhanced Tracking Protection level for GeckoView. */ internal fun TrackingProtectionPolicy.getEtpLevel(): Int { return when { trackingCategories.contains(TrackingCategory.NONE) -> ContentBlocking.EtpLevel.NONE else -> ContentBlocking.EtpLevel.STRICT } } /** * Returns the [TrackingProtectionPolicy] as a tracking policy for GeckoView. */ internal fun TrackingProtectionPolicy.getAntiTrackingPolicy(): Int { /** * The [TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES] is an * artificial category, created with the sole purpose of going around this bug * https://bugzilla.mozilla.org/show_bug.cgi?id=1579264, for this reason we have to * remove its value from the valid anti tracking categories, when is present. */ val total = trackingCategories.sumBy { it.id } return if (contains(TrackingCategory.SCRIPTS_AND_SUB_RESOURCES)) { total - TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id } else { total } }
components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/ext/TrackingProtectionPolicyKtTest.kt 0 → 100644 +41 −0 Original line number Diff line number Diff line /* * 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 mozilla.components.browser.engine.gecko.ext import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy import org.junit.Assert.assertEquals import org.junit.Test import org.mozilla.geckoview.ContentBlocking.EtpLevel class TrackingProtectionPolicyKtTest { private val defaultSafeBrowsing = arrayOf(EngineSession.SafeBrowsingPolicy.RECOMMENDED) @Test fun `transform the policy to a GeckoView ContentBlockingSetting`() { val policy = TrackingProtectionPolicy.recommended() val setting = policy.toContentBlockingSetting() assertEquals(policy.getEtpLevel(), setting.enhancedTrackingProtectionLevel) assertEquals(policy.getAntiTrackingPolicy(), setting.antiTrackingCategories) assertEquals(policy.cookiePolicy.id, setting.cookieBehavior) assertEquals(defaultSafeBrowsing.sumBy { it.id }, setting.safeBrowsingCategories) // TODO Add this when we have it from GV; https://bugzilla.mozilla.org/show_bug.cgi?id=1651454 // assertEquals(policy.getStrictSocialTrackingProtection(), setting.strictSocialTrackingProtection) val policyWithSafeBrowsing = TrackingProtectionPolicy.recommended().toContentBlockingSetting(emptyArray()) assertEquals(0, policyWithSafeBrowsing.safeBrowsingCategories) } @Test fun `getEtpLevel is always Strict unless None`() { assertEquals(EtpLevel.STRICT, TrackingProtectionPolicy.recommended().getEtpLevel()) assertEquals(EtpLevel.STRICT, TrackingProtectionPolicy.strict().getEtpLevel()) assertEquals(EtpLevel.NONE, TrackingProtectionPolicy.none().getEtpLevel()) } }
components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt +20 −30 Original line number Diff line number Diff line Loading @@ -7,6 +7,9 @@ package mozilla.components.browser.engine.gecko import android.content.Context import android.util.AttributeSet import androidx.annotation.VisibleForTesting import mozilla.components.browser.engine.gecko.ext.getAntiTrackingPolicy import mozilla.components.browser.engine.gecko.ext.getEtpLevel import mozilla.components.browser.engine.gecko.ext.getStrictSocialTrackingProtection import mozilla.components.browser.engine.gecko.integration.LocaleSettingUpdater import mozilla.components.browser.engine.gecko.mediaquery.from import mozilla.components.browser.engine.gecko.mediaquery.toGeckoValue Loading Loading @@ -519,39 +522,26 @@ class GeckoEngine( override var trackingProtectionPolicy: TrackingProtectionPolicy? = null set(value) { value?.let { policy -> val activateStrictSocialTracking = policy.strictSocialTrackingProtection ?: policy.trackingCategories.contains( TrackingCategory.STRICT ) val etpLevel = when { policy.trackingCategories.contains(TrackingCategory.NONE) -> ContentBlocking.EtpLevel.NONE else -> ContentBlocking.EtpLevel.STRICT } runtime.settings.contentBlocking.setEnhancedTrackingProtectionLevel(etpLevel) runtime.settings.contentBlocking.setStrictSocialTrackingProtection( activateStrictSocialTracking ) runtime.settings.contentBlocking.setAntiTracking(policy.getAntiTrackingPolicy()) runtime.settings.contentBlocking.setCookieBehavior(policy.cookiePolicy.id) defaultSettings?.trackingProtectionPolicy = value field = value with(runtime.settings.contentBlocking) { if (enhancedTrackingProtectionLevel != value.getEtpLevel()) { enhancedTrackingProtectionLevel = value.getEtpLevel() } if (strictSocialTrackingProtection != value.getStrictSocialTrackingProtection()) { strictSocialTrackingProtection = policy.getStrictSocialTrackingProtection() } private fun TrackingProtectionPolicy.getAntiTrackingPolicy(): Int { /** * The [TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES] is an * artificial category, created with the sole purpose of going around this bug * https://bugzilla.mozilla.org/show_bug.cgi?id=1579264, for this reason we have to * remove its value from the valid anti tracking categories, when is present. */ val total = trackingCategories.sumBy { it.id } return if (contains(TrackingCategory.SCRIPTS_AND_SUB_RESOURCES)) { total - TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id } else { total if (antiTrackingCategories != value.getAntiTrackingPolicy()) { setAntiTracking(policy.getAntiTrackingPolicy()) } if (cookieBehavior != value.cookiePolicy.id) { cookieBehavior = value.cookiePolicy.id } } defaultSettings?.trackingProtectionPolicy = value field = value } } Loading
components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/ext/TrackingProtectionPolicy.kt 0 → 100644 +59 −0 Original line number Diff line number Diff line /* 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 mozilla.components.browser.engine.gecko.ext import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.TrackingCategory import org.mozilla.geckoview.ContentBlocking import org.mozilla.geckoview.GeckoRuntimeSettings /** * Converts a [TrackingProtectionPolicy] into a GeckoView setting that can be used with [GeckoRuntimeSettings.Builder]. */ fun TrackingProtectionPolicy.toContentBlockingSetting( safeBrowsingPolicy: Array<EngineSession.SafeBrowsingPolicy> = arrayOf(EngineSession.SafeBrowsingPolicy.RECOMMENDED) ) = ContentBlocking.Settings.Builder().apply { enhancedTrackingProtectionLevel(getEtpLevel()) antiTracking(getAntiTrackingPolicy()) cookieBehavior(cookiePolicy.id) safeBrowsing(safeBrowsingPolicy.sumBy { it.id }) strictSocialTrackingProtection(getStrictSocialTrackingProtection()) }.build() /** * Returns whether [TrackingCategory.STRICT] is enabled in the [TrackingProtectionPolicy]. */ internal fun TrackingProtectionPolicy.getStrictSocialTrackingProtection(): Boolean { return strictSocialTrackingProtection ?: trackingCategories.contains(TrackingCategory.STRICT) } /** * Returns the [TrackingProtectionPolicy] categories as an Enhanced Tracking Protection level for GeckoView. */ internal fun TrackingProtectionPolicy.getEtpLevel(): Int { return when { trackingCategories.contains(TrackingCategory.NONE) -> ContentBlocking.EtpLevel.NONE else -> ContentBlocking.EtpLevel.STRICT } } /** * Returns the [TrackingProtectionPolicy] as a tracking policy for GeckoView. */ internal fun TrackingProtectionPolicy.getAntiTrackingPolicy(): Int { /** * The [TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES] is an * artificial category, created with the sole purpose of going around this bug * https://bugzilla.mozilla.org/show_bug.cgi?id=1579264, for this reason we have to * remove its value from the valid anti tracking categories, when is present. */ val total = trackingCategories.sumBy { it.id } return if (contains(TrackingCategory.SCRIPTS_AND_SUB_RESOURCES)) { total - TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id } else { total } }
components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt +98 −14 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ package mozilla.components.browser.engine.gecko import android.app.Activity import android.content.Context import androidx.test.ext.junit.runners.AndroidJUnit4 import mozilla.components.browser.engine.gecko.ext.getAntiTrackingPolicy import mozilla.components.browser.engine.gecko.mediaquery.toGeckoValue import mozilla.components.concept.engine.DefaultSettings import mozilla.components.concept.engine.Engine Loading Loading @@ -43,11 +44,13 @@ import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyFloat import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.spy import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mozilla.gecko.util.GeckoBundle import org.mozilla.geckoview.ContentBlocking import org.mozilla.geckoview.ContentBlocking.CookieBehavior import org.mozilla.geckoview.ContentBlockingController import org.mozilla.geckoview.ContentBlockingController.Event import org.mozilla.geckoview.GeckoResult Loading Loading @@ -252,7 +255,7 @@ class GeckoEngineTest { val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } val artificialCategory = TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id assertEquals( trackingStrictCategories - artificialCategory, contentBlockingSettings.antiTrackingCategories Loading Loading @@ -280,29 +283,30 @@ class GeckoEngineTest { @Test fun `the SCRIPTS_AND_SUB_RESOURCES tracking protection category must not be passed to gecko view`() { val mockRuntime = mock<GeckoRuntime>() val settings = spy(ContentBlocking.Settings.Builder().build()) whenever(mockRuntime.settings).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(settings) val geckoRunTime = GeckoRuntime.getDefault(testContext) val engine = GeckoEngine(testContext, runtime = geckoRunTime) val engine = GeckoEngine(testContext, runtime = mockRuntime) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } val artificialCategory = TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id val artificialCategory = TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id assertEquals( trackingStrictCategories - artificialCategory, geckoRunTime.settings.contentBlocking.antiTrackingCategories mockRuntime.settings.contentBlocking.antiTrackingCategories ) geckoRunTime.settings.contentBlocking.setAntiTracking(0) mockRuntime.settings.contentBlocking.setAntiTracking(0) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.select( arrayOf(TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES) arrayOf(TrackingCategory.SCRIPTS_AND_SUB_RESOURCES) ) assertEquals(0, geckoRunTime.settings.contentBlocking.antiTrackingCategories) assertEquals(0, mockRuntime.settings.contentBlocking.antiTrackingCategories) } @Test Loading Loading @@ -333,11 +337,63 @@ class GeckoEngineTest { ) } @Test fun `setAntiTracking is only invoked when the value is changed`() { val mockRuntime = mock<GeckoRuntime>() val settings = spy(ContentBlocking.Settings.Builder().build()) whenever(mockRuntime.settings).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(settings) val engine = GeckoEngine(testContext, runtime = mockRuntime) val policy = TrackingProtectionPolicy.recommended() engine.settings.trackingProtectionPolicy = policy verify(mockRuntime.settings.contentBlocking).setAntiTracking( policy.getAntiTrackingPolicy() ) reset(settings) engine.settings.trackingProtectionPolicy = policy verify(mockRuntime.settings.contentBlocking, never()).setAntiTracking( policy.getAntiTrackingPolicy() ) } @Test fun `setCookieBehavior is only invoked when the value is changed`() { val mockRuntime = mock<GeckoRuntime>() val settings = spy(ContentBlocking.Settings.Builder().build()) whenever(mockRuntime.settings).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(settings) whenever(mockRuntime.settings.contentBlocking.cookieBehavior).thenReturn(CookieBehavior.ACCEPT_NONE) val engine = GeckoEngine(testContext, runtime = mockRuntime) val policy = TrackingProtectionPolicy.recommended() engine.settings.trackingProtectionPolicy = policy verify(mockRuntime.settings.contentBlocking).setCookieBehavior( policy.cookiePolicy.id ) reset(settings) engine.settings.trackingProtectionPolicy = policy verify(mockRuntime.settings.contentBlocking, never()).setCookieBehavior( policy.cookiePolicy.id ) } @Test fun `setEnhancedTrackingProtectionLevel MUST always be set to STRICT unless the tracking protection policy is none`() { val mockRuntime = mock<GeckoRuntime>() val settings = spy(ContentBlocking.Settings.Builder().build()) whenever(mockRuntime.settings).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(settings) val engine = GeckoEngine(testContext, runtime = mockRuntime) Loading @@ -347,17 +403,43 @@ class GeckoEngineTest { ContentBlocking.EtpLevel.STRICT ) reset(settings) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.recommended() verify(mockRuntime.settings.contentBlocking, never()).setEnhancedTrackingProtectionLevel( ContentBlocking.EtpLevel.STRICT ) reset(settings) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() verify(mockRuntime.settings.contentBlocking, times(2)).setEnhancedTrackingProtectionLevel( verify(mockRuntime.settings.contentBlocking, never()).setEnhancedTrackingProtectionLevel( ContentBlocking.EtpLevel.STRICT ) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.none() reset(settings) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.none() verify(mockRuntime.settings.contentBlocking).setEnhancedTrackingProtectionLevel( ContentBlocking.EtpLevel.NONE ) reset(settings) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.none() verify(mockRuntime.settings.contentBlocking, never()).setEnhancedTrackingProtectionLevel( ContentBlocking.EtpLevel.NONE ) reset(settings) engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() verify(mockRuntime.settings.contentBlocking).setEnhancedTrackingProtectionLevel( ContentBlocking.EtpLevel.STRICT ) } @Test Loading @@ -365,6 +447,7 @@ class GeckoEngineTest { val mockRuntime = mock<GeckoRuntime>() whenever(mockRuntime.settings).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking.strictSocialTrackingProtection).thenReturn(true) val engine = GeckoEngine(testContext, runtime = mockRuntime) Loading Loading @@ -393,6 +476,7 @@ class GeckoEngineTest { val mockRuntime = mock<GeckoRuntime>() whenever(mockRuntime.settings).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking).thenReturn(mock()) whenever(mockRuntime.settings.contentBlocking.strictSocialTrackingProtection).thenReturn(true) val engine = GeckoEngine(testContext, runtime = mockRuntime) Loading Loading @@ -439,7 +523,7 @@ class GeckoEngineTest { val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } val artificialCategory = TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id assertEquals( trackingStrictCategories - artificialCategory, contentBlockingSettings.antiTrackingCategories Loading