From 62bed0cd06d1a0336beabff3b5900ee0b6ebdf17 Mon Sep 17 00:00:00 2001 From: Sawyer Blatz Date: Wed, 22 May 2019 10:43:23 -0700 Subject: [PATCH] For #1190: Adds telemetry for FxA login --- app/metrics.yaml | 91 +++++++++++++++++++ .../components/metrics/GleanMetricsService.kt | 30 ++++++ .../fenix/components/metrics/Metrics.kt | 7 ++ .../fenix/settings/AccountSettingsFragment.kt | 27 ++++++ .../fenix/settings/SettingsFragment.kt | 1 + .../fenix/settings/TurnOnSyncFragment.kt | 27 +++++- app/src/main/res/values/preference_keys.xml | 1 + .../res/xml/account_settings_preferences.xml | 1 + 8 files changed, 184 insertions(+), 1 deletion(-) diff --git a/app/metrics.yaml b/app/metrics.yaml index a62e10ac6..8c4bd8c76 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -370,6 +370,18 @@ metrics: notification_emails: - fenix-core@mozilla.com expires: "2019-09-01" + syncing_items: + type: string_list + description: > + The preference keys for the switch preferences the user has enabled to sync with FxA. We currently track: + Bookmarks and History. + bugs: + - 1190 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-03-01" search.default_engine: code: @@ -732,4 +744,83 @@ error_page: - https://github.com/mozilla-mobile/fenix/pull/2491#issuecomment-492414486 notification_emails: - fenix-core@mozilla.com + expires: "2020-03-01" + +sync: + opened: + type: event + description: > + A user opened the sync page + bugs: + - 1190 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-03-01" + closed: + type: event + description: > + A user closed the sync page + bugs: + - 1190 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-03-01" + sign_in: + type: event + description: > + A user pressed the sign in button on the sync page + bugs: + - 1190 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-03-01" + scan_pairing: + type: event + description: > + A user pressed the scan pairing button on the sync page + bugs: + - 1190 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-03-01" + create_account: + type: event + description: > + A user pressed the create account button on the sync page + bugs: + - 1190 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-03-01" + sync_now: + type: event + description: > + A user pressed the sync now button on the sync page + bugs: + - 1190 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-03-01" + sign_out: + type: event + description: > + A user pressed the sign out button on the sync page + bugs: + - 1190 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 + notification_emails: + - fenix-core@mozilla.com expires: "2020-03-01" \ No newline at end of file diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt index 958367ed8..61ea64d41 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt @@ -26,6 +26,10 @@ import kotlinx.coroutines.runBlocking import org.mozilla.fenix.GleanMetrics.QrScanner import org.mozilla.fenix.GleanMetrics.Library import org.mozilla.fenix.GleanMetrics.ErrorPage +import org.mozilla.fenix.GleanMetrics.Sync +import org.mozilla.fenix.R +import org.mozilla.fenix.ext.getPreferenceKey +import org.mozilla.fenix.utils.Settings private class EventWrapper>( private val recorder: ((Map?) -> Unit), @@ -188,6 +192,27 @@ private val Event.wrapper { ErrorPage.visitedError }, { ErrorPage.visitedErrorKeys.valueOf(it) } ) + is Event.SyncOpened -> EventWrapper( + { Sync.opened.record(it) } + ) + is Event.SyncClosed -> EventWrapper( + { Sync.closed.record(it) } + ) + is Event.SyncSignIn -> EventWrapper( + { Sync.signIn.record(it) } + ) + is Event.SyncScanPairing -> EventWrapper( + { Sync.scanPairing.record(it) } + ) + is Event.SyncCreateAccount -> EventWrapper( + { Sync.createAccount.record(it) } + ) + is Event.SyncSyncNow -> EventWrapper( + { Sync.syncNow.record(it) } + ) + is Event.SyncSignOut -> EventWrapper( + { Sync.signOut.record(it) } + ) // Don't track other events with Glean else -> null @@ -217,6 +242,11 @@ class GleanMetricsService(private val context: Context) : MetricsService { defaultBrowser.set(Browsers.all(context).isDefaultBrowser) defaultMozBrowser.set(MozillaProductDetector.getMozillaBrowserDefault(context) ?: "") mozillaProducts.set(MozillaProductDetector.getInstalledMozillaProducts(context)) + + val syncItemsKey = context.getPreferenceKey(R.string.pref_key_sync_syncing_items) + Settings.getInstance(context).preferences.getStringSet(syncItemsKey, setOf())?.toList()?.let { + syncingItems.set(it) + } } SearchDefaultEngine.apply { diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt index c25f72d4b..b8cce0640 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt @@ -81,6 +81,13 @@ sealed class Event { object QRScannerNavigationDenied : Event() object LibraryOpened : Event() object LibraryClosed : Event() + object SyncOpened : Event() + object SyncClosed : Event() + object SyncSignIn : Event() + object SyncScanPairing : Event() + object SyncCreateAccount : Event() + object SyncSyncNow : Event() + object SyncSignOut : Event() data class PreferenceToggled(val preferenceKey: String, val enabled: Boolean, val context: Context) : Event() { private val switchPreferenceTelemetryAllowList = listOf( diff --git a/app/src/main/java/org/mozilla/fenix/settings/AccountSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/AccountSettingsFragment.kt index 07e25667b..28c40171a 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/AccountSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/AccountSettingsFragment.kt @@ -9,8 +9,11 @@ import android.os.Bundle import android.text.format.DateUtils import androidx.appcompat.app.AppCompatActivity import androidx.navigation.Navigation +import androidx.preference.CheckBoxPreference import androidx.preference.Preference +import androidx.preference.PreferenceCategory import androidx.preference.PreferenceFragmentCompat +import androidx.preference.forEach import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -24,8 +27,10 @@ import mozilla.components.service.fxa.FxaPanicException import mozilla.components.service.fxa.manager.FxaAccountManager import mozilla.components.support.base.log.logger.Logger import org.mozilla.fenix.R +import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.ext.getPreferenceKey import org.mozilla.fenix.ext.requireComponents +import org.mozilla.fenix.utils.Settings import java.lang.Exception import kotlin.coroutines.CoroutineContext @@ -92,6 +97,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { private fun getClickListenerForSignOut(): Preference.OnPreferenceClickListener { return Preference.OnPreferenceClickListener { + requireComponents.analytics.metrics.track(Event.SyncSignOut) launch { accountManager.logoutAsync().await() Navigation.findNavController(view!!).popBackStack() @@ -103,6 +109,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { private fun getClickListenerForSyncNow(): Preference.OnPreferenceClickListener { return Preference.OnPreferenceClickListener { // Trigger a sync. + requireComponents.analytics.metrics.track(Event.SyncSyncNow) requireComponents.backgroundServices.syncManager.syncNow() // Poll for device events. launch { @@ -146,6 +153,8 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { view?.announceForAccessibility(getString(R.string.sync_syncing)) pref?.title = getString(R.string.sync_syncing) pref?.isEnabled = false + + updateSyncingItemsPreference() } } @@ -174,6 +183,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { } } + private val deviceConstellationObserver = object : DeviceConstellationObserver { override fun onDevicesUpdate(constellation: ConstellationState) { val deviceNameKey = context!!.getPreferenceKey(R.string.pref_key_sync_device_name) @@ -182,6 +192,23 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { } } + private fun updateSyncingItemsPreference() { + val syncCategory = context!!.getPreferenceKey(R.string.preferences_sync_category) + val preferencesSyncCategory = findPreference(syncCategory) as PreferenceCategory + val stringSet = mutableSetOf() + + preferencesSyncCategory.forEach { + (it as CheckBoxPreference).let { checkboxPreference -> + if (checkboxPreference.isChecked) { + stringSet.add(checkboxPreference.key) + } + } + } + + Settings.getInstance(context!!).preferences.edit() + .putStringSet(context!!.getPreferenceKey(R.string.pref_key_sync_syncing_items), stringSet).apply() + } + fun updateLastSyncedTimePref(context: Context, pref: Preference, failed: Boolean = false) { val lastSyncTime = getLastSynced(context) diff --git a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt index 24e61d204..c78d03045 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -203,6 +203,7 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse private fun getClickListenerForSignIn(): OnPreferenceClickListener { return OnPreferenceClickListener { + requireComponents.analytics.metrics.track(Event.SyncOpened) val directions = SettingsFragmentDirections.actionSettingsFragmentToTurnOnSyncFragment() Navigation.findNavController(view!!).navigate(directions) true diff --git a/app/src/main/java/org/mozilla/fenix/settings/TurnOnSyncFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/TurnOnSyncFragment.kt index 24fb0e426..80e5b4a1c 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/TurnOnSyncFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/TurnOnSyncFragment.kt @@ -12,11 +12,22 @@ import androidx.preference.PreferenceFragmentCompat import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R +import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.ext.getPreferenceKey import org.mozilla.fenix.ext.requireComponents class TurnOnSyncFragment : PreferenceFragmentCompat() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + requireComponents.analytics.metrics.track(Event.SyncOpened) + } + + override fun onDestroy() { + super.onDestroy() + requireComponents.analytics.metrics.track(Event.SyncClosed) + } + override fun onResume() { super.onResume() (activity as AppCompatActivity).title = getString(R.string.preferences_sync) @@ -33,7 +44,7 @@ class TurnOnSyncFragment : PreferenceFragmentCompat() { val preferencePairSignIn = findPreference(context!!.getPreferenceKey(R.string.pref_key_sync_pair)) preferenceSignIn?.onPreferenceClickListener = getClickListenerForSignIn() - preferenceNewAccount?.onPreferenceClickListener = getClickListenerForSignIn() + preferenceNewAccount?.onPreferenceClickListener = getClickListenerForCreateAccount() preferencePairSignIn?.onPreferenceClickListener = getClickListenerForPairing() } @@ -45,6 +56,19 @@ class TurnOnSyncFragment : PreferenceFragmentCompat() { // session history stack. // We could auto-close this tab once we get to the end of the authentication process? // Via an interceptor, perhaps. + requireComponents.analytics.metrics.track(Event.SyncSignIn) + view?.let { + (activity as HomeActivity).openToBrowser(BrowserDirection.FromTurnOnSync) + } + true + } + } + + private fun getClickListenerForCreateAccount(): Preference.OnPreferenceClickListener { + // Currently the same as sign in, as FxA handles this, however we want to emit a different telemetry event + return Preference.OnPreferenceClickListener { + requireComponents.services.accountsAuthFeature.beginAuthentication() + requireComponents.analytics.metrics.track(Event.SyncCreateAccount) view?.let { (activity as HomeActivity).openToBrowser(BrowserDirection.FromTurnOnSync) } @@ -56,6 +80,7 @@ class TurnOnSyncFragment : PreferenceFragmentCompat() { return Preference.OnPreferenceClickListener { val directions = TurnOnSyncFragmentDirections.actionTurnOnSyncFragmentToPairInstructionsFragment() Navigation.findNavController(view!!).navigate(directions) + requireComponents.analytics.metrics.track(Event.SyncScanPairing) true } diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index 0bf8b9995..dda5e7f4d 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -44,6 +44,7 @@ pref_key_sync_pair pref_key_sync_sign_in pref_key_sync_create_account + pref_key_sync_syncing_items pref_key_show_search_suggestions diff --git a/app/src/main/res/xml/account_settings_preferences.xml b/app/src/main/res/xml/account_settings_preferences.xml index 419c58045..c9255ce29 100644 --- a/app/src/main/res/xml/account_settings_preferences.xml +++ b/app/src/main/res/xml/account_settings_preferences.xml @@ -9,6 +9,7 @@ android:title="@string/preferences_sync_now" />