diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 720066ea59..14e4b473ae 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -300,6 +300,15 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { } } + components.backgroundServices.accountManagerAvailableQueue.runIfReadyOrQueue { + lifecycleScope.launch(IO) { + // If we're authenticated, kick-off a sync and a device state refresh. + components.backgroundServices.accountManager.authenticatedAccount()?.let { + components.backgroundServices.accountManager.syncNow(reason = SyncReason.Startup) + } + } + } + components.core.engine.profiler?.addMarker( MarkersActivityLifecycleCallbacks.MARKER_NAME, startTimeProfiler, "HomeActivity.onCreate" ) @@ -336,23 +345,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { message = "onResume()" ) - components.backgroundServices.accountManagerAvailableQueue.runIfReadyOrQueue { - lifecycleScope.launch { - // If we're authenticated, kick-off a sync and a device state refresh. - components.backgroundServices.accountManager.authenticatedAccount()?.let { - val syncReason = when (isVisuallyComplete) { - true -> SyncReason.User - false -> SyncReason.Startup - } - - components.backgroundServices.accountManager.syncNow( - reason = syncReason, - debounce = true - ) - } - } - } - lifecycleScope.launch(IO) { try { if (settings().showContileFeature) { diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 0c989fec63..dc51e680a4 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -281,6 +281,7 @@ class HomeFragment : Fragment() { if (requireContext().settings().enableTaskContinuityEnhancements) { recentSyncedTabFeature.set( feature = RecentSyncedTabFeature( + context = requireContext(), appStore = requireComponents.appStore, syncStore = requireComponents.backgroundServices.syncStore, storage = requireComponents.backgroundServices.syncedTabsStorage, diff --git a/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/RecentSyncedTabFeature.kt b/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/RecentSyncedTabFeature.kt index 5777edffab..8d325d612a 100644 --- a/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/RecentSyncedTabFeature.kt +++ b/app/src/main/java/org/mozilla/fenix/home/recentsyncedtabs/RecentSyncedTabFeature.kt @@ -4,6 +4,7 @@ package org.mozilla.fenix.home.recentsyncedtabs +import android.content.Context import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -12,6 +13,7 @@ import mozilla.components.feature.syncedtabs.storage.SyncedTabsStorage import mozilla.components.lib.state.ext.flow import mozilla.components.service.fxa.SyncEngine import mozilla.components.service.fxa.manager.FxaAccountManager +import mozilla.components.service.fxa.manager.SyncEnginesStorage import mozilla.components.service.fxa.manager.ext.withConstellation import mozilla.components.service.fxa.store.SyncStatus import mozilla.components.service.fxa.store.SyncStore @@ -33,6 +35,7 @@ import org.mozilla.fenix.GleanMetrics.RecentSyncedTabs * @property coroutineScope The scope to collect Sync state Flow updates in. */ class RecentSyncedTabFeature( + private val context: Context, private val appStore: AppStore, private val syncStore: SyncStore, private val storage: SyncedTabsStorage, @@ -62,7 +65,6 @@ class RecentSyncedTabFeature( accountManager.withConstellation { refreshDevices() } accountManager.syncNow( reason = SyncReason.User, - debounce = true, customEngineSubset = listOf(SyncEngine.Tabs), ) } @@ -94,6 +96,14 @@ class RecentSyncedTabFeature( } private suspend fun dispatchSyncedTabs() { + if (!isSyncedTabsEngineEnabled()) { + appStore.dispatch( + AppAction.RecentSyncedTabStateChange(RecentSyncedTabState.None) + ) + + return + } + val syncedTab = storage.getSyncedDeviceTabs() .filterNot { it.device.isCurrentDevice || it.tabs.isEmpty() } .maxByOrNull { it.device.lastAccessTime ?: 0 } @@ -106,12 +116,19 @@ class RecentSyncedTabFeature( url = tab.url, iconUrl = tab.iconUrl ) - } ?: return - recordMetrics(syncedTab, lastSyncedTab, syncStartId) - appStore.dispatch( - AppAction.RecentSyncedTabStateChange(RecentSyncedTabState.Success(syncedTab)) - ) - lastSyncedTab = syncedTab + } + + if (syncedTab == null) { + appStore.dispatch( + AppAction.RecentSyncedTabStateChange(RecentSyncedTabState.None) + ) + } else { + recordMetrics(syncedTab, lastSyncedTab, syncStartId) + appStore.dispatch( + AppAction.RecentSyncedTabStateChange(RecentSyncedTabState.Success(syncedTab)) + ) + lastSyncedTab = syncedTab + } } private fun onError() { @@ -131,6 +148,10 @@ class RecentSyncedTabFeature( RecentSyncedTabs.latestSyncedTabIsStale.add() } } + + private fun isSyncedTabsEngineEnabled(): Boolean { + return SyncEnginesStorage(context).getStatus()[SyncEngine.Tabs] ?: true + } } /** diff --git a/app/src/main/java/org/mozilla/fenix/home/recenttabs/view/RecentTabViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/recenttabs/view/RecentTabViewHolder.kt index 531d64f80a..030a59731a 100644 --- a/app/src/main/java/org/mozilla/fenix/home/recenttabs/view/RecentTabViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/recenttabs/view/RecentTabViewHolder.kt @@ -67,16 +67,11 @@ class RecentTabViewHolder( ) recentSyncedTabState.value?.let { - if (components.settings.enableTaskContinuityEnhancements && it != RecentSyncedTabState.None) { + if (components.settings.enableTaskContinuityEnhancements && it is RecentSyncedTabState.Success) { Spacer(modifier = Modifier.height(8.dp)) - val syncedTab = when (it) { - RecentSyncedTabState.None, - RecentSyncedTabState.Loading -> null - is RecentSyncedTabState.Success -> it.tab - } RecentSyncedTab( - tab = syncedTab, + tab = it.tab, onRecentSyncedTabClick = { tab -> recentSyncedTabInteractor.onRecentSyncedTabClicked(tab) }, diff --git a/app/src/test/java/org/mozilla/fenix/home/recentsyncedtabs/RecentSyncedTabFeatureTest.kt b/app/src/test/java/org/mozilla/fenix/home/recentsyncedtabs/RecentSyncedTabFeatureTest.kt index 2c9c1be807..99174dd283 100644 --- a/app/src/test/java/org/mozilla/fenix/home/recentsyncedtabs/RecentSyncedTabFeatureTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/recentsyncedtabs/RecentSyncedTabFeatureTest.kt @@ -9,6 +9,7 @@ import io.mockk.coEvery import io.mockk.coVerify import io.mockk.every import io.mockk.mockk +import io.mockk.mockkConstructor import io.mockk.verify import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.test.StandardTestDispatcher @@ -24,6 +25,7 @@ import mozilla.components.concept.sync.DeviceType import mozilla.components.feature.syncedtabs.storage.SyncedTabsStorage import mozilla.components.service.fxa.SyncEngine import mozilla.components.service.fxa.manager.FxaAccountManager +import mozilla.components.service.fxa.manager.SyncEnginesStorage import mozilla.components.service.fxa.manager.ext.withConstellation import mozilla.components.service.fxa.store.Account import mozilla.components.service.fxa.store.SyncAction @@ -97,8 +99,13 @@ class RecentSyncedTabFeatureTest { Dispatchers.setMain(StandardTestDispatcher()) every { appStore.dispatch(any()) } returns mockk() + mockkConstructor(SyncEnginesStorage::class) + every { anyConstructed().getStatus() } returns mapOf( + SyncEngine.Tabs to true + ) feature = RecentSyncedTabFeature( + context = testContext, appStore = appStore, syncStore = syncStore, accountManager = accountManager, @@ -128,7 +135,7 @@ class RecentSyncedTabFeatureTest { verify { appStore.dispatch(AppAction.RecentSyncedTabStateChange(RecentSyncedTabState.Loading)) } coVerify { accountManager.withConstellation { refreshDevices() } } - coVerify { accountManager.syncNow(reason = SyncReason.User, debounce = true, customEngineSubset = listOf(SyncEngine.Tabs)) } + coVerify { accountManager.syncNow(reason = SyncReason.User, customEngineSubset = listOf(SyncEngine.Tabs)) } } @Test @@ -249,6 +256,34 @@ class RecentSyncedTabFeatureTest { } } + @Test + fun `GIVEN sync tabs are disabled WHEN dispatching recent synced tab THEN dispatch none`() = runTest { + val account = mockk() + syncStore.setState(account = account) + every { appStore.state } returns mockk { + every { recentSyncedTabState } returns RecentSyncedTabState.Loading + } + every { anyConstructed().getStatus() } returns mapOf( + SyncEngine.Tabs to false + ) + + val firstTab = createActiveTab("remote", "https://mozilla.org", null) + val syncedTabs = listOf( + SyncedDeviceTabs(deviceAccessed1, listOf(firstTab)), + ) + coEvery { storage.getSyncedDeviceTabs() } returns syncedTabs + + feature.start() + syncStore.setState(status = SyncStatus.Idle) + runCurrent() + + verify { + appStore.dispatch( + AppAction.RecentSyncedTabStateChange(RecentSyncedTabState.None) + ) + } + } + @Test fun `WHEN synced tab dispatched THEN labeled counter metric recorded with device type`() = runTest { val account = mockk()