For #25764 - Prevent sponsored shortcut URLs from appearing as `frecent` shortcuts

pull/543/head
Alexandru2909 2 years ago committed by mergify[bot]
parent 2676ef9696
commit 4d430adbbe

@ -36,6 +36,7 @@ import mozilla.components.feature.addons.update.GlobalAddonDependencyProvider
import mozilla.components.feature.autofill.AutofillUseCases
import mozilla.components.feature.search.ext.buildSearchUrl
import mozilla.components.feature.search.ext.waitForSelectedOrDefaultSearchEngine
import mozilla.components.feature.top.sites.TopSitesFrecencyConfig
import mozilla.components.feature.top.sites.TopSitesProviderConfig
import mozilla.components.lib.crash.CrashReporter
import mozilla.components.service.fxa.manager.SyncEnginesStorage
@ -71,6 +72,7 @@ import org.mozilla.fenix.components.appstate.AppAction
import org.mozilla.fenix.components.metrics.MetricServiceType
import org.mozilla.fenix.components.metrics.MozillaProductDetector
import org.mozilla.fenix.components.toolbar.ToolbarPosition
import org.mozilla.fenix.ext.containsQueryParameters
import org.mozilla.fenix.ext.isCustomEngine
import org.mozilla.fenix.ext.isKnownSearchDomain
import org.mozilla.fenix.ext.settings
@ -262,7 +264,9 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
// we can prevent with this.
components.core.topSitesStorage.getTopSites(
totalSites = components.settings.topSitesMaxLimit,
frecencyConfig = FrecencyThresholdOption.SKIP_ONE_TIME_PAGES,
frecencyConfig = TopSitesFrecencyConfig(
FrecencyThresholdOption.SKIP_ONE_TIME_PAGES
) { !it.containsQueryParameters(components.settings.frecencyFilterQuery) },
providerConfig = TopSitesProviderConfig(
showProviderTopSites = components.settings.showContileFeature,
maxThreshold = TOP_SITES_PROVIDER_MAX_THRESHOLD

@ -4,6 +4,7 @@
package org.mozilla.fenix.ext
import android.net.Uri
import mozilla.components.feature.top.sites.TopSite
import org.mozilla.fenix.settings.SupportUtils
@ -35,3 +36,31 @@ fun List<TopSite>.sort(): List<TopSite> {
result
}
}
/**
* Returns true if the url contains any query parameters specified by the [searchParameters].
*
* @param searchParameters [String] of the following forms:
* - "" (empty) - Don't search for any params
* - "key" - Search param named "key" with any or no value
* - "key=" - Search param named "key" with no value
* - "key=value" - Search param named "key" with value "value"
*/
fun TopSite.containsQueryParameters(searchParameters: String): Boolean {
if (searchParameters.isBlank()) {
return false
}
val params = searchParameters.split("=")
val uri = Uri.parse(url)
return when (params.size) {
1 -> {
uri.queryParameterNames.contains(params.first()) &&
uri.getQueryParameter(params.first()).isNullOrBlank()
}
2 -> {
uri.queryParameterNames.contains(params.first()) &&
uri.getQueryParameter(params.first()) == params.last()
}
else -> false
}
}

@ -57,6 +57,7 @@ import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.feature.tab.collections.TabCollection
import mozilla.components.feature.top.sites.TopSitesConfig
import mozilla.components.feature.top.sites.TopSitesFeature
import mozilla.components.feature.top.sites.TopSitesFrecencyConfig
import mozilla.components.feature.top.sites.TopSitesProviderConfig
import mozilla.components.lib.state.ext.consumeFlow
import mozilla.components.lib.state.ext.consumeFrom
@ -82,6 +83,7 @@ import org.mozilla.fenix.components.toolbar.FenixTabCounterMenu
import org.mozilla.fenix.components.toolbar.ToolbarPosition
import org.mozilla.fenix.databinding.FragmentHomeBinding
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.containsQueryParameters
import org.mozilla.fenix.ext.hideToolbar
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.requireComponents
@ -412,7 +414,9 @@ class HomeFragment : Fragment() {
val settings = requireContext().settings()
return TopSitesConfig(
totalSites = settings.topSitesMaxLimit,
frecencyConfig = FrecencyThresholdOption.SKIP_ONE_TIME_PAGES,
frecencyConfig = TopSitesFrecencyConfig(
FrecencyThresholdOption.SKIP_ONE_TIME_PAGES
) { !it.containsQueryParameters(settings.frecencyFilterQuery) },
providerConfig = TopSitesProviderConfig(
showProviderTopSites = settings.showContileFeature,
maxThreshold = TOP_SITES_PROVIDER_MAX_THRESHOLD,

@ -1137,6 +1137,18 @@ class Settings(private val appContext: Context) : PreferencesHolder {
appContext.getPreferenceKey(R.string.pref_key_installed_addons_list),
default = ""
)
/**
* URLs from the user's history that contain this search param will be hidden
* from the top sites. The value is a string with one of the following forms:
* - "" (empty) - Disable this feature
* - "key" - Search param named "key" with any or no value
* - "key=" - Search param named "key" with no value
* - "key=value" - Search param named "key" with value "value"
*/
val frecencyFilterQuery by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_frecency_filter_query),
default = "mfadid=adm"
)
/**
* Storing number of enabled add-ons for telemetry purposes

@ -218,6 +218,8 @@
<string name="pref_key_enable_contile" translatable="false">pref_key_enable_contile</string>
<!-- Whether or not the Task Continuity enhancements are shown -->
<string name="pref_key_enable_task_continuity" translatable="false">pref_key_enable_task_continuity</string>
<!-- Query containing the search parameters to be hidden from the top frecent sites -->
<string name="pref_key_frecency_filter_query" translatable="false">pref_key_frecency_filter_query</string>
<!-- A value of `true` means the PWA dialog has been showed or user already has PWAs installed -->
<string name="pref_key_user_knows_about_pwa" translatable="false">pref_key_user_knows_about_pwa</string>

@ -6,6 +6,8 @@ package org.mozilla.fenix.ext
import mozilla.components.feature.top.sites.TopSite
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.helpers.FenixRobolectricTestRunner
@ -114,4 +116,43 @@ class TopSiteTest {
assertEquals(topSites.sort(), expected)
}
@Test
fun `WHEN containsQueryParameters is invoked THEN the result should be true only if the url contains the search parameters`() {
var searchParameters = ""
val querySite = TopSite.Frecent(
id = 1L,
title = "Search",
url = "test.com/?q=value",
createdAt = 0
)
val blankQuerySite = TopSite.Frecent(
id = 1L,
title = "BlankSearch",
url = "test.com/?q=",
createdAt = 0
)
assertFalse(defaultGoogleTopSite.containsQueryParameters(searchParameters))
assertFalse(querySite.containsQueryParameters(searchParameters))
assertFalse(blankQuerySite.containsQueryParameters(searchParameters))
searchParameters = "q"
assertFalse(defaultGoogleTopSite.containsQueryParameters(searchParameters))
assertFalse(querySite.containsQueryParameters(searchParameters))
assertTrue(blankQuerySite.containsQueryParameters(searchParameters))
searchParameters = "q="
assertFalse(defaultGoogleTopSite.containsQueryParameters(searchParameters))
assertFalse(querySite.containsQueryParameters(searchParameters))
assertTrue(blankQuerySite.containsQueryParameters(searchParameters))
searchParameters = "q=value"
assertFalse(defaultGoogleTopSite.containsQueryParameters(searchParameters))
assertTrue(querySite.containsQueryParameters(searchParameters))
assertFalse(blankQuerySite.containsQueryParameters(searchParameters))
}
}

Loading…
Cancel
Save