for #24665: cache previous auth status and display placeholders accordingly

pull/543/head
MatthewTighe 2 years ago committed by mergify[bot]
parent b746295da1
commit ccb3d33e8b

@ -124,6 +124,8 @@ class BackgroundServices(
}
}
private val accountAuthenticationObserver = AccountAuthenticationObserver(context.settings())
private val telemetryAccountObserver = TelemetryAccountObserver(
context.settings(),
)
@ -163,6 +165,9 @@ class BackgroundServices(
),
crashReporter
).also { accountManager ->
// Register an authentication account observer to cache status
accountManager.register(accountAuthenticationObserver)
// Register a telemetry account observer to keep track of FxA auth metrics.
accountManager.register(telemetryAccountObserver)
@ -196,6 +201,16 @@ class BackgroundServices(
}
}
private class AccountAuthenticationObserver(private val settings: Settings) : AccountObserver {
override fun onAuthenticated(account: OAuthAccount, authType: AuthType) {
settings.hasFxaAuthenticated = true
}
override fun onLoggedOut() {
settings.hasFxaAuthenticated = false
}
}
private class AccountManagerReadyObserver(
private val accountManagerAvailableQueue: RunWhenReadyQueue
) : AccountObserver {

@ -37,6 +37,7 @@ import org.mozilla.fenix.ext.sort
import org.mozilla.fenix.home.PocketUpdatesMiddleware
import org.mozilla.fenix.home.blocklist.BlocklistHandler
import org.mozilla.fenix.home.blocklist.BlocklistMiddleware
import org.mozilla.fenix.home.recentsyncedtabs.RecentSyncedTabState
import org.mozilla.fenix.perf.AppStartReasonProvider
import org.mozilla.fenix.perf.StartupActivityLog
import org.mozilla.fenix.perf.StartupStateProvider
@ -214,6 +215,11 @@ class Components(private val context: Context) {
} else {
emptyList()
},
recentSyncedTabState = if (settings.hasFxaAuthenticated) {
RecentSyncedTabState.Loading
} else {
RecentSyncedTabState.None
},
recentHistory = emptyList()
).run { filterState(blocklistHandler) },
middlewares = listOf(

@ -85,7 +85,10 @@ class RecentSyncedTabFeature(
override fun stopLoading() = Unit
override fun onError(error: SyncedTabsView.ErrorType) {
store.dispatch(AppAction.RecentSyncedTabStateChange(RecentSyncedTabState.None))
val isSyncing = store.state.recentSyncedTabState == RecentSyncedTabState.Loading
if ((!isSyncing && error == SyncedTabsView.ErrorType.NO_TABS_AVAILABLE) || error.isFatal()) {
store.dispatch(AppAction.RecentSyncedTabStateChange(RecentSyncedTabState.None))
}
}
override fun start() {
@ -107,6 +110,19 @@ class RecentSyncedTabFeature(
RecentSyncedTabs.latestSyncedTabIsStale.add()
}
}
// Fatal errors represent any that will force a NONE state for the recent synced tab, such that
// it won't be displayed.
// SYNC_UNAVAILABLE is sent even though displaySyncedTabs is never called when an account
// is not authenticated. NO_TABS_AVAILABLE is only fatal if encountered after a sync is
// completed, and is handled separately above.
private fun SyncedTabsView.ErrorType.isFatal(): Boolean = when (this) {
SyncedTabsView.ErrorType.MULTIPLE_DEVICES_UNAVAILABLE,
SyncedTabsView.ErrorType.SYNC_ENGINE_UNAVAILABLE,
SyncedTabsView.ErrorType.SYNC_NEEDS_REAUTHENTICATION -> true
SyncedTabsView.ErrorType.NO_TABS_AVAILABLE,
SyncedTabsView.ErrorType.SYNC_UNAVAILABLE -> false
}
}
/**

@ -1012,6 +1012,16 @@ class Settings(private val appContext: Context) : PreferencesHolder {
default = true
)
var hasFxaAuthenticated by booleanPreference(
appContext.getPreferenceKey(R.string.pref_key_fxa_has_authenticated),
default = false
)
var lastPlacesStorageMaintenance by longPreference(
appContext.getPreferenceKey(R.string.pref_key_last_maintenance),
default = 0
)
fun addSearchWidgetInstalled(count: Int) {
val key = appContext.getPreferenceKey(R.string.pref_key_search_widget_installed)
val newValue = preferences.getInt(key, 0) + count

@ -85,6 +85,7 @@
<string name="pref_key_sign_out" translatable="false">pref_key_sign_out</string>
<string name="pref_key_sync_sign_in" translatable="false">pref_key_sync_sign_in</string>
<string name="pref_key_push_project_id" translatable="false">project_id</string>
<string name="pref_key_fxa_has_authenticated" translatable="false">pref_key_fxa_has_authenticated</string>
<string name="pref_key_search_widget_installed" translatable="false">pref_key_search_widget_installed</string>
<string name="pref_key_saved_logins_sorting_strategy" translatable="false">pref_key_saved_logins_sorting_strategy</string>
<!-- Key for credit cards sync preference in the account settings fragment -->

@ -175,13 +175,6 @@ class RecentSyncedTabFeatureTest {
}
}
@Test
fun `WHEN error is received THEN action dispatched with empty synced state`() {
feature.onError(SyncedTabsView.ErrorType.NO_TABS_AVAILABLE)
verify { store.dispatch(AppAction.RecentSyncedTabStateChange(RecentSyncedTabState.None)) }
}
@Test
fun `WHEN synced tab displayed THEN labeled counter metric recorded with device type`() {
val tab = SyncedDeviceTabs(deviceAccessed1, listOf(createActiveTab()))
@ -222,6 +215,26 @@ class RecentSyncedTabFeatureTest {
assertFalse(RecentSyncedTabs.latestSyncedTabIsStale.testHasValue())
}
@Test
fun `GIVEN that feature is not loading WHEN no tabs error received THEN dispatches NONE state`() {
every { store.state } returns mockk {
every { recentSyncedTabState } returns RecentSyncedTabState.None
}
feature.onError(SyncedTabsView.ErrorType.NO_TABS_AVAILABLE)
verify { store.dispatch(AppAction.RecentSyncedTabStateChange(RecentSyncedTabState.None)) }
}
@Test
fun `GIVEN that feature is loading WHEN fatal error received THEN dispatches NONE state`() {
every { store.state } returns mockk {
every { recentSyncedTabState } returns RecentSyncedTabState.Loading
}
feature.onError(SyncedTabsView.ErrorType.MULTIPLE_DEVICES_UNAVAILABLE)
verify { store.dispatch(AppAction.RecentSyncedTabStateChange(RecentSyncedTabState.None)) }
}
private fun createActiveTab(
title: String = "title",
url: String = "url",

Loading…
Cancel
Save