From 26b65a2a23adf6ecc6efdcdc08cdc6b20f45827f Mon Sep 17 00:00:00 2001 From: Gabriel Luong Date: Thu, 9 Dec 2021 14:00:48 -0500 Subject: [PATCH] For #22727 - Add Contile to Top Sites --- app/build.gradle | 1 + .../java/org/mozilla/fenix/FeatureFlags.kt | 5 + .../java/org/mozilla/fenix/components/Core.kt | 11 +- .../mozilla/fenix/components/metrics/Event.kt | 5 +- .../toolbar/BrowserToolbarMenuController.kt | 4 +- .../java/org/mozilla/fenix/ext/TopSite.kt | 17 +++ .../sessioncontrol/SessionControlAdapter.kt | 3 +- .../SessionControlController.kt | 37 +++--- .../SessionControlInteractor.kt | 9 +- .../home/topsites/TopSiteItemViewHolder.kt | 14 +-- .../DefaultSessionControlControllerTest.kt | 114 ++++++++++++++---- .../SessionControlAdapterTest.kt | 13 +- .../topsites/TopSiteItemViewHolderTest.kt | 22 ++-- .../home/topsites/TopSiteViewHolderTest.kt | 5 +- .../home/topsites/TopSitesAdapterTest.kt | 15 +-- .../home/topsites/TopSitesPagerAdapterTest.kt | 54 ++++----- buildSrc/src/main/java/AndroidComponents.kt | 2 +- buildSrc/src/main/java/Dependencies.kt | 2 + 18 files changed, 206 insertions(+), 127 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/ext/TopSite.kt diff --git a/app/build.gradle b/app/build.gradle index ba6c4155c..7d04267d5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -478,6 +478,7 @@ dependencies { implementation Deps.mozilla_feature_webcompat_reporter implementation Deps.mozilla_service_pocket + implementation Deps.mozilla_service_contile implementation Deps.mozilla_service_digitalassetlinks implementation Deps.mozilla_service_sync_autofill implementation Deps.mozilla_service_sync_logins diff --git a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt index b4cac70a9..1ea8daf61 100644 --- a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt +++ b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt @@ -91,4 +91,9 @@ object FeatureFlags { * Enables showing the wallpaper functionality. */ val showWallpapers = Config.channel.isNightlyOrDebug + + /** + * Enables the Contile top sites. + */ + const val contileFeature = false } diff --git a/app/src/main/java/org/mozilla/fenix/components/Core.kt b/app/src/main/java/org/mozilla/fenix/components/Core.kt index 5fc8ac26f..1bddabf79 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Core.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Core.kt @@ -53,6 +53,7 @@ import mozilla.components.feature.webcompat.WebCompatFeature import mozilla.components.feature.webcompat.reporter.WebCompatReporterFeature import mozilla.components.feature.webnotifications.WebNotificationFeature import mozilla.components.lib.dataprotect.SecureAbove22Preferences +import mozilla.components.service.contile.ContileTopSitesProvider import mozilla.components.service.digitalassetlinks.RelationChecker import mozilla.components.service.digitalassetlinks.local.StatementApi import mozilla.components.service.digitalassetlinks.local.StatementRelationChecker @@ -67,6 +68,7 @@ import mozilla.components.support.locale.LocaleManager import org.mozilla.fenix.AppRequestInterceptor import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.Config +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.components.search.SearchMigration @@ -334,6 +336,8 @@ class Core( } val pocketStoriesService by lazyMonitored { PocketStoriesService(context, pocketStoriesConfig) } + val contileTopSitesProvider by lazyMonitored { ContileTopSitesProvider(client) } + val topSitesStorage by lazyMonitored { val defaultTopSites = mutableListOf>() @@ -404,9 +408,10 @@ class Core( } DefaultTopSitesStorage( - pinnedSiteStorage, - historyStorage, - defaultTopSites + pinnedSitesStorage = pinnedSiteStorage, + historyStorage = historyStorage, + topSitesProvider = if (FeatureFlags.contileFeature) contileTopSitesProvider else null, + defaultTopSites = defaultTopSites ) } diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt index 8f56d67a5..ffe14641e 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt @@ -29,6 +29,7 @@ import org.mozilla.fenix.GleanMetrics.ToolbarSettings import org.mozilla.fenix.GleanMetrics.TopSites import org.mozilla.fenix.GleanMetrics.TrackingProtection import org.mozilla.fenix.R +import org.mozilla.fenix.ext.name import java.util.Locale sealed class Event { @@ -335,9 +336,9 @@ sealed class Event { object SecurePrefsWriteSuccess : Event() object SecurePrefsReset : Event() - data class TopSiteLongPress(val type: TopSite.Type) : Event() { + data class TopSiteLongPress(val topSite: TopSite) : Event() { override val extras: Map? - get() = hashMapOf(TopSites.longPressKeys.type to type.name) + get() = hashMapOf(TopSites.longPressKeys.type to topSite.name()) } data class ProgressiveWebAppForeground(val timeForegrounded: Long) : Event() { diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt index 48f67cefd..c7b306d7e 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt @@ -250,8 +250,8 @@ class DefaultBrowserToolbarMenuController( is ToolbarMenu.Item.AddToTopSites -> { scope.launch { val context = swipeRefresh.context - val numPinnedSites = - topSitesStorage.cachedTopSites.filter { it.type != TopSite.Type.FRECENT }.size + val numPinnedSites = topSitesStorage.cachedTopSites + .filter { it !is TopSite.Frecent || it !is TopSite.Provided }.size if (numPinnedSites >= settings.topSitesMaxLimit) { AlertDialog.Builder(swipeRefresh.context).apply { diff --git a/app/src/main/java/org/mozilla/fenix/ext/TopSite.kt b/app/src/main/java/org/mozilla/fenix/ext/TopSite.kt new file mode 100644 index 000000000..3bda9a589 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/ext/TopSite.kt @@ -0,0 +1,17 @@ +/* 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.ext + +import mozilla.components.feature.top.sites.TopSite + +/** + * Returns the type name of the [TopSite]. + */ +fun TopSite.name(): String = when (this) { + is TopSite.Default -> "DEFAULT" + is TopSite.Frecent -> "FRECENT" + is TopSite.Pinned -> "PINNED" + is TopSite.Provided -> "PROVIDED" +} diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt index 98b4f761e..7445945f0 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt @@ -15,7 +15,6 @@ import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.feature.top.sites.TopSite -import mozilla.components.feature.top.sites.TopSite.Type.FRECENT import mozilla.components.ui.widgets.WidgetSiteItemView import org.mozilla.fenix.components.Components import org.mozilla.fenix.components.tips.Tip @@ -98,7 +97,7 @@ sealed class AdapterItem(@LayoutRes val viewType: Int) { for ((index, item) in oldTopSites.topSites.withIndex()) { val changedItem = - newTopSites.topSites.getOrNull(index) ?: TopSite(-1, "REMOVED", "", 0, FRECENT) + newTopSites.topSites.getOrNull(index) ?: TopSite.Frecent(-1, "REMOVED", "", 0) if (changedItem != item) { changed.add((Pair(index, changedItem))) } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt index 6318551dc..91203d4c5 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt @@ -118,7 +118,7 @@ interface SessionControlController { /** * @see [TopSiteInteractor.onSelectTopSite] */ - fun handleSelectTopSite(url: String, type: TopSite.Type) + fun handleSelectTopSite(topSite: TopSite) /** * @see [OnboardingInteractor.onStartBrowsingClicked] @@ -373,38 +373,29 @@ class DefaultSessionControlController( metrics.track(Event.CollectionRenamePressed) } - override fun handleSelectTopSite(url: String, type: TopSite.Type) { + override fun handleSelectTopSite(topSite: TopSite) { dismissSearchDialogIfDisplayed() metrics.track(Event.TopSiteOpenInNewTab) - when (type) { - TopSite.Type.DEFAULT -> metrics.track(Event.TopSiteOpenDefault) - TopSite.Type.FRECENT -> metrics.track(Event.TopSiteOpenFrecent) - TopSite.Type.PINNED -> metrics.track(Event.TopSiteOpenPinned) + when (topSite) { + is TopSite.Default -> metrics.track(Event.TopSiteOpenDefault) + is TopSite.Frecent -> metrics.track(Event.TopSiteOpenFrecent) + is TopSite.Pinned -> metrics.track(Event.TopSiteOpenPinned) } - if (url == SupportUtils.GOOGLE_URL) { - metrics.track(Event.TopSiteOpenGoogle) - } - - if (url == SupportUtils.BAIDU_URL) { - metrics.track(Event.TopSiteOpenBaidu) - } - - if (url == SupportUtils.POCKET_TRENDING_URL) { - metrics.track(Event.PocketTopSiteClicked) + when (topSite.url) { + SupportUtils.GOOGLE_URL -> metrics.track(Event.TopSiteOpenGoogle) + SupportUtils.BAIDU_URL -> metrics.track(Event.TopSiteOpenBaidu) + SupportUtils.POCKET_TRENDING_URL -> metrics.track(Event.PocketTopSiteClicked) } val availableEngines = getAvailableSearchEngines() - val searchAccessPoint = Event.PerformedSearch.SearchAccessPoint.TOPSITE val event = - availableEngines.firstOrNull { - engine -> - engine.resultUrls.firstOrNull { it.contains(url) } != null - }?.let { - searchEngine -> + availableEngines.firstOrNull { engine -> + engine.resultUrls.firstOrNull { it.contains(topSite.url) } != null + }?.let { searchEngine -> searchAccessPoint.let { sap -> MetricsUtils.createSearchEvent(searchEngine, store, sap) } @@ -412,7 +403,7 @@ class DefaultSessionControlController( event?.let { activity.metrics.track(it) } val tabId = addTabUseCase.invoke( - url = appendSearchAttributionToUrlIfNeeded(url), + url = appendSearchAttributionToUrlIfNeeded(topSite.url), selectTab = true, startLoading = true ) diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt index bf0ad8caa..d9e244e41 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt @@ -209,10 +209,9 @@ interface TopSiteInteractor { /** * Selects the given top site. Called when a user clicks on a top site. * - * @param url The URL of the top site. - * @param type The type of the top site. + * @param topSite The top site that was selected. */ - fun onSelectTopSite(url: String, type: TopSite.Type) + fun onSelectTopSite(topSite: TopSite) /** * Called when top site menu is opened. @@ -298,8 +297,8 @@ class SessionControlInteractor( controller.handleRenameCollectionTapped(collection) } - override fun onSelectTopSite(url: String, type: TopSite.Type) { - controller.handleSelectTopSite(url, type) + override fun onSelectTopSite(topSite: TopSite) { + controller.handleSelectTopSite(topSite) } override fun onStartBrowsingClicked() { diff --git a/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolder.kt index 775c485c7..2a7f385d5 100644 --- a/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolder.kt @@ -13,9 +13,6 @@ import androidx.appcompat.content.res.AppCompatResources.getDrawable import mozilla.components.browser.menu.BrowserMenuBuilder import mozilla.components.browser.menu.item.SimpleBrowserMenuItem import mozilla.components.feature.top.sites.TopSite -import mozilla.components.feature.top.sites.TopSite.Type.DEFAULT -import mozilla.components.feature.top.sites.TopSite.Type.FRECENT -import mozilla.components.feature.top.sites.TopSite.Type.PINNED import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.databinding.TopSiteItemBinding @@ -34,14 +31,17 @@ class TopSiteItemViewHolder( init { binding.topSiteItem.setOnClickListener { - interactor.onSelectTopSite(topSite.url, topSite.type) + interactor.onSelectTopSite(topSite) } binding.topSiteItem.setOnLongClickListener { interactor.onTopSiteMenuOpened() - it.context.components.analytics.metrics.track(Event.TopSiteLongPress(topSite.type)) + it.context.components.analytics.metrics.track(Event.TopSiteLongPress(topSite)) - val topSiteMenu = TopSiteItemMenu(view.context, topSite.type != FRECENT) { item -> + val topSiteMenu = TopSiteItemMenu( + context = view.context, + isPinnedSite = topSite is TopSite.Pinned || topSite is TopSite.Default + ) { item -> when (item) { is TopSiteItemMenu.Item.OpenInPrivateTab -> interactor.onOpenInPrivateTabClicked( topSite @@ -65,7 +65,7 @@ class TopSiteItemViewHolder( fun bind(topSite: TopSite) { binding.topSiteTitle.text = topSite.title - if (topSite.type == PINNED || topSite.type == DEFAULT) { + if (topSite is TopSite.Pinned || topSite is TopSite.Default) { val pinIndicator = getDrawable(itemView.context, R.drawable.ic_new_pin) binding.topSiteTitle.setCompoundDrawablesWithIntrinsicBounds(pinIndicator, null, null, null) } else { diff --git a/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt b/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt index aecd77b75..740058f10 100644 --- a/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt @@ -384,16 +384,23 @@ class DefaultSessionControlControllerTest { @Test fun handleSelectDefaultTopSite() { - val topSiteUrl = "mozilla.org" + val topSite = TopSite.Default( + id = 1L, + title = "Mozilla", + url = "mozilla.org", + createdAt = 0 + ) val controller = spyk(createController()) + every { controller.getAvailableSearchEngines() } returns listOf(searchEngine) - controller.handleSelectTopSite(topSiteUrl, TopSite.Type.DEFAULT) + controller.handleSelectTopSite(topSite) + verify { metrics.track(Event.TopSiteOpenInNewTab) } verify { metrics.track(Event.TopSiteOpenDefault) } verify { tabsUseCases.addTab.invoke( - topSiteUrl, + url = topSite.url, selectTab = true, startLoading = true ) @@ -403,15 +410,22 @@ class DefaultSessionControlControllerTest { @Test fun handleSelectNonDefaultTopSite() { - val topSiteUrl = "mozilla.org" + val topSite = TopSite.Frecent( + id = 1L, + title = "Mozilla", + url = "mozilla.org", + createdAt = 0 + ) val controller = spyk(createController()) + every { controller.getAvailableSearchEngines() } returns listOf(searchEngine) - controller.handleSelectTopSite(topSiteUrl, TopSite.Type.FRECENT) + controller.handleSelectTopSite(topSite) + verify { metrics.track(Event.TopSiteOpenInNewTab) } verify { tabsUseCases.addTab.invoke( - topSiteUrl, + url = topSite.url, selectTab = true, startLoading = true ) @@ -421,13 +435,20 @@ class DefaultSessionControlControllerTest { @Test fun handleSelectGoogleDefaultTopSiteUS() { - val topSiteUrl = SupportUtils.GOOGLE_URL + val topSite = TopSite.Default( + id = 1L, + title = "Google", + url = SupportUtils.GOOGLE_URL, + createdAt = 0 + ) val controller = spyk(createController()) + every { controller.getAvailableSearchEngines() } returns listOf(searchEngine) store.dispatch(SearchAction.SetRegionAction(RegionState("US", "US"))).joinBlocking() - controller.handleSelectTopSite(topSiteUrl, TopSite.Type.DEFAULT) + controller.handleSelectTopSite(topSite) + verify { metrics.track(Event.TopSiteOpenInNewTab) } verify { metrics.track(Event.TopSiteOpenDefault) } verify { metrics.track(Event.TopSiteOpenGoogle) } @@ -443,13 +464,20 @@ class DefaultSessionControlControllerTest { @Test fun handleSelectGoogleDefaultTopSiteXX() { - val topSiteUrl = SupportUtils.GOOGLE_URL + val topSite = TopSite.Default( + id = 1L, + title = "Google", + url = SupportUtils.GOOGLE_URL, + createdAt = 0 + ) val controller = spyk(createController()) + every { controller.getAvailableSearchEngines() } returns listOf(searchEngine) store.dispatch(SearchAction.SetRegionAction(RegionState("DE", "FR"))).joinBlocking() - controller.handleSelectTopSite(topSiteUrl, TopSite.Type.DEFAULT) + controller.handleSelectTopSite(topSite) + verify { metrics.track(Event.TopSiteOpenInNewTab) } verify { metrics.track(Event.TopSiteOpenDefault) } verify { metrics.track(Event.TopSiteOpenGoogle) } @@ -465,16 +493,23 @@ class DefaultSessionControlControllerTest { @Test fun handleSelectGoogleDefaultTopSite_EventPerformedSearchTopSite() { - val topSiteUrl = SupportUtils.GOOGLE_URL + val topSite = TopSite.Default( + id = 1L, + title = "Google", + url = SupportUtils.GOOGLE_URL, + createdAt = 0 + ) val engineSource = EngineSource.Default(googleSearchEngine, false) val controller = spyk(createController()) + every { controller.getAvailableSearchEngines() } returns listOf(googleSearchEngine) + try { mockkStatic("mozilla.components.browser.state.state.SearchStateKt") every { any().selectedOrDefaultSearchEngine } returns googleSearchEngine - controller.handleSelectTopSite(topSiteUrl, TopSite.Type.DEFAULT) + controller.handleSelectTopSite(topSite) verify { metrics.track( @@ -494,16 +529,23 @@ class DefaultSessionControlControllerTest { @Test fun handleSelectDuckDuckGoTopSite_EventPerformedSearchTopSite() { - val topSiteUrl = "https://duckduckgo.com" + val topSite = TopSite.Pinned( + id = 1L, + title = "DuckDuckGo", + url = "https://duckduckgo.com", + createdAt = 0 + ) val engineSource = EngineSource.Shortcut(duckDuckGoSearchEngine, false) val controller = spyk(createController()) + every { controller.getAvailableSearchEngines() } returns listOf(googleSearchEngine, duckDuckGoSearchEngine) + try { mockkStatic("mozilla.components.browser.state.state.SearchStateKt") every { any().selectedOrDefaultSearchEngine } returns googleSearchEngine - controller.handleSelectTopSite(topSiteUrl, TopSite.Type.PINNED) + controller.handleSelectTopSite(topSite) verify { metrics.track( @@ -523,13 +565,20 @@ class DefaultSessionControlControllerTest { @Test fun handleSelectGooglePinnedTopSiteUS() { - val topSiteUrl = SupportUtils.GOOGLE_URL + val topSite = TopSite.Pinned( + id = 1L, + title = "Google", + url = SupportUtils.GOOGLE_URL, + createdAt = 0 + ) val controller = spyk(createController()) + every { controller.getAvailableSearchEngines() } returns listOf(searchEngine) store.dispatch(SearchAction.SetRegionAction(RegionState("US", "US"))).joinBlocking() - controller.handleSelectTopSite(topSiteUrl, TopSite.Type.PINNED) + controller.handleSelectTopSite(topSite) + verify { metrics.track(Event.TopSiteOpenInNewTab) } verify { metrics.track(Event.TopSiteOpenPinned) } verify { metrics.track(Event.TopSiteOpenGoogle) } @@ -545,13 +594,20 @@ class DefaultSessionControlControllerTest { @Test fun handleSelectGooglePinnedTopSiteXX() { - val topSiteUrl = SupportUtils.GOOGLE_URL + val topSite = TopSite.Pinned( + id = 1L, + title = "Google", + url = SupportUtils.GOOGLE_URL, + createdAt = 0 + ) val controller = spyk(createController()) + every { controller.getAvailableSearchEngines() } returns listOf(searchEngine) store.dispatch(SearchAction.SetRegionAction(RegionState("DE", "FR"))).joinBlocking() - controller.handleSelectTopSite(topSiteUrl, TopSite.Type.PINNED) + controller.handleSelectTopSite(topSite) + verify { metrics.track(Event.TopSiteOpenInNewTab) } verify { metrics.track(Event.TopSiteOpenPinned) } verify { metrics.track(Event.TopSiteOpenGoogle) } @@ -567,13 +623,20 @@ class DefaultSessionControlControllerTest { @Test fun handleSelectGoogleFrecentTopSiteUS() { - val topSiteUrl = SupportUtils.GOOGLE_URL + val topSite = TopSite.Frecent( + id = 1L, + title = "Google", + url = SupportUtils.GOOGLE_URL, + createdAt = 0 + ) val controller = spyk(createController()) + every { controller.getAvailableSearchEngines() } returns listOf(searchEngine) store.dispatch(SearchAction.SetRegionAction(RegionState("US", "US"))).joinBlocking() - controller.handleSelectTopSite(topSiteUrl, TopSite.Type.FRECENT) + controller.handleSelectTopSite(topSite) + verify { metrics.track(Event.TopSiteOpenInNewTab) } verify { metrics.track(Event.TopSiteOpenFrecent) } verify { metrics.track(Event.TopSiteOpenGoogle) } @@ -589,13 +652,20 @@ class DefaultSessionControlControllerTest { @Test fun handleSelectGoogleFrecentTopSiteXX() { - val topSiteUrl = SupportUtils.GOOGLE_URL + val topSite = TopSite.Frecent( + id = 1L, + title = "Google", + url = SupportUtils.GOOGLE_URL, + createdAt = 0 + ) val controller = spyk(createController()) + every { controller.getAvailableSearchEngines() } returns listOf(searchEngine) store.dispatch(SearchAction.SetRegionAction(RegionState("DE", "FR"))).joinBlocking() - controller.handleSelectTopSite(topSiteUrl, TopSite.Type.FRECENT) + controller.handleSelectTopSite(topSite) + verify { metrics.track(Event.TopSiteOpenInNewTab) } verify { metrics.track(Event.TopSiteOpenFrecent) } verify { metrics.track(Event.TopSiteOpenGoogle) } diff --git a/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapterTest.kt b/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapterTest.kt index 73d67e60d..03c72e82e 100644 --- a/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapterTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapterTest.kt @@ -7,7 +7,6 @@ package org.mozilla.fenix.home.sessioncontrol import io.mockk.every import io.mockk.mockk import mozilla.components.feature.top.sites.TopSite -import mozilla.components.feature.top.sites.TopSite.Type.FRECENT import org.junit.Assert.assertEquals import org.junit.Assert.assertNull import org.junit.Test @@ -52,9 +51,9 @@ class SessionControlAdapterTest { @Test fun `GIVEN two topSites WHEN getChangePayload called with one changed item THEN return TopSitePagerPayload with changes`() { - val topSite0 = TopSite(-1, "topSite0", "", 0, FRECENT) - val topSite1 = TopSite(-1, "topSite1", "", 0, FRECENT) - val topSiteChanged = TopSite(-1, "changed", "", 0, FRECENT) + val topSite0 = TopSite.Frecent(-1, "topSite0", "", 0) + val topSite1 = TopSite.Frecent(-1, "topSite1", "", 0) + val topSiteChanged = TopSite.Frecent(-1, "changed", "", 0) val topSitePager = TopSitePager(listOf(topSite0, topSite1)) val newItem = TopSitePager(listOf(topSite0, topSiteChanged)) @@ -65,9 +64,9 @@ class SessionControlAdapterTest { @Test fun `GIVEN two topSites WHEN getChangePayload called with one removed THEN return TopSitePagerPayload with removed item`() { - val topSite0 = TopSite(-1, "topSite0", "", 0, FRECENT) - val topSite1 = TopSite(-1, "topSite1", "", 0, FRECENT) - val topSiteRemoved = TopSite(-1, "REMOVED", "", 0, FRECENT) + val topSite0 = TopSite.Frecent(-1, "topSite0", "", 0) + val topSite1 = TopSite.Frecent(-1, "topSite1", "", 0) + val topSiteRemoved = TopSite.Frecent(-1, "REMOVED", "", 0) val topSitePager = TopSitePager(listOf(topSite0, topSite1)) val newItem = TopSitePager(listOf(topSite0)) diff --git a/app/src/test/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolderTest.kt index 5bf2a0bcd..7cef00f86 100644 --- a/app/src/test/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/topsites/TopSiteItemViewHolderTest.kt @@ -26,12 +26,11 @@ class TopSiteItemViewHolderTest { private lateinit var binding: TopSiteItemBinding private lateinit var interactor: TopSiteInteractor - private val pocket = TopSite( + private val pocket = TopSite.Default( id = 1L, title = "Pocket", url = "https://getpocket.com", - createdAt = 0, - type = TopSite.Type.DEFAULT + createdAt = 0 ) @Before @@ -46,7 +45,7 @@ class TopSiteItemViewHolderTest { TopSiteItemViewHolder(binding.root, interactor).bind(pocket) binding.topSiteItem.performClick() - verify { interactor.onSelectTopSite("https://getpocket.com", TopSite.Type.DEFAULT) } + verify { interactor.onSelectTopSite(pocket) } } @Test @@ -60,12 +59,11 @@ class TopSiteItemViewHolderTest { @Test fun `GIVEN a default top site WHEN bind is called THEN the title has a pin indicator`() { - val defaultTopSite = TopSite( + val defaultTopSite = TopSite.Default( id = 1L, title = "Pocket", url = "https://getpocket.com", - createdAt = 0, - type = TopSite.Type.DEFAULT + createdAt = 0 ) TopSiteItemViewHolder(binding.root, interactor).bind(defaultTopSite) @@ -76,12 +74,11 @@ class TopSiteItemViewHolderTest { @Test fun `GIVEN a pinned top site WHEN bind is called THEN the title has a pin indicator`() { - val pinnedTopSite = TopSite( + val pinnedTopSite = TopSite.Pinned( id = 1L, title = "Mozilla", url = "https://www.mozilla.org", - createdAt = 0, - type = TopSite.Type.PINNED + createdAt = 0 ) TopSiteItemViewHolder(binding.root, interactor).bind(pinnedTopSite) @@ -92,12 +89,11 @@ class TopSiteItemViewHolderTest { @Test fun `GIVEN a frecent top site WHEN bind is called THEN the title does not have a pin indicator`() { - val frecentTopSite = TopSite( + val frecentTopSite = TopSite.Frecent( id = 1L, title = "Mozilla", url = "https://www.mozilla.org", - createdAt = 0, - type = TopSite.Type.FRECENT + createdAt = 0 ) TopSiteItemViewHolder(binding.root, interactor).bind(frecentTopSite) diff --git a/app/src/test/java/org/mozilla/fenix/home/topsites/TopSiteViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/home/topsites/TopSiteViewHolderTest.kt index b1c1530d5..f3a8debf3 100644 --- a/app/src/test/java/org/mozilla/fenix/home/topsites/TopSiteViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/topsites/TopSiteViewHolderTest.kt @@ -32,12 +32,11 @@ class TopSiteViewHolderTest { fun `binds list of top sites`() { TopSiteViewHolder(binding.root, interactor).bind( listOf( - TopSite( + TopSite.Default( id = 1L, title = "Pocket", url = "https://getpocket.com", - createdAt = 0, - type = TopSite.Type.DEFAULT + createdAt = 0 ) ) ) diff --git a/app/src/test/java/org/mozilla/fenix/home/topsites/TopSitesAdapterTest.kt b/app/src/test/java/org/mozilla/fenix/home/topsites/TopSitesAdapterTest.kt index 80ba31287..3f46dfd74 100644 --- a/app/src/test/java/org/mozilla/fenix/home/topsites/TopSitesAdapterTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/topsites/TopSitesAdapterTest.kt @@ -12,19 +12,17 @@ class TopSitesAdapterTest { @Test fun testDiffCallback() { - val topSite = TopSite( + val topSite = TopSite.Default( id = 1L, title = "Title1", url = "https://mozilla.org", - null, - TopSite.Type.DEFAULT + null ) - val topSite2 = TopSite( + val topSite2 = TopSite.Default( id = 1L, title = "Title2", url = "https://mozilla.org", - null, - TopSite.Type.DEFAULT + null ) assertEquals( @@ -32,12 +30,11 @@ class TopSitesAdapterTest { topSite.copy(title = "Title2") ) - val topSite3 = TopSite( + val topSite3 = TopSite.Default( id = 2L, title = "Title2", url = "https://firefox.org", - null, - TopSite.Type.DEFAULT + null ) assertEquals( diff --git a/app/src/test/java/org/mozilla/fenix/home/topsites/TopSitesPagerAdapterTest.kt b/app/src/test/java/org/mozilla/fenix/home/topsites/TopSitesPagerAdapterTest.kt index ff9c5ec60..f8daa3988 100644 --- a/app/src/test/java/org/mozilla/fenix/home/topsites/TopSitesPagerAdapterTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/topsites/TopSitesPagerAdapterTest.kt @@ -11,7 +11,6 @@ import io.mockk.mockk import io.mockk.spyk import io.mockk.verify import mozilla.components.feature.top.sites.TopSite -import mozilla.components.feature.top.sites.TopSite.Type.DEFAULT import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test @@ -21,35 +20,31 @@ class TopSitesPagerAdapterTest { private lateinit var topSitesPagerAdapter: TopSitesPagerAdapter - private val topSite = TopSite( + private val topSite = TopSite.Default( id = 1L, title = "Title1", url = "https://mozilla.org", - null, - DEFAULT + null ) - private val topSite2 = TopSite( + private val topSite2 = TopSite.Default( id = 2L, title = "Title2", url = "https://mozilla.org", - null, - DEFAULT + null ) - private val topSite3 = TopSite( + private val topSite3 = TopSite.Default( id = 3L, title = "Title3", url = "https://firefox.org", - null, - DEFAULT + null ) - private val topSite4 = TopSite( + private val topSite4 = TopSite.Default( id = 4L, title = "Title4", url = "https://firefox.org", - null, - DEFAULT + null ) @Before @@ -101,16 +96,17 @@ class TopSitesPagerAdapterTest { @Test fun `WHEN update is called to delete the 1st of 4 topSites THEN submitList will update 3 topSites`() { - val currentList = mutableListOf(topSite, topSite2, topSite3, topSite4) + val currentList = listOf(topSite, topSite2, topSite3, topSite4) val topSitesAdapter: TopSitesAdapter = mockk() + every { topSitesAdapter.currentList } returns currentList every { topSitesAdapter.submitList(any()) } just Runs - val removedTopSite = TopSite( + + val removedTopSite = TopSite.Default( id = -1L, title = "REMOVED", url = "https://firefox.org", - null, - DEFAULT + null ) val payload = TopSitePagerPayload( setOf( @@ -123,22 +119,23 @@ class TopSitesPagerAdapterTest { topSitesPagerAdapter.update(payload, 0, topSitesAdapter) - val expected = mutableListOf(topSite2, topSite3, topSite4) + val expected = listOf(topSite2, topSite3, topSite4) verify { topSitesAdapter.submitList(expected) } } @Test fun `WHEN update is called to delete the 4th of 4 topSites THEN submitList will update 1 topSite`() { - val currentList = mutableListOf(topSite, topSite2, topSite3, topSite4) + val currentList = listOf(topSite, topSite2, topSite3, topSite4) val topSitesAdapter: TopSitesAdapter = mockk() + every { topSitesAdapter.currentList } returns currentList every { topSitesAdapter.submitList(any()) } just Runs - val removedTopSite = TopSite( + + val removedTopSite = TopSite.Default( id = -1L, title = "REMOVED", url = "https://firefox.org", - null, - DEFAULT + null ) val payload = TopSitePagerPayload( setOf( @@ -148,22 +145,23 @@ class TopSitesPagerAdapterTest { topSitesPagerAdapter.update(payload, 0, topSitesAdapter) - val expected = mutableListOf(topSite, topSite2, topSite3) + val expected = listOf(topSite, topSite2, topSite3) verify { topSitesAdapter.submitList(expected) } } @Test fun `WHEN update is called to update the 3rd of 4 topSites THEN submitList will contain 4 items`() { - val currentList = mutableListOf(topSite, topSite2, topSite3, topSite4) + val currentList = listOf(topSite, topSite2, topSite3, topSite4) val topSitesAdapter: TopSitesAdapter = mockk() + every { topSitesAdapter.currentList } returns currentList every { topSitesAdapter.submitList(any()) } just Runs - val changedTopSite = TopSite( + + val changedTopSite = TopSite.Default( id = 3L, title = "CHANGED", url = "https://firefox.org", - null, - DEFAULT + null ) val payload = TopSitePagerPayload( setOf( @@ -173,7 +171,7 @@ class TopSitesPagerAdapterTest { topSitesPagerAdapter.update(payload, 0, topSitesAdapter) - val expected = mutableListOf(topSite, topSite2, changedTopSite, topSite4) + val expected = listOf(topSite, topSite2, changedTopSite, topSite4) verify { topSitesAdapter.submitList(expected) } } } diff --git a/buildSrc/src/main/java/AndroidComponents.kt b/buildSrc/src/main/java/AndroidComponents.kt index 2b83db167..e73f4698a 100644 --- a/buildSrc/src/main/java/AndroidComponents.kt +++ b/buildSrc/src/main/java/AndroidComponents.kt @@ -3,5 +3,5 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ object AndroidComponents { - const val VERSION = "98.0.20220117143334" + const val VERSION = "98.0.20220118143334" } diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index f1ce808b4..167207cdd 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -137,6 +137,8 @@ object Deps { const val mozilla_feature_webcompat_reporter = "org.mozilla.components:feature-webcompat-reporter:${Versions.mozilla_android_components}" const val mozilla_service_pocket = "org.mozilla.components:service-pocket:${Versions.mozilla_android_components}" + const val mozilla_service_contile = + "org.mozilla.components:service-contile:${Versions.mozilla_android_components}" const val mozilla_service_digitalassetlinks = "org.mozilla.components:service-digitalassetlinks:${Versions.mozilla_android_components}" const val mozilla_service_sync_autofill =