Bug 1959107 - Fix intermittent coroutines memory leak related to top sites on home r=android-reviewers,pollymce
# Conflicts: # mobile/android/fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt Differential Revision: https://phabricator.services.mozilla.com/D246359
This commit is contained in:
@@ -17,4 +17,9 @@ interface TopSitesProvider {
|
||||
* @return a list of top sites from the provider.
|
||||
*/
|
||||
suspend fun getTopSites(allowCache: Boolean = true): List<TopSite>
|
||||
|
||||
/**
|
||||
* Refreshes the cache with the latest top sites response if the cache is expired.
|
||||
*/
|
||||
suspend fun refreshTopSitesIfCacheExpired()
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ class MarsTopSitesProvider(
|
||||
* Refreshes the cache with the latest tiles response from [endPointURL] if the cache
|
||||
* is expired.
|
||||
*/
|
||||
suspend fun refreshTopSitesIfCacheExpired() {
|
||||
override suspend fun refreshTopSitesIfCacheExpired() {
|
||||
if (!isCacheExpired()) return
|
||||
|
||||
getTopSites(allowCache = false)
|
||||
|
||||
@@ -92,7 +92,7 @@ class ContileTopSitesProvider(
|
||||
* Refreshes the cache with the latest top sites response from [endPointURL]
|
||||
* if the cache is expired.
|
||||
*/
|
||||
suspend fun refreshTopSitesIfCacheExpired() {
|
||||
override suspend fun refreshTopSitesIfCacheExpired() {
|
||||
if (!isCacheExpired(shouldUseServerMaxAge = false)) return
|
||||
|
||||
getTopSites(allowCache = false)
|
||||
|
||||
@@ -12,7 +12,6 @@ import androidx.test.espresso.intent.rule.IntentsRule
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.customannotations.SkipLeaks
|
||||
import org.mozilla.fenix.customannotations.SmokeTest
|
||||
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens
|
||||
import org.mozilla.fenix.helpers.AppAndSystemHelper.deleteDownloadedFileOnStorage
|
||||
@@ -293,7 +292,6 @@ class DownloadTest : TestSetup() {
|
||||
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/1632384
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun warningWhenClosingPrivateTabsWhileDownloadingTest() {
|
||||
homeScreen {
|
||||
}.togglePrivateBrowsingMode()
|
||||
|
||||
@@ -7,7 +7,6 @@ package org.mozilla.fenix.ui
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.customannotations.SkipLeaks
|
||||
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
|
||||
import org.mozilla.fenix.helpers.TestAssetHelper.TestAsset
|
||||
import org.mozilla.fenix.helpers.TestAssetHelper.getGPCTestAsset
|
||||
@@ -58,7 +57,6 @@ class GlobalPrivacyControlTest : TestSetup() {
|
||||
}
|
||||
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2429364
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
@Test
|
||||
fun testGPCinPrivateBrowsing() {
|
||||
homeScreen { }.togglePrivateBrowsingMode()
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.IntentReceiverActivity
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.customannotations.SkipLeaks
|
||||
import org.mozilla.fenix.customannotations.SmokeTest
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens
|
||||
@@ -122,7 +121,6 @@ class MainMenuTestCompose : TestSetup() {
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2860843
|
||||
@SmokeTest
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun verifyTheNewPrivateTabButtonTest() {
|
||||
val testPage = getGenericAsset(mockWebServer, 1)
|
||||
|
||||
|
||||
@@ -158,7 +158,6 @@ class NavigationToolbarTest : TestSetup() {
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2256552
|
||||
@SmokeTest
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun goToHomeScreenInPrivateModeTest() {
|
||||
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ package org.mozilla.fenix.ui
|
||||
import androidx.core.net.toUri
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.customannotations.SkipLeaks
|
||||
import org.mozilla.fenix.customannotations.SmokeTest
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.helpers.AppAndSystemHelper.assertYoutubeAppOpens
|
||||
@@ -93,7 +92,6 @@ class SettingsAdvancedTest : TestSetup() {
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2121052
|
||||
// Assumes Youtube is installed and enabled
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun privateBrowsingAskBeforeOpeningOpenLinkInAppTest() {
|
||||
val externalLinksPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
|
||||
|
||||
@@ -183,7 +181,6 @@ class SettingsAdvancedTest : TestSetup() {
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2121051
|
||||
// Assumes Youtube is installed and enabled
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun privateBrowsingAskBeforeOpeningLinkInAppCancelTest() {
|
||||
TestHelper.appContext.settings().shouldShowCookieBannersCFR = false
|
||||
val externalLinksPage = TestAssetHelper.getExternalLinksAsset(mockWebServer)
|
||||
|
||||
@@ -10,7 +10,6 @@ import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.FenixApplication
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.customannotations.SkipLeaks
|
||||
import org.mozilla.fenix.customannotations.SmokeTest
|
||||
import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources
|
||||
import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithSystemLocaleChanged
|
||||
@@ -143,7 +142,6 @@ class SettingsGeneralTest : TestSetup() {
|
||||
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/516078
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun verifyFollowDeviceLanguageTest() {
|
||||
val frenchLocale = LocaleListCompat.forLanguageTags("fr")
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ package org.mozilla.fenix.ui
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.customannotations.SkipLeaks
|
||||
import org.mozilla.fenix.customannotations.SmokeTest
|
||||
import org.mozilla.fenix.helpers.AppAndSystemHelper.openAppFromExternalLink
|
||||
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
|
||||
@@ -178,7 +177,6 @@ class SettingsHomepageTest : TestSetup() {
|
||||
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/1569843
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun verifyOpeningScreenAfterLaunchingExternalLinkTest() {
|
||||
val genericPage = getGenericAsset(mockWebServer, 1)
|
||||
|
||||
|
||||
@@ -508,7 +508,6 @@ class SettingsSearchTest : TestSetup() {
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/464420
|
||||
// Tests the "Don't allow" option from private mode search suggestions onboarding dialog
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun doNotAllowSearchSuggestionsInPrivateBrowsingTest() {
|
||||
homeScreen {
|
||||
togglePrivateBrowsingModeOnOff()
|
||||
@@ -523,7 +522,6 @@ class SettingsSearchTest : TestSetup() {
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/1957063
|
||||
// Tests the "Allow" option from private mode search suggestions onboarding dialog
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun allowSearchSuggestionsInPrivateBrowsingTest() {
|
||||
homeScreen {
|
||||
togglePrivateBrowsingModeOnOff()
|
||||
|
||||
@@ -6,7 +6,6 @@ package org.mozilla.fenix.ui
|
||||
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.customannotations.SkipLeaks
|
||||
import org.mozilla.fenix.customannotations.SmokeTest
|
||||
import org.mozilla.fenix.helpers.Constants.defaultTopSitesList
|
||||
import org.mozilla.fenix.helpers.DataGenerationHelper.getSponsoredShortcutTitle
|
||||
@@ -62,7 +61,6 @@ class SponsoredShortcutsTest : TestSetup() {
|
||||
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/1729334
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun openSponsoredShortcutInPrivateTabTest() {
|
||||
homeScreen {
|
||||
sponsoredShortcutTitle = getSponsoredShortcutTitle(2)
|
||||
|
||||
@@ -141,7 +141,6 @@ class TabbedBrowsingTest : TestSetup() {
|
||||
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/903591
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun closingPrivateTabsTest() {
|
||||
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@@ -182,7 +181,6 @@ class TabbedBrowsingTest : TestSetup() {
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/903592
|
||||
@SmokeTest
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun verifyCloseAllPrivateTabsNotificationTest() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@@ -336,7 +334,12 @@ class TabbedBrowsingTest : TestSetup() {
|
||||
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2343663
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
@SkipLeaks(
|
||||
reasons = [
|
||||
"https://bugzilla.mozilla.org/show_bug.cgi?id=1962065",
|
||||
"https://bugzilla.mozilla.org/show_bug.cgi?id=1962070",
|
||||
],
|
||||
)
|
||||
fun tabsCounterShortcutMenuNewPrivateTabTest() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@@ -353,7 +356,7 @@ class TabbedBrowsingTest : TestSetup() {
|
||||
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2343662
|
||||
@Test
|
||||
@SkipLeaks
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1962065"])
|
||||
fun tabsCounterShortcutMenuNewTabTest() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@@ -370,7 +373,7 @@ class TabbedBrowsingTest : TestSetup() {
|
||||
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/927315
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1962065"])
|
||||
fun privateTabsCounterShortcutMenuCloseTabTest() {
|
||||
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
|
||||
@@ -402,7 +405,7 @@ class TabbedBrowsingTest : TestSetup() {
|
||||
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2344199
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1962065"])
|
||||
fun privateTabsCounterShortcutMenuNewPrivateTabTest() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@@ -422,7 +425,7 @@ class TabbedBrowsingTest : TestSetup() {
|
||||
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2344198
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1962065"])
|
||||
fun privateTabsCounterShortcutMenuNewTabTest() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import androidx.compose.ui.test.junit4.AndroidComposeTestRule
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.customannotations.SkipLeaks
|
||||
import org.mozilla.fenix.customannotations.SmokeTest
|
||||
import org.mozilla.fenix.helpers.DataGenerationHelper.generateRandomString
|
||||
import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource
|
||||
@@ -188,7 +187,6 @@ class TopSitesTestCompose : TestSetup() {
|
||||
|
||||
// TestRail link: https://mozilla.testrail.io/index.php?/cases/view/2323641
|
||||
@Test
|
||||
@SkipLeaks(reasons = ["https://bugzilla.mozilla.org/show_bug.cgi?id=1959107"])
|
||||
fun removeTopSiteFromMainMenuTest() {
|
||||
val defaultWebPage = getGenericAsset(mockWebServer, 1)
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@ import org.mozilla.fenix.ext.containsQueryParameters
|
||||
import org.mozilla.fenix.ext.isCustomEngine
|
||||
import org.mozilla.fenix.ext.isKnownSearchDomain
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.TOP_SITES_PROVIDER_LIMIT
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.TOP_SITES_PROVIDER_MAX_THRESHOLD
|
||||
import org.mozilla.fenix.lifecycle.StoreLifecycleObserver
|
||||
import org.mozilla.fenix.lifecycle.VisibilityLifecycleObserver
|
||||
import org.mozilla.fenix.nimbus.FxNimbus
|
||||
@@ -111,8 +113,6 @@ import org.mozilla.fenix.push.WebPushEngineIntegration
|
||||
import org.mozilla.fenix.session.PerformanceActivityLifecycleCallbacks
|
||||
import org.mozilla.fenix.session.VisibilityLifecycleCallback
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_LIMIT
|
||||
import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_MAX_THRESHOLD
|
||||
import org.mozilla.fenix.utils.isLargeScreenSize
|
||||
import org.mozilla.fenix.wallpapers.Wallpaper
|
||||
import java.util.UUID
|
||||
|
||||
@@ -69,7 +69,6 @@ import mozilla.components.service.pocket.PocketStoriesService
|
||||
import mozilla.components.support.base.feature.ActivityResultHandler
|
||||
import mozilla.components.support.base.feature.UserInteractionHandler
|
||||
import mozilla.components.support.base.feature.UserInteractionOnBackPressedCallback
|
||||
import mozilla.components.support.base.log.logger.Logger
|
||||
import mozilla.components.support.ktx.android.arch.lifecycle.addObservers
|
||||
import mozilla.components.support.ktx.android.content.call
|
||||
import mozilla.components.support.ktx.android.content.email
|
||||
@@ -123,6 +122,7 @@ import org.mozilla.fenix.ext.setNavigationIcon
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.extension.WebExtensionPromptFeature
|
||||
import org.mozilla.fenix.home.HomeFragment
|
||||
import org.mozilla.fenix.home.TopSitesRefresher
|
||||
import org.mozilla.fenix.home.intent.AssistIntentProcessor
|
||||
import org.mozilla.fenix.home.intent.CrashReporterIntentProcessor
|
||||
import org.mozilla.fenix.home.intent.HomeDeepLinkIntentProcessor
|
||||
@@ -495,6 +495,14 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
||||
extensionsProcessDisabledBackgroundController,
|
||||
serviceWorkerSupport,
|
||||
crashReporterBinding,
|
||||
TopSitesRefresher(
|
||||
settings = settings(),
|
||||
topSitesProvider = if (settings().marsAPIEnabled) {
|
||||
components.core.marsTopSitesProvider
|
||||
} else {
|
||||
components.core.contileTopSitesProvider
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
if (!isCustomTabIntent(intent)) {
|
||||
@@ -644,7 +652,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
@@ -655,18 +662,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
||||
)
|
||||
|
||||
lifecycleScope.launch(IO) {
|
||||
try {
|
||||
if (settings().showContileFeature) {
|
||||
if (settings().marsAPIEnabled) {
|
||||
components.core.marsTopSitesProvider.refreshTopSitesIfCacheExpired()
|
||||
} else {
|
||||
components.core.contileTopSitesProvider.refreshTopSitesIfCacheExpired()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Logger.error("Failed to refresh contile top sites", e)
|
||||
}
|
||||
|
||||
if (settings().checkIfFenixIsDefaultBrowserOnAppResume()) {
|
||||
if (components.appStore.state.wasNativeDefaultBrowserPromptShown) {
|
||||
Metrics.defaultBrowserChangedViaNativeSystemPrompt.record(NoExtras())
|
||||
|
||||
@@ -29,7 +29,6 @@ import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.content.ContextCompat.getColor
|
||||
import androidx.core.graphics.drawable.toDrawable
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
@@ -65,17 +64,13 @@ import mozilla.components.compose.base.Divider
|
||||
import mozilla.components.compose.cfr.CFRPopup
|
||||
import mozilla.components.compose.cfr.CFRPopupLayout
|
||||
import mozilla.components.compose.cfr.CFRPopupProperties
|
||||
import mozilla.components.concept.storage.FrecencyThresholdOption
|
||||
import mozilla.components.concept.sync.AccountObserver
|
||||
import mozilla.components.concept.sync.AuthType
|
||||
import mozilla.components.concept.sync.OAuthAccount
|
||||
import mozilla.components.feature.accounts.push.SendTabUseCases
|
||||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
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
|
||||
import mozilla.components.lib.state.ext.observeAsState
|
||||
@@ -113,7 +108,6 @@ import org.mozilla.fenix.compose.snackbar.Snackbar
|
||||
import org.mozilla.fenix.compose.snackbar.SnackbarState
|
||||
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.isToolbarAtBottom
|
||||
import org.mozilla.fenix.ext.nav
|
||||
@@ -147,6 +141,10 @@ import org.mozilla.fenix.home.toolbar.HomeToolbarView
|
||||
import org.mozilla.fenix.home.toolbar.SearchSelectorBinding
|
||||
import org.mozilla.fenix.home.toolbar.SearchSelectorMenuBinding
|
||||
import org.mozilla.fenix.home.topsites.DefaultTopSitesView
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.AMAZON_SEARCH_ENGINE_NAME
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.AMAZON_SPONSORED_TITLE
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.EBAY_SPONSORED_TITLE
|
||||
import org.mozilla.fenix.home.topsites.getTopSitesConfig
|
||||
import org.mozilla.fenix.home.ui.Homepage
|
||||
import org.mozilla.fenix.messaging.DefaultMessageController
|
||||
import org.mozilla.fenix.messaging.FenixMessageSurfaceId
|
||||
@@ -166,8 +164,6 @@ import org.mozilla.fenix.snackbar.SnackbarBinding
|
||||
import org.mozilla.fenix.tabstray.Page
|
||||
import org.mozilla.fenix.tabstray.TabsTrayAccessPoint
|
||||
import org.mozilla.fenix.theme.FirefoxTheme
|
||||
import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_LIMIT
|
||||
import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_MAX_THRESHOLD
|
||||
import org.mozilla.fenix.utils.allowUndo
|
||||
import org.mozilla.fenix.wallpapers.Wallpaper
|
||||
import java.lang.ref.WeakReference
|
||||
@@ -384,7 +380,10 @@ class HomeFragment : Fragment() {
|
||||
settings = components.settings,
|
||||
),
|
||||
storage = components.core.topSitesStorage,
|
||||
config = ::getTopSitesConfig,
|
||||
config = getTopSitesConfig(
|
||||
settings = requireContext().settings(),
|
||||
store = store,
|
||||
),
|
||||
),
|
||||
owner = viewLifecycleOwner,
|
||||
view = binding.root,
|
||||
@@ -1063,37 +1062,6 @@ class HomeFragment : Fragment() {
|
||||
private fun shouldShowMicrosurveyPrompt(context: Context) =
|
||||
context.components.settings.shouldShowMicrosurveyPrompt
|
||||
|
||||
/**
|
||||
* Returns a [TopSitesConfig] which specifies how many top sites to display and whether or
|
||||
* not frequently visited sites should be displayed.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
internal fun getTopSitesConfig(): TopSitesConfig {
|
||||
val settings = requireContext().settings()
|
||||
return TopSitesConfig(
|
||||
totalSites = settings.topSitesMaxLimit,
|
||||
frecencyConfig = if (FxNimbus.features.homepageHideFrecentTopSites.value().enabled) {
|
||||
null
|
||||
} else {
|
||||
TopSitesFrecencyConfig(
|
||||
frecencyTresholdOption = FrecencyThresholdOption.SKIP_ONE_TIME_PAGES,
|
||||
) { !it.url.toUri().containsQueryParameters(settings.frecencyFilterQuery) }
|
||||
},
|
||||
providerConfig = TopSitesProviderConfig(
|
||||
showProviderTopSites = settings.showContileFeature,
|
||||
limit = TOP_SITES_PROVIDER_LIMIT,
|
||||
maxThreshold = TOP_SITES_PROVIDER_MAX_THRESHOLD,
|
||||
providerFilter = { topSite ->
|
||||
when (store.state.search.selectedOrDefaultSearchEngine?.name) {
|
||||
AMAZON_SEARCH_ENGINE_NAME -> topSite.title != AMAZON_SPONSORED_TITLE
|
||||
EBAY_SPONSORED_TITLE -> topSite.title != EBAY_SPONSORED_TITLE
|
||||
else -> true
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
internal fun showUndoSnackbarForTopSite(topSite: TopSite) {
|
||||
lifecycleScope.allowUndo(
|
||||
@@ -1658,11 +1626,6 @@ class HomeFragment : Fragment() {
|
||||
// Delay for scrolling to the collection header
|
||||
private const val ANIM_SCROLL_DELAY = 100L
|
||||
|
||||
// Sponsored top sites titles and search engine names used for filtering
|
||||
const val AMAZON_SPONSORED_TITLE = "Amazon"
|
||||
const val AMAZON_SEARCH_ENGINE_NAME = "Amazon.com"
|
||||
const val EBAY_SPONSORED_TITLE = "eBay"
|
||||
|
||||
// Elevation for undo toasts
|
||||
internal const val TOAST_ELEVATION = 80f
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/* 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.home
|
||||
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.feature.top.sites.TopSitesProvider
|
||||
import mozilla.components.support.base.log.logger.Logger
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
/**
|
||||
* Class to refresh the top sites using the [TopSitesProvider]
|
||||
*
|
||||
* @param settings Fenix [Settings]
|
||||
* @param topSitesProvider [TopSitesProvider] to refresh top sites
|
||||
* @param dispatcher [CoroutineDispatcher] to use launch the refresh job.
|
||||
* Default value is [Dispatchers.IO]. It is helpful to improve testability
|
||||
*/
|
||||
class TopSitesRefresher(
|
||||
private val settings: Settings,
|
||||
private val topSitesProvider: TopSitesProvider,
|
||||
private val dispatcher: CoroutineDispatcher = Dispatchers.IO,
|
||||
) : DefaultLifecycleObserver {
|
||||
|
||||
private val logger = Logger("TopSitesRefresher")
|
||||
private val scope = CoroutineScope(dispatcher)
|
||||
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
scope.launch(dispatcher) {
|
||||
runCatching {
|
||||
if (settings.showContileFeature) {
|
||||
topSitesProvider.refreshTopSitesIfCacheExpired()
|
||||
}
|
||||
}.onFailure { exception ->
|
||||
logger.error("Failed to refresh contile top sites", exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause(owner: LifecycleOwner) {
|
||||
scope.cancel()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/* 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.home.topsites
|
||||
|
||||
/**
|
||||
* Constants used for the [mozilla.components.feature.top.sites.TopSitesConfig]
|
||||
*/
|
||||
internal object TopSitesConfigConstants {
|
||||
|
||||
/**
|
||||
* Only fetch top sites from the [mozilla.components.feature.top.sites.TopSitesProvider]
|
||||
* when the number of default and pinned sites are below this maximum threshold.
|
||||
*/
|
||||
internal const val TOP_SITES_PROVIDER_MAX_THRESHOLD = 8
|
||||
|
||||
/**
|
||||
* Number of top sites to take from the [mozilla.components.feature.top.sites.TopSitesProvider].
|
||||
*/
|
||||
internal const val TOP_SITES_PROVIDER_LIMIT = 2
|
||||
|
||||
/**
|
||||
* The maximum number of top sites to display.
|
||||
*/
|
||||
internal const val TOP_SITES_MAX_COUNT = 16
|
||||
|
||||
/**
|
||||
* Sponsored top sites titles for Amazon used for filtering
|
||||
*/
|
||||
const val AMAZON_SPONSORED_TITLE = "Amazon"
|
||||
|
||||
/**
|
||||
* Sponsored top sites search engine for Amazon used for filtering
|
||||
*/
|
||||
const val AMAZON_SEARCH_ENGINE_NAME = "Amazon.com"
|
||||
|
||||
/**
|
||||
* Sponsored top sites titles for eBay used for filtering
|
||||
*/
|
||||
const val EBAY_SPONSORED_TITLE = "eBay"
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/* 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.home.topsites
|
||||
|
||||
import androidx.core.net.toUri
|
||||
import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.concept.storage.FrecencyThresholdOption
|
||||
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 org.mozilla.fenix.ext.containsQueryParameters
|
||||
import org.mozilla.fenix.home.HomeFragment
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.AMAZON_SEARCH_ENGINE_NAME
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.AMAZON_SPONSORED_TITLE
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.EBAY_SPONSORED_TITLE
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.TOP_SITES_PROVIDER_LIMIT
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.TOP_SITES_PROVIDER_MAX_THRESHOLD
|
||||
import org.mozilla.fenix.nimbus.FxNimbus
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
/**
|
||||
* Top level function that creates [TopSitesConfig] for Fenix based on information from the [BrowserStore]
|
||||
* and [Settings].
|
||||
*
|
||||
* This is meant to be used with the [TopSitesFeature] and it exists instead of the lambda which
|
||||
* holds an implicit reference to the [HomeFragment].
|
||||
*/
|
||||
internal fun getTopSitesConfig(
|
||||
settings: Settings,
|
||||
store: BrowserStore,
|
||||
): () -> TopSitesConfig {
|
||||
return {
|
||||
TopSitesConfig(
|
||||
totalSites = settings.topSitesMaxLimit,
|
||||
frecencyConfig = if (FxNimbus.features.homepageHideFrecentTopSites.value().enabled) {
|
||||
null
|
||||
} else {
|
||||
TopSitesFrecencyConfig(
|
||||
frecencyTresholdOption = FrecencyThresholdOption.SKIP_ONE_TIME_PAGES,
|
||||
) { !it.url.toUri().containsQueryParameters(settings.frecencyFilterQuery) }
|
||||
},
|
||||
providerConfig = TopSitesProviderConfig(
|
||||
showProviderTopSites = settings.showContileFeature,
|
||||
limit = TOP_SITES_PROVIDER_LIMIT,
|
||||
maxThreshold = TOP_SITES_PROVIDER_MAX_THRESHOLD,
|
||||
providerFilter = { topSite ->
|
||||
when (store.state.search.selectedOrDefaultSearchEngine?.name) {
|
||||
AMAZON_SEARCH_ENGINE_NAME -> topSite.title != AMAZON_SPONSORED_TITLE
|
||||
EBAY_SPONSORED_TITLE -> topSite.title != EBAY_SPONSORED_TITLE
|
||||
else -> true
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import mozilla.components.concept.engine.EngineSession.CookieBannerHandlingMode
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules.AutoplayAction
|
||||
import mozilla.components.feature.top.sites.TopSitesProvider
|
||||
import mozilla.components.support.ktx.android.content.PreferencesHolder
|
||||
import mozilla.components.support.ktx.android.content.booleanPreference
|
||||
import mozilla.components.support.ktx.android.content.floatPreference
|
||||
@@ -45,6 +44,7 @@ import org.mozilla.fenix.components.toolbar.navbar.shouldAddNavigationBar
|
||||
import org.mozilla.fenix.debugsettings.addresses.SharedPrefsAddressesDebugLocalesRepository
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.TOP_SITES_MAX_COUNT
|
||||
import org.mozilla.fenix.nimbus.CookieBannersSection
|
||||
import org.mozilla.fenix.nimbus.FxNimbus
|
||||
import org.mozilla.fenix.nimbus.HomeScreenSection
|
||||
@@ -98,20 +98,6 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
||||
@VisibleForTesting
|
||||
internal var SEARCH_GROUP_MINIMUM_SITES: Int = 2
|
||||
|
||||
// The maximum number of top sites to display.
|
||||
const val TOP_SITES_MAX_COUNT = 16
|
||||
|
||||
/**
|
||||
* Only fetch top sites from the [TopSitesProvider] when the number of default and
|
||||
* pinned sites are below this maximum threshold.
|
||||
*/
|
||||
const val TOP_SITES_PROVIDER_MAX_THRESHOLD = 8
|
||||
|
||||
/**
|
||||
* Number of top sites to take from the [TopSitesProvider].
|
||||
*/
|
||||
const val TOP_SITES_PROVIDER_LIMIT = 2
|
||||
|
||||
/**
|
||||
* Minimum number of days between Set as default Browser prompt displays in home page.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/* 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.helpers.lifecycle
|
||||
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.Lifecycle.State
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LifecycleRegistry
|
||||
|
||||
/**
|
||||
* [LifecycleOwner] to be used for testing
|
||||
*
|
||||
* @param initialState Initial state. Defaults to [State.CREATED]
|
||||
*/
|
||||
class TestLifecycleOwner(initialState: State = State.CREATED) : LifecycleOwner {
|
||||
|
||||
private val registry = LifecycleRegistry.createUnsafe(this)
|
||||
|
||||
init {
|
||||
registry.currentState = initialState
|
||||
}
|
||||
|
||||
override val lifecycle: Lifecycle
|
||||
get() = registry
|
||||
|
||||
/**
|
||||
* Registers a [LifecycleObserver] for this [LifecycleOwner]
|
||||
*/
|
||||
fun registerObserver(observer: LifecycleObserver) {
|
||||
registry.addObserver(observer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates the `onCreate()` event
|
||||
*/
|
||||
fun onCreate() = registry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
|
||||
|
||||
/**
|
||||
* Simulates the on `onStart()` event
|
||||
*/
|
||||
fun onStart() = registry.handleLifecycleEvent(Lifecycle.Event.ON_START)
|
||||
|
||||
/**
|
||||
* Simulates the on `onResume()` event
|
||||
*/
|
||||
fun onResume() = registry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||
|
||||
/**
|
||||
* Simulates the on `onPause()` event
|
||||
*/
|
||||
fun onPause() = registry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE)
|
||||
|
||||
/**
|
||||
* Simulates the on `onStop()` event
|
||||
*/
|
||||
fun onStop() = registry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
|
||||
|
||||
/**
|
||||
* Simulates the on `onDestroy()` event
|
||||
*/
|
||||
fun onDestroy() = registry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
|
||||
}
|
||||
@@ -8,12 +8,6 @@ import android.content.Context
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.spyk
|
||||
import mozilla.components.browser.state.search.SearchEngine
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.SearchState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertNull
|
||||
@@ -25,8 +19,6 @@ import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.components.Core
|
||||
import org.mozilla.fenix.ext.application
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.home.HomeFragment.Companion.AMAZON_SPONSORED_TITLE
|
||||
import org.mozilla.fenix.home.HomeFragment.Companion.EBAY_SPONSORED_TITLE
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
class HomeFragmentTest {
|
||||
@@ -57,52 +49,6 @@ class HomeFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN getTopSitesConfig is called THEN it returns TopSitesConfig with non-null frecencyConfig`() {
|
||||
every { settings.topSitesMaxLimit } returns 10
|
||||
|
||||
val topSitesConfig = homeFragment.getTopSitesConfig()
|
||||
|
||||
assertNotNull(topSitesConfig.frecencyConfig)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN a topSitesMaxLimit WHEN getTopSitesConfig is called THEN it returns TopSitesConfig with totalSites = topSitesMaxLimit`() {
|
||||
val topSitesMaxLimit = 10
|
||||
every { settings.topSitesMaxLimit } returns topSitesMaxLimit
|
||||
|
||||
val topSitesConfig = homeFragment.getTopSitesConfig()
|
||||
|
||||
assertEquals(topSitesMaxLimit, topSitesConfig.totalSites)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the selected search engine is set to eBay WHEN getTopSitesConfig is called THEN providerFilter filters the eBay provided top sites`() {
|
||||
val searchEngine: SearchEngine = mockk()
|
||||
val browserStore = BrowserStore(
|
||||
initialState = BrowserState(
|
||||
search = SearchState(
|
||||
regionSearchEngines = listOf(searchEngine),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
every { core.store } returns browserStore
|
||||
every { searchEngine.name } returns EBAY_SPONSORED_TITLE
|
||||
|
||||
val eBayTopSite = TopSite.Provided(1L, EBAY_SPONSORED_TITLE, "eBay.com", "", "", "", 0L)
|
||||
val amazonTopSite = TopSite.Provided(2L, AMAZON_SPONSORED_TITLE, "Amazon.com", "", "", "", 0L)
|
||||
val firefoxTopSite = TopSite.Provided(3L, "Firefox", "mozilla.org", "", "", "", 0L)
|
||||
val providedTopSites = listOf(eBayTopSite, amazonTopSite, firefoxTopSite)
|
||||
|
||||
val topSitesConfig = homeFragment.getTopSitesConfig()
|
||||
|
||||
val filteredProvidedSites = providedTopSites.filter {
|
||||
topSitesConfig.providerConfig?.providerFilter?.invoke(it) ?: true
|
||||
}
|
||||
assertTrue(filteredProvidedSites.containsAll(listOf(amazonTopSite, firefoxTopSite)))
|
||||
assertFalse(filteredProvidedSites.contains(eBayTopSite))
|
||||
}
|
||||
|
||||
fun `GIVEN the user is in normal mode WHEN checking if should enable wallpaper THEN return true`() {
|
||||
val activity: HomeActivity = mockk {
|
||||
every { themeManager.currentTheme.isPrivate } returns false
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/* 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.home
|
||||
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
import mozilla.components.feature.top.sites.TopSitesProvider
|
||||
import mozilla.components.support.test.rule.MainCoroutineRule
|
||||
import mozilla.components.support.test.rule.runTestOnMain
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.helpers.lifecycle.TestLifecycleOwner
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
/**
|
||||
* Class to test the [TopSitesRefresher]
|
||||
*/
|
||||
class TopSitesRefresherTest {
|
||||
|
||||
@get:Rule
|
||||
val coroutinesTestRule = MainCoroutineRule()
|
||||
|
||||
private val lifecycleOwner = TestLifecycleOwner()
|
||||
|
||||
private val topSitesProvider = FakeTopSitesProvider()
|
||||
private val settings: Settings = mockk(relaxed = true)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
lifecycleOwner.registerObserver(
|
||||
observer = TopSitesRefresher(
|
||||
settings = settings,
|
||||
topSitesProvider = topSitesProvider,
|
||||
dispatcher = coroutinesTestRule.testDispatcher,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN lifecycle resumes AND we want to show contile feature THEN top sites are refreshed`() =
|
||||
runTestOnMain {
|
||||
every { settings.showContileFeature } returns true
|
||||
|
||||
lifecycleOwner.onResume()
|
||||
|
||||
assertTrue(topSitesProvider.cacheRefreshed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN lifecycle resumes AND we DO NOT want to show contile feature THEN top sites are NOT refreshed`() =
|
||||
runTestOnMain {
|
||||
every { settings.showContileFeature } returns false
|
||||
|
||||
lifecycleOwner.onResume()
|
||||
|
||||
assertFalse(topSitesProvider.cacheRefreshed)
|
||||
}
|
||||
|
||||
private class FakeTopSitesProvider : TopSitesProvider {
|
||||
|
||||
var expectedTopSites: List<TopSite> = emptyList()
|
||||
var cacheRefreshed: Boolean = false
|
||||
|
||||
override suspend fun getTopSites(allowCache: Boolean): List<TopSite> = expectedTopSites
|
||||
|
||||
override suspend fun refreshTopSitesIfCacheExpired() {
|
||||
cacheRefreshed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/* 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.home.topsites
|
||||
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import mozilla.components.browser.state.search.SearchEngine
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.SearchState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
import mozilla.components.feature.top.sites.TopSitesConfig
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.AMAZON_SPONSORED_TITLE
|
||||
import org.mozilla.fenix.home.topsites.TopSitesConfigConstants.EBAY_SPONSORED_TITLE
|
||||
import org.mozilla.fenix.nimbus.FxNimbus
|
||||
import org.mozilla.fenix.nimbus.HomepageHideFrecentTopSites
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
/**
|
||||
* Tests the top-level function [getTopSitesConfig] we use to create [TopSitesConfig]
|
||||
*/
|
||||
class TopSitesConfigCreatorTest {
|
||||
private lateinit var settings: Settings
|
||||
|
||||
private val browserStore = BrowserStore(
|
||||
initialState = BrowserState(search = SearchState(regionSearchEngines = listOf())),
|
||||
)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
settings = mockk(relaxed = true)
|
||||
every { settings.topSitesMaxLimit } returns 10
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN hide top sites flag is not enabled THEN it returns TopSitesConfig with non-null frequencyConfig`() {
|
||||
FxNimbus.features.homepageHideFrecentTopSites.withCachedValue(
|
||||
HomepageHideFrecentTopSites(
|
||||
enabled = false,
|
||||
),
|
||||
)
|
||||
|
||||
val topSitesConfig = getTopSitesConfig(settings = settings, store = browserStore).invoke()
|
||||
|
||||
assertNotNull(topSitesConfig.frecencyConfig)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN hide top sites flag is enabled THEN it returns TopSitesConfig with null frequencyConfig`() {
|
||||
FxNimbus.features.homepageHideFrecentTopSites.withCachedValue(
|
||||
HomepageHideFrecentTopSites(enabled = true),
|
||||
)
|
||||
|
||||
val topSitesConfig = getTopSitesConfig(settings = settings, store = browserStore).invoke()
|
||||
|
||||
assertNull(topSitesConfig.frecencyConfig)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN a topSitesMaxLimit THEN it returns TopSitesConfig with totalSites = topSitesMaxLimit`() {
|
||||
val topSitesMaxLimit = 15
|
||||
every { settings.topSitesMaxLimit } returns topSitesMaxLimit
|
||||
|
||||
val topSitesConfig = getTopSitesConfig(settings = settings, store = browserStore).invoke()
|
||||
|
||||
assertEquals(topSitesMaxLimit, topSitesConfig.totalSites)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN the selected search engine is set to eBay THEN providerFilter filters the eBay provided top sites`() {
|
||||
val searchEngine: SearchEngine = mockk()
|
||||
val browserStore = BrowserStore(
|
||||
initialState = BrowserState(
|
||||
search = SearchState(
|
||||
regionSearchEngines = listOf(searchEngine),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
every { searchEngine.name } returns EBAY_SPONSORED_TITLE
|
||||
|
||||
val eBayTopSite = TopSite.Provided(1L, EBAY_SPONSORED_TITLE, "eBay.com", "", "", "", 0L)
|
||||
val amazonTopSite =
|
||||
TopSite.Provided(2L, AMAZON_SPONSORED_TITLE, "Amazon.com", "", "", "", 0L)
|
||||
val firefoxTopSite = TopSite.Provided(3L, "Firefox", "mozilla.org", "", "", "", 0L)
|
||||
val providedTopSites = listOf(eBayTopSite, amazonTopSite, firefoxTopSite)
|
||||
|
||||
val topSitesConfig = getTopSitesConfig(settings = settings, store = browserStore).invoke()
|
||||
|
||||
val filteredProvidedSites = providedTopSites.filter {
|
||||
topSitesConfig.providerConfig?.providerFilter?.invoke(it) != false
|
||||
}
|
||||
assertTrue(filteredProvidedSites.containsAll(listOf(amazonTopSite, firefoxTopSite)))
|
||||
assertFalse(filteredProvidedSites.contains(eBayTopSite))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user