diff --git a/components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt b/components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt index a118920d4ba..fe4c20d8f72 100644 --- a/components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt +++ b/components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt @@ -176,13 +176,28 @@ class GeckoEngine( runtime.settings.contentBlocking.setStrictSocialTrackingProtection( activateStrictSocialTracking ) - runtime.settings.contentBlocking.setAntiTracking(policy.trackingCategories.sumBy { it.id }) - runtime.settings.contentBlocking.cookieBehavior = policy.cookiePolicy.id + runtime.settings.contentBlocking.setAntiTracking(policy.getAntiTrackingPolicy()) + runtime.settings.contentBlocking.setCookieBehavior(policy.cookiePolicy.id) defaultSettings?.trackingProtectionPolicy = value field = value } } + 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(TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES)) { + total - TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id + } else { + total + } + } + override var remoteDebuggingEnabled: Boolean get() = runtime.settings.remoteDebuggingEnabled set(value) { runtime.settings.remoteDebuggingEnabled = value } diff --git a/components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt b/components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt index c2ebe4dcf4d..98a976b9b30 100644 --- a/components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt +++ b/components/browser/engine-gecko-beta/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt @@ -172,7 +172,20 @@ class GeckoEngineSession( } else { policy.useForRegularSessions } - geckoSession.settings.useTrackingProtection = enabled + /** + * As described on https://bugzilla.mozilla.org/show_bug.cgi?id=1579264,useTrackingProtection + * is a misleading setting. When is set to true is blocking content (scripts/sub-resources). + * Instead of just turn on/off tracking protection. Until, this issue is fixed consumers need + * a way to indicate, if they want to block content or not, this is why we use + * [TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES]. + */ + val shouldBlockContent = + policy.contains(TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES) + + if (!enabled) { + disableTrackingProtectionOnGecko() + } + geckoSession.settings.useTrackingProtection = shouldBlockContent notifyObservers { onTrackerBlockingEnabledChange(enabled) } } @@ -180,10 +193,19 @@ class GeckoEngineSession( * See [EngineSession.disableTrackingProtection] */ override fun disableTrackingProtection() { - geckoSession.settings.useTrackingProtection = false + disableTrackingProtectionOnGecko() notifyObservers { onTrackerBlockingEnabledChange(false) } } + // To fully disable tracking protection we need to change the different tracking protection + // variables to none. + private fun disableTrackingProtectionOnGecko() { + geckoSession.settings.useTrackingProtection = false + runtime.settings.contentBlocking.setAntiTracking(ContentBlocking.AntiTracking.NONE) + runtime.settings.contentBlocking.cookieBehavior = ContentBlocking.CookieBehavior.ACCEPT_ALL + runtime.settings.contentBlocking.setStrictSocialTrackingProtection(false) + } + /** * See [EngineSession.settings] */ diff --git a/components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt b/components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt index 8bc2c1e2196..de48c222322 100644 --- a/components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt +++ b/components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt @@ -877,6 +877,7 @@ class GeckoEngineSessionTest { fun enableTrackingProtection() { val runtime = mock() whenever(runtime.settings).thenReturn(mock()) + whenever(runtime.settings.contentBlocking).thenReturn(mock()) val session = GeckoEngineSession(runtime, geckoSessionProvider = geckoSessionProvider) val privSession = GeckoEngineSession( runtime, @@ -912,6 +913,17 @@ class GeckoEngineSessionTest { session.enableTrackingProtection(privateOnlyPolicy) assertFalse(trackerBlockingObserved) + assertEquals( + GeckoCookieBehavior.ACCEPT_ALL, + runtime.settings.contentBlocking.cookieBehavior + ) + + assertEquals( + ContentBlocking.AntiTracking.NONE, + runtime.settings.contentBlocking.antiTrackingCategories + ) + + assertFalse(session.geckoSession.settings.useTrackingProtection) session.enableTrackingProtection(regularOnlyPolicy) assertTrue(trackerBlockingObserved) @@ -930,6 +942,8 @@ class GeckoEngineSessionTest { fun disableTrackingProtection() { val runtime = mock() whenever(runtime.settings).thenReturn(mock()) + whenever(runtime.settings.contentBlocking).thenReturn(mock()) + val engineSession = GeckoEngineSession(runtime, geckoSessionProvider = geckoSessionProvider) var trackerBlockingDisabledObserved = false @@ -941,6 +955,10 @@ class GeckoEngineSessionTest { engineSession.disableTrackingProtection() assertTrue(trackerBlockingDisabledObserved) + assertFalse(engineSession.geckoSession.settings.useTrackingProtection) + verify(runtime.settings.contentBlocking).setAntiTracking(ContentBlocking.AntiTracking.NONE) + verify(runtime.settings.contentBlocking).setCookieBehavior(GeckoCookieBehavior.ACCEPT_ALL) + verify(runtime.settings.contentBlocking).setStrictSocialTrackingProtection(false) } @Test @@ -963,18 +981,7 @@ class GeckoEngineSessionTest { assertEquals(GeckoAntiTracking.TEST, TrackingCategory.TEST.id) assertEquals(GeckoAntiTracking.CRYPTOMINING, TrackingCategory.CRYPTOMINING.id) assertEquals(GeckoAntiTracking.FINGERPRINTING, TrackingCategory.FINGERPRINTING.id) - assertEquals(GeckoAntiTracking.DEFAULT, TrackingCategory.RECOMMENDED.id) - assertEquals(GeckoAntiTracking.STRICT, TrackingCategory.STRICT.id) - - val recommendedPolicy = TrackingProtectionPolicy.recommended() - val strictPolicy = TrackingProtectionPolicy.strict() - var antiTrackingCategories = strictPolicy.trackingCategories.sumBy { it.id } - - assertEquals(GeckoAntiTracking.STRICT, antiTrackingCategories) - - antiTrackingCategories = recommendedPolicy.trackingCategories.sumBy { it.id } - - assertEquals(GeckoAntiTracking.DEFAULT, antiTrackingCategories) + assertEquals(GeckoAntiTracking.STP, TrackingCategory.MOZILLA_SOCIAL.id) assertEquals(GeckoCookieBehavior.ACCEPT_ALL, CookiePolicy.ACCEPT_ALL.id) assertEquals( @@ -1386,6 +1393,42 @@ class GeckoEngineSessionTest { verify(geckoSession.settings).useTrackingProtection = true } + @Test + fun `WHEN TrackingCategory do not includes content then useTrackingProtection must be set to false`() { + val runtime = mock() + whenever(runtime.settings).thenReturn(mock()) + + val defaultSettings = + DefaultSettings(trackingProtectionPolicy = TrackingProtectionPolicy.recommended()) + + GeckoEngineSession( + runtime, geckoSessionProvider = geckoSessionProvider, + privateMode = false, defaultSettings = defaultSettings + ) + + verify(geckoSession.settings).useTrackingProtection = false + } + + @Test + fun `WHEN disabling tracking protection THEN CookieBehavior and AntiTracking category must be set to ACCEPT_ALL and NONE`() { + val runtime = mock() + whenever(runtime.settings).thenReturn(mock()) + whenever(runtime.settings.contentBlocking).thenReturn(mock()) + + val defaultSettings = + DefaultSettings(trackingProtectionPolicy = TrackingProtectionPolicy.recommended()) + + val session = GeckoEngineSession( + runtime, geckoSessionProvider = geckoSessionProvider, + privateMode = false, defaultSettings = defaultSettings + ) + + session.disableTrackingProtection() + verify(geckoSession.settings, times(2)).useTrackingProtection = false + verify(runtime.settings.contentBlocking).setAntiTracking(ContentBlocking.AntiTracking.NONE) + verify(runtime.settings.contentBlocking).setCookieBehavior(ContentBlocking.CookieBehavior.ACCEPT_ALL) + } + @Test fun contentDelegate() { val engineSession = GeckoEngineSession(mock(), diff --git a/components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt b/components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt index 6aa5a55baa3..34370b5534a 100644 --- a/components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt +++ b/components/browser/engine-gecko-beta/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt @@ -139,7 +139,12 @@ class GeckoEngineTest { engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } - assertEquals(trackingStrictCategories, contentBlockingSettings.antiTrackingCategories) + val artificialCategory = + TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id + assertEquals( + trackingStrictCategories - artificialCategory, + contentBlockingSettings.antiTrackingCategories + ) val safeStrictBrowsingCategories = SafeBrowsingPolicy.RECOMMENDED.id assertEquals(safeStrictBrowsingCategories, contentBlockingSettings.safeBrowsingCategories) @@ -161,6 +166,33 @@ class GeckoEngineTest { } catch (e: UnsupportedSettingException) { } } + @Test + fun `the SCRIPTS_AND_SUB_RESOURCES tracking protection category must not be passed to gecko view`() { + + val geckoRunTime = GeckoRuntime.getDefault(testContext) + + val engine = GeckoEngine(testContext, runtime = geckoRunTime) + + engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() + + val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } + val artificialCategory = + TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id + + assertEquals( + trackingStrictCategories - artificialCategory, + geckoRunTime.settings.contentBlocking.antiTrackingCategories + ) + + geckoRunTime.settings.contentBlocking.setAntiTracking(0) + + engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.select( + arrayOf(TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES) + ) + + assertEquals(0, geckoRunTime.settings.contentBlocking.antiTrackingCategories) + } + @Test fun `WHEN a strict tracking protection policy is set THEN the strict social list must be activated`() { val mockRuntime = mock() @@ -253,7 +285,12 @@ class GeckoEngineTest { verify(runtimeSettings).autoplayDefault = GeckoRuntimeSettings.AUTOPLAY_DEFAULT_BLOCKED val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } - assertEquals(trackingStrictCategories, contentBlockingSettings.antiTrackingCategories) + val artificialCategory = + TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id + assertEquals( + trackingStrictCategories - artificialCategory, + contentBlockingSettings.antiTrackingCategories + ) assertEquals(SafeBrowsingPolicy.RECOMMENDED.id, contentBlockingSettings.safeBrowsingCategories) diff --git a/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt b/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt index a118920d4ba..fe4c20d8f72 100644 --- a/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt +++ b/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt @@ -176,13 +176,28 @@ class GeckoEngine( runtime.settings.contentBlocking.setStrictSocialTrackingProtection( activateStrictSocialTracking ) - runtime.settings.contentBlocking.setAntiTracking(policy.trackingCategories.sumBy { it.id }) - runtime.settings.contentBlocking.cookieBehavior = policy.cookiePolicy.id + runtime.settings.contentBlocking.setAntiTracking(policy.getAntiTrackingPolicy()) + runtime.settings.contentBlocking.setCookieBehavior(policy.cookiePolicy.id) defaultSettings?.trackingProtectionPolicy = value field = value } } + 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(TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES)) { + total - TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id + } else { + total + } + } + override var remoteDebuggingEnabled: Boolean get() = runtime.settings.remoteDebuggingEnabled set(value) { runtime.settings.remoteDebuggingEnabled = value } diff --git a/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt b/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt index 402f1fd2708..4d06cfb23e6 100644 --- a/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt +++ b/components/browser/engine-gecko-nightly/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt @@ -172,7 +172,20 @@ class GeckoEngineSession( } else { policy.useForRegularSessions } - geckoSession.settings.useTrackingProtection = enabled + /** + * As described on https://bugzilla.mozilla.org/show_bug.cgi?id=1579264,useTrackingProtection + * is a misleading setting. When is set to true is blocking content (scripts/sub-resources). + * Instead of just turn on/off tracking protection. Until, this issue is fixed consumers need + * a way to indicate, if they want to block content or not, this is why we use + * [TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES]. + */ + val shouldBlockContent = + policy.contains(TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES) + + geckoSession.settings.useTrackingProtection = shouldBlockContent + if (!enabled) { + disableTrackingProtectionOnGecko() + } notifyObservers { onTrackerBlockingEnabledChange(enabled) } } @@ -180,10 +193,19 @@ class GeckoEngineSession( * See [EngineSession.disableTrackingProtection] */ override fun disableTrackingProtection() { - geckoSession.settings.useTrackingProtection = false + disableTrackingProtectionOnGecko() notifyObservers { onTrackerBlockingEnabledChange(false) } } + // To fully disable tracking protection we need to change the different tracking protection + // variables to none. + private fun disableTrackingProtectionOnGecko() { + geckoSession.settings.useTrackingProtection = false + runtime.settings.contentBlocking.setAntiTracking(ContentBlocking.AntiTracking.NONE) + runtime.settings.contentBlocking.cookieBehavior = ContentBlocking.CookieBehavior.ACCEPT_ALL + runtime.settings.contentBlocking.setStrictSocialTrackingProtection(false) + } + /** * See [EngineSession.settings] */ diff --git a/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt b/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt index 8bc2c1e2196..6165a79589f 100644 --- a/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt +++ b/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt @@ -877,6 +877,7 @@ class GeckoEngineSessionTest { fun enableTrackingProtection() { val runtime = mock() whenever(runtime.settings).thenReturn(mock()) + whenever(runtime.settings.contentBlocking).thenReturn(mock()) val session = GeckoEngineSession(runtime, geckoSessionProvider = geckoSessionProvider) val privSession = GeckoEngineSession( runtime, @@ -912,6 +913,17 @@ class GeckoEngineSessionTest { session.enableTrackingProtection(privateOnlyPolicy) assertFalse(trackerBlockingObserved) + assertEquals( + GeckoCookieBehavior.ACCEPT_ALL, + runtime.settings.contentBlocking.cookieBehavior + ) + + assertEquals( + ContentBlocking.AntiTracking.NONE, + runtime.settings.contentBlocking.antiTrackingCategories + ) + + assertFalse(session.geckoSession.settings.useTrackingProtection) session.enableTrackingProtection(regularOnlyPolicy) assertTrue(trackerBlockingObserved) @@ -930,6 +942,8 @@ class GeckoEngineSessionTest { fun disableTrackingProtection() { val runtime = mock() whenever(runtime.settings).thenReturn(mock()) + whenever(runtime.settings.contentBlocking).thenReturn(mock()) + val engineSession = GeckoEngineSession(runtime, geckoSessionProvider = geckoSessionProvider) var trackerBlockingDisabledObserved = false @@ -941,6 +955,10 @@ class GeckoEngineSessionTest { engineSession.disableTrackingProtection() assertTrue(trackerBlockingDisabledObserved) + assertFalse(engineSession.geckoSession.settings.useTrackingProtection) + verify(runtime.settings.contentBlocking).setAntiTracking(ContentBlocking.AntiTracking.NONE) + verify(runtime.settings.contentBlocking).setCookieBehavior(GeckoCookieBehavior.ACCEPT_ALL) + verify(runtime.settings.contentBlocking).setStrictSocialTrackingProtection(false) } @Test @@ -963,18 +981,7 @@ class GeckoEngineSessionTest { assertEquals(GeckoAntiTracking.TEST, TrackingCategory.TEST.id) assertEquals(GeckoAntiTracking.CRYPTOMINING, TrackingCategory.CRYPTOMINING.id) assertEquals(GeckoAntiTracking.FINGERPRINTING, TrackingCategory.FINGERPRINTING.id) - assertEquals(GeckoAntiTracking.DEFAULT, TrackingCategory.RECOMMENDED.id) - assertEquals(GeckoAntiTracking.STRICT, TrackingCategory.STRICT.id) - - val recommendedPolicy = TrackingProtectionPolicy.recommended() - val strictPolicy = TrackingProtectionPolicy.strict() - var antiTrackingCategories = strictPolicy.trackingCategories.sumBy { it.id } - - assertEquals(GeckoAntiTracking.STRICT, antiTrackingCategories) - - antiTrackingCategories = recommendedPolicy.trackingCategories.sumBy { it.id } - - assertEquals(GeckoAntiTracking.DEFAULT, antiTrackingCategories) + assertEquals(GeckoAntiTracking.STP, TrackingCategory.MOZILLA_SOCIAL.id) assertEquals(GeckoCookieBehavior.ACCEPT_ALL, CookiePolicy.ACCEPT_ALL.id) assertEquals( @@ -1386,6 +1393,40 @@ class GeckoEngineSessionTest { verify(geckoSession.settings).useTrackingProtection = true } + @Test + fun `WHEN TrackingCategory do not includes content then useTrackingProtection must be set to false`() { + val runtime = mock() + whenever(runtime.settings).thenReturn(mock()) + + val defaultSettings = + DefaultSettings(trackingProtectionPolicy = TrackingProtectionPolicy.recommended()) + + GeckoEngineSession(runtime, geckoSessionProvider = geckoSessionProvider, + privateMode = false, defaultSettings = defaultSettings) + + verify(geckoSession.settings).useTrackingProtection = false + } + + @Test + fun `WHEN disabling tracking protection THEN CookieBehavior and AntiTracking category must be set to ACCEPT_ALL and NONE`() { + val runtime = mock() + whenever(runtime.settings).thenReturn(mock()) + whenever(runtime.settings.contentBlocking).thenReturn(mock()) + + val defaultSettings = + DefaultSettings(trackingProtectionPolicy = TrackingProtectionPolicy.recommended()) + + val session = GeckoEngineSession( + runtime, geckoSessionProvider = geckoSessionProvider, + privateMode = false, defaultSettings = defaultSettings + ) + + session.disableTrackingProtection() + verify(geckoSession.settings, times(2)).useTrackingProtection = false + verify(runtime.settings.contentBlocking).setAntiTracking(ContentBlocking.AntiTracking.NONE) + verify(runtime.settings.contentBlocking).setCookieBehavior(ContentBlocking.CookieBehavior.ACCEPT_ALL) + } + @Test fun contentDelegate() { val engineSession = GeckoEngineSession(mock(), diff --git a/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt b/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt index e4c7e8bd0d0..f176a79953d 100644 --- a/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt +++ b/components/browser/engine-gecko-nightly/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt @@ -139,7 +139,12 @@ class GeckoEngineTest { engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } - assertEquals(trackingStrictCategories, contentBlockingSettings.antiTrackingCategories) + val artificialCategory = + TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id + assertEquals( + trackingStrictCategories - artificialCategory, + contentBlockingSettings.antiTrackingCategories + ) val safeStrictBrowsingCategories = SafeBrowsingPolicy.RECOMMENDED.id assertEquals(safeStrictBrowsingCategories, contentBlockingSettings.safeBrowsingCategories) @@ -161,6 +166,33 @@ class GeckoEngineTest { } catch (e: UnsupportedSettingException) { } } + @Test + fun `the SCRIPTS_AND_SUB_RESOURCES tracking protection category must not be passed to gecko view`() { + + val geckoRunTime = GeckoRuntime.getDefault(testContext) + + val engine = GeckoEngine(testContext, runtime = geckoRunTime) + + engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() + + val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } + val artificialCategory = + TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id + + assertEquals( + trackingStrictCategories - artificialCategory, + geckoRunTime.settings.contentBlocking.antiTrackingCategories + ) + + geckoRunTime.settings.contentBlocking.setAntiTracking(0) + + engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.select( + arrayOf(TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES) + ) + + assertEquals(0, geckoRunTime.settings.contentBlocking.antiTrackingCategories) + } + @Test fun `WHEN a strict tracking protection policy is set THEN the strict social list must be activated`() { val mockRuntime = mock() @@ -253,7 +285,12 @@ class GeckoEngineTest { verify(runtimeSettings).autoplayDefault = GeckoRuntimeSettings.AUTOPLAY_DEFAULT_BLOCKED val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } - assertEquals(trackingStrictCategories, contentBlockingSettings.antiTrackingCategories) + val artificialCategory = + TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id + assertEquals( + trackingStrictCategories - artificialCategory, + contentBlockingSettings.antiTrackingCategories + ) assertEquals(SafeBrowsingPolicy.RECOMMENDED.id, contentBlockingSettings.safeBrowsingCategories) diff --git a/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt b/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt index 1542c0db5e3..4ccc3e49890 100644 --- a/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt +++ b/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt @@ -174,7 +174,7 @@ class GeckoEngine( set(value) { value?.let { policy -> - val trackingCategories = policy.trackingCategories.sumBy { it.id } + + val trackingCategories = policy.getAntiTrackingPolicy() + safeBrowsingPolicy.sumBy { it.id } runtime.settings.contentBlocking.categories = trackingCategories @@ -184,6 +184,22 @@ class GeckoEngine( } } + 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(TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES)) { + total - TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id + } else { + total + } + } + override var remoteDebuggingEnabled: Boolean get() = runtime.settings.remoteDebuggingEnabled set(value) { runtime.settings.remoteDebuggingEnabled = value } diff --git a/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt b/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt index 87e30497433..b4ada305cf5 100644 --- a/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt +++ b/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt @@ -907,16 +907,6 @@ class GeckoEngineSessionTest { assertEquals(TrackingCategory.CRYPTOMINING.id, ContentBlocking.AT_CRYPTOMINING) assertEquals(TrackingCategory.FINGERPRINTING.id, ContentBlocking.AT_FINGERPRINTING) - assertEquals( - TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id }, - ContentBlocking.AT_STRICT - ) - - assertEquals( - TrackingProtectionPolicy.recommended().trackingCategories.sumBy { it.id }, - ContentBlocking.AT_DEFAULT - ) - assertEquals(TrackingProtectionPolicy.CookiePolicy.ACCEPT_ALL.id, ContentBlocking.COOKIE_ACCEPT_ALL) assertEquals( TrackingProtectionPolicy.CookiePolicy.ACCEPT_NON_TRACKERS.id, diff --git a/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt b/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt index f9e2ee7a8f2..b1071a19816 100644 --- a/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt +++ b/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt @@ -19,6 +19,7 @@ import mozilla.components.support.test.any import mozilla.components.support.test.argumentCaptor import mozilla.components.support.test.eq import mozilla.components.support.test.mock +import mozilla.components.support.test.robolectric.testContext import mozilla.components.support.test.whenever import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -138,7 +139,15 @@ class GeckoEngineTest { engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } - assertEquals(trackingStrictCategories, ContentBlocking.AT_STRICT) + val artificialCategory = + TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id + + // This category isn't on stable yet we have to remove it + TrackingProtectionPolicy.TrackingCategory.MOZILLA_SOCIAL.id + + assertEquals( + (trackingStrictCategories - artificialCategory) + engine.settings.safeBrowsingPolicy.sumBy { it.id }, + contentBlockingSettings.categories + ) val safeStrictBrowsingCategories = SafeBrowsingPolicy.RECOMMENDED.id assertEquals(safeStrictBrowsingCategories, ContentBlocking.SB_ALL) @@ -158,6 +167,38 @@ class GeckoEngineTest { } catch (e: UnsupportedSettingException) { } } + @Test + fun `the SCRIPTS_AND_SUB_RESOURCES tracking protection category must not be passed to gecko view`() { + + val geckoRunTime = GeckoRuntime.getDefault(testContext) + + val engine = GeckoEngine(testContext, runtime = geckoRunTime) + + engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() + + val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } + val artificialCategory = + TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id + + // This category isn't on stable yet we have to remove it + TrackingProtectionPolicy.TrackingCategory.MOZILLA_SOCIAL.id + + assertEquals( + (trackingStrictCategories - artificialCategory) + engine.settings.safeBrowsingPolicy.sumBy { it.id }, + geckoRunTime.settings.contentBlocking.categories + ) + + geckoRunTime.settings.contentBlocking.categories = 0 + + engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.select( + arrayOf(TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES) + ) + + assertEquals( + engine.settings.safeBrowsingPolicy.sumBy { it.id }, + geckoRunTime.settings.contentBlocking.categories + ) + } + @Test fun defaultSettings() { val runtime = mock() @@ -193,8 +234,17 @@ class GeckoEngineTest { verify(runtimeSettings).remoteDebuggingEnabled = true verify(runtimeSettings).autoplayDefault = GeckoRuntimeSettings.AUTOPLAY_DEFAULT_BLOCKED + engine.settings.trackingProtectionPolicy = TrackingProtectionPolicy.strict() val trackingStrictCategories = TrackingProtectionPolicy.strict().trackingCategories.sumBy { it.id } - assertEquals(trackingStrictCategories, ContentBlocking.AT_STRICT) + val artificialCategory = + TrackingProtectionPolicy.TrackingCategory.SCRIPTS_AND_SUB_RESOURCES.id + + // This category isn't on stable yet we have to remove it + TrackingProtectionPolicy.TrackingCategory.MOZILLA_SOCIAL.id + + assertEquals( + (trackingStrictCategories - artificialCategory) + engine.settings.safeBrowsingPolicy.sumBy { it.id }, + contentBlockingSettings.categories + ) assertTrue(contentBlockingSettings.contains(SafeBrowsingPolicy.RECOMMENDED)) diff --git a/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineViewTest.kt b/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineViewTest.kt index ec70cf8ac52..37e11c482d1 100644 --- a/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineViewTest.kt +++ b/components/browser/engine-system/src/test/java/mozilla/components/browser/engine/system/SystemEngineViewTest.kt @@ -593,11 +593,6 @@ class SystemEngineViewTest { assertTrue(trackerBlocked!!.trackingCategories.first() == TrackingCategory.ANALYTICS) - whenever(blockedRequest.url).thenReturn(Uri.parse("http://contenttest1.com/")) - webViewClient.shouldInterceptRequest(engineSession.webView, blockedRequest) - - assertTrue(trackerBlocked!!.trackingCategories.first() == TrackingCategory.CONTENT) - whenever(blockedRequest.url).thenReturn(Uri.parse("http://www.socialtest1.com/")) webViewClient.shouldInterceptRequest(engineSession.webView, blockedRequest) @@ -1034,7 +1029,7 @@ class SystemEngineViewTest { UrlMatcher.ADVERTISING, UrlMatcher.ANALYTICS, UrlMatcher.SOCIAL ) val strictCategories = setOf( - UrlMatcher.ADVERTISING, UrlMatcher.ANALYTICS, UrlMatcher.SOCIAL, UrlMatcher.CONTENT + UrlMatcher.ADVERTISING, UrlMatcher.ANALYTICS, UrlMatcher.SOCIAL ) var urlMatcher = SystemEngineView.getOrCreateUrlMatcher(resources, recommendedPolicy) diff --git a/components/concept/engine/src/main/java/mozilla/components/concept/engine/EngineSession.kt b/components/concept/engine/src/main/java/mozilla/components/concept/engine/EngineSession.kt index 1fa0092ef44..642771aa417 100644 --- a/components/concept/engine/src/main/java/mozilla/components/concept/engine/EngineSession.kt +++ b/components/concept/engine/src/main/java/mozilla/components/concept/engine/EngineSession.kt @@ -176,22 +176,22 @@ abstract class EngineSession( NONE(0), /** - * Blocks advertisement trackers. + * Blocks advertisement trackers from the ads-track-digest256 list. */ AD(1 shl 1), /** - * Blocks analytics trackers. + * Blocks analytics trackers from the analytics-track-digest256 list. */ ANALYTICS(1 shl 2), /** - * Blocks social trackers. + * Blocks social trackers from the social-track-digest256 list. */ SOCIAL(1 shl 3), /** - * Blocks content trackers. + * Blocks content trackers from the content-track-digest256 list. * May cause issues with some web sites. */ CONTENT(1 shl 4), @@ -209,13 +209,23 @@ abstract class EngineSession( */ FINGERPRINTING(1 shl 7), - RECOMMENDED(AD.id + ANALYTICS.id + SOCIAL.id + TEST.id), + /** + * Blocks social trackers from the social-tracking-protection-digest256 list. + */ + MOZILLA_SOCIAL(1 shl 8), + + /** + * Blocks content like scripts and sub-resources. + */ + SCRIPTS_AND_SUB_RESOURCES(1 shl 9999), + + RECOMMENDED(AD.id + ANALYTICS.id + SOCIAL.id + TEST.id + MOZILLA_SOCIAL.id + + CRYPTOMINING.id + FINGERPRINTING.id), /** - * Combining the [RECOMMENDED] categories plus [CRYPTOMINING], - * [FINGERPRINTING] and [CONTENT]. + * Combining the [RECOMMENDED] categories plus [CRYPTOMINING] and [FINGERPRINTING]. */ - STRICT(RECOMMENDED.id + CRYPTOMINING.id + FINGERPRINTING.id + CONTENT.id) + STRICT(RECOMMENDED.id + SCRIPTS_AND_SUB_RESOURCES.id) } companion object { @@ -234,7 +244,8 @@ abstract class EngineSession( */ fun strict() = TrackingProtectionPolicyForSessionTypes( trackingCategory = arrayOf(TrackingCategory.STRICT), - cookiePolicy = ACCEPT_NON_TRACKERS + cookiePolicy = ACCEPT_NON_TRACKERS, + strictSocialTrackingProtection = true ) /** @@ -244,7 +255,8 @@ abstract class EngineSession( */ fun recommended() = TrackingProtectionPolicyForSessionTypes( trackingCategory = arrayOf(TrackingCategory.RECOMMENDED), - cookiePolicy = ACCEPT_NON_TRACKERS + cookiePolicy = ACCEPT_NON_TRACKERS, + strictSocialTrackingProtection = false ) fun select( @@ -276,6 +288,12 @@ abstract class EngineSession( /** * Subtype of [TrackingProtectionPolicy] to control the type of session this policy * should be applied to. By default, a policy will be applied to all sessions. + * @param trackingCategory a list of tracking categories to apply. + * @param cookiePolicy indicate how cookies should behave for this policy. + * @param strictSocialTrackingProtection indicate if content should be blocked from the + * social-tracking-protection-digest256 list, when given a null value, + * it is only applied when the [EngineSession.TrackingProtectionPolicy.TrackingCategory.STRICT] + * is set. */ class TrackingProtectionPolicyForSessionTypes internal constructor( trackingCategory: Array = arrayOf(TrackingCategory.RECOMMENDED), diff --git a/components/concept/engine/src/test/java/mozilla/components/concept/engine/EngineSessionTest.kt b/components/concept/engine/src/test/java/mozilla/components/concept/engine/EngineSessionTest.kt index a387ee44e1b..909e726e613 100644 --- a/components/concept/engine/src/test/java/mozilla/components/concept/engine/EngineSessionTest.kt +++ b/components/concept/engine/src/test/java/mozilla/components/concept/engine/EngineSessionTest.kt @@ -688,8 +688,8 @@ class EngineSessionTest { assertTrue(recommendedPolicy.contains(TrackingCategory.SOCIAL)) assertTrue(recommendedPolicy.contains(TrackingCategory.TEST)) - assertFalse(recommendedPolicy.contains(TrackingCategory.FINGERPRINTING)) - assertFalse(recommendedPolicy.contains(TrackingCategory.CRYPTOMINING)) + assertTrue(recommendedPolicy.contains(TrackingCategory.FINGERPRINTING)) + assertTrue(recommendedPolicy.contains(TrackingCategory.CRYPTOMINING)) assertFalse(recommendedPolicy.contains(TrackingCategory.CONTENT)) val strictPolicy = TrackingProtectionPolicy.strict() @@ -701,7 +701,7 @@ class EngineSessionTest { assertTrue(strictPolicy.contains(TrackingCategory.TEST)) assertTrue(strictPolicy.contains(TrackingCategory.FINGERPRINTING)) assertTrue(strictPolicy.contains(TrackingCategory.CRYPTOMINING)) - assertTrue(strictPolicy.contains(TrackingCategory.CONTENT)) + assertFalse(strictPolicy.contains(TrackingCategory.CONTENT)) } } diff --git a/docs/changelog.md b/docs/changelog.md index 7eb3dc30160..a4655af5d37 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -12,6 +12,9 @@ permalink: /changelog/ * [Gecko](https://github.com/mozilla-mobile/android-components/blob/master/buildSrc/src/main/java/Gecko.kt) * [Configuration](https://github.com/mozilla-mobile/android-components/blob/master/buildSrc/src/main/java/Config.kt) +* **browser-engine-gecko-nightly**, **browser-engine-gecko-beta** and **browser-engine-gecko** + * The `TrackingProtectionPolicy.recommended()` and `TrackingProtectionPolicy.strict()` policies are now aligned with standard and strict (respectively) policies on FireFox desktop, for more details see the [issue #4349](https://github.com/mozilla-mobile/android-components/issues/4349). + * **browser-engine-gecko-nightly** and **browser-engine-gecko-beta** * The `TrackingProtectionPolicy.select` function now allows you to indicate if `strictSocialTrackingProtection` should be activated or not. When it is active blocks trackers from the social-tracking-protection-digest256 list, for more details take a look at the [issue #4320](https://github.com/mozilla-mobile/android-components/issues/4320) ```kotlin