From a4097cd380c471576bf8e5090f48b94ec3556526 Mon Sep 17 00:00:00 2001 From: Grisha Kruglov Date: Thu, 22 Aug 2019 16:56:13 -0700 Subject: [PATCH] FxA WebChannels integration This patch includes: - WebChannels support enabled by default, with ability to disable it via remote flag - expanded FxA telemetry (closes #4971) Co-authored-by: Arturo Mejia --- .../java/org/mozilla/fenix/HomeActivity.kt | 3 +- .../fenix/browser/BaseBrowserFragment.kt | 4 +- .../fenix/components/BackgroundServices.kt | 6 +-- .../account/AccountSettingsFragment.kt | 54 +++++++++++++++++-- .../res/xml/account_settings_preferences.xml | 2 - buildSrc/src/main/java/Dependencies.kt | 2 +- 6 files changed, 58 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index f3c2d3498..18cfc4cdb 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -25,6 +25,7 @@ import mozilla.components.browser.search.SearchEngine import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager import mozilla.components.concept.engine.EngineView +import mozilla.components.service.fxa.sync.SyncReason import mozilla.components.support.base.feature.BackHandler import mozilla.components.support.ktx.kotlin.isUrl import mozilla.components.support.ktx.kotlin.toNormalizedUrl @@ -112,7 +113,7 @@ open class HomeActivity : AppCompatActivity() { accountManager.initAsync().await() // If we're authenticated, kick-off a sync and a device state refresh. accountManager.authenticatedAccount()?.let { - accountManager.syncNowAsync(startup = true, debounce = true) + accountManager.syncNowAsync(SyncReason.Startup, debounce = true) it.deviceConstellation().pollForEventsAsync().await() } } diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index 3629189b9..cc350eec0 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -31,6 +31,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager +import mozilla.components.feature.accounts.FxaCapability import mozilla.components.feature.accounts.FxaWebChannelFeature import mozilla.components.feature.app.links.AppLinksFeature import mozilla.components.feature.contextmenu.ContextMenuFeature @@ -380,7 +381,8 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler, SessionManager.Obs customTabSessionId, requireComponents.core.engine, requireComponents.core.sessionManager, - requireComponents.backgroundServices.accountManager + requireComponents.backgroundServices.accountManager, + setOf(FxaCapability.CHOOSE_WHAT_TO_SYNC) ), owner = this, view = view diff --git a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt index 106f4e008..6249cf1e2 100644 --- a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt +++ b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt @@ -94,7 +94,7 @@ class BackgroundServices( val syncConfig = if (context.isInExperiment(Experiments.asFeatureSyncDisabled)) { null } else { - SyncConfig(setOf(SyncEngine.HISTORY, SyncEngine.BOOKMARKS), syncPeriodInMinutes = 240L) // four hours + SyncConfig(setOf(SyncEngine.History, SyncEngine.Bookmarks), syncPeriodInMinutes = 240L) // four hours } private val pushService by lazy { FirebasePush() } @@ -103,8 +103,8 @@ class BackgroundServices( init { // Make the "history" and "bookmark" stores accessible to workers spawned by the sync manager. - GlobalSyncableStoreProvider.configureStore(SyncEngine.HISTORY to historyStorage) - GlobalSyncableStoreProvider.configureStore(SyncEngine.BOOKMARKS to bookmarkStorage) + GlobalSyncableStoreProvider.configureStore(SyncEngine.History to historyStorage) + GlobalSyncableStoreProvider.configureStore(SyncEngine.Bookmarks to bookmarkStorage) } private val deviceEventObserver = object : DeviceEventsObserver { diff --git a/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt index 1b12f4574..301e1ae34 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt @@ -11,6 +11,7 @@ import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController +import androidx.preference.CheckBoxPreference import androidx.preference.EditTextPreference import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat @@ -22,13 +23,17 @@ import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.ConstellationState import mozilla.components.concept.sync.DeviceConstellationObserver import mozilla.components.lib.state.ext.consumeFrom +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.sync.SyncReason import mozilla.components.service.fxa.sync.SyncStatusObserver import mozilla.components.service.fxa.sync.getLastSynced import org.mozilla.fenix.R import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.StoreProvider import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.getPreferenceKey import org.mozilla.fenix.ext.requireComponents @@ -147,6 +152,27 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { } } + // Make sure out sync engine checkboxes are up-to-date. + updateSyncEngineStates() + + val historyNameKey = getPreferenceKey(R.string.pref_key_sync_history) + findPreference(historyNameKey)?.apply { + setOnPreferenceChangeListener { _, newValue -> + SyncEnginesStorage(context).setStatus(SyncEngine.History, newValue as Boolean) + context.components.backgroundServices.accountManager.syncNowAsync(SyncReason.EngineChange) + true + } + } + + val bookmarksNameKey = getPreferenceKey(R.string.pref_key_sync_bookmarks) + findPreference(bookmarksNameKey)?.apply { + setOnPreferenceChangeListener { _, newValue -> + SyncEnginesStorage(context).setStatus(SyncEngine.Bookmarks, newValue as Boolean) + context.components.backgroundServices.accountManager.syncNowAsync(SyncReason.EngineChange) + true + } + } + deviceConstellation?.registerDeviceObserver(deviceConstellationObserver, owner = this, autoPause = true) // NB: ObserverRegistry will take care of cleaning up internal references to 'observer' and @@ -156,11 +182,25 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { ) } + private fun updateSyncEngineStates() { + val syncEnginesStatus = SyncEnginesStorage(context!!).getStatus() + val bookmarksNameKey = getPreferenceKey(R.string.pref_key_sync_bookmarks) + findPreference(bookmarksNameKey)?.apply { + isEnabled = syncEnginesStatus.containsKey(SyncEngine.Bookmarks) + isChecked = syncEnginesStatus.getOrElse(SyncEngine.Bookmarks) { true } + } + val historyNameKey = getPreferenceKey(R.string.pref_key_sync_history) + findPreference(historyNameKey)?.apply { + isEnabled = syncEnginesStatus.containsKey(SyncEngine.History) + isChecked = syncEnginesStatus.getOrElse(SyncEngine.History) { true } + } + } + private fun syncNow() { lifecycleScope.launch { requireComponents.analytics.metrics.track(Event.SyncAccountSyncNow) // Trigger a sync. - requireComponents.backgroundServices.accountManager.syncNowAsync().await() + requireComponents.backgroundServices.accountManager.syncNowAsync(SyncReason.User).await() // Poll for device events & update devices. accountManager.authenticatedAccount() ?.deviceConstellation()?.run { @@ -176,10 +216,12 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { } // This may fail, and we'll have a disparity in the UI until `updateDeviceName` is called. lifecycleScope.launch(Main) { - accountManager.authenticatedAccount() - ?.deviceConstellation() - ?.setDeviceNameAsync(newValue) - ?.await() + context?.let { + accountManager.authenticatedAccount() + ?.deviceConstellation() + ?.setDeviceNameAsync(newValue, it) + ?.await() + } } return true } @@ -229,6 +271,8 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { val time = getLastSynced(requireContext()) accountSettingsStore.dispatch(AccountSettingsFragmentAction.SyncEnded(time)) } + // Make sure out sync engine checkboxes are up-to-date. + updateSyncEngineStates() } } diff --git a/app/src/main/res/xml/account_settings_preferences.xml b/app/src/main/res/xml/account_settings_preferences.xml index 13f329b0e..808b28283 100644 --- a/app/src/main/res/xml/account_settings_preferences.xml +++ b/app/src/main/res/xml/account_settings_preferences.xml @@ -15,13 +15,11 @@