1
0
Fork 0

For #1190: Adds telemetry for FxA login

master
Sawyer Blatz 2019-05-22 10:43:23 -07:00
parent 2ad6875f09
commit 62bed0cd06
8 changed files with 184 additions and 1 deletions

View File

@ -370,6 +370,18 @@ metrics:
notification_emails: notification_emails:
- fenix-core@mozilla.com - fenix-core@mozilla.com
expires: "2019-09-01" 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: search.default_engine:
code: code:
@ -732,4 +744,83 @@ error_page:
- https://github.com/mozilla-mobile/fenix/pull/2491#issuecomment-492414486 - https://github.com/mozilla-mobile/fenix/pull/2491#issuecomment-492414486
notification_emails: notification_emails:
- fenix-core@mozilla.com - 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" expires: "2020-03-01"

View File

@ -26,6 +26,10 @@ import kotlinx.coroutines.runBlocking
import org.mozilla.fenix.GleanMetrics.QrScanner import org.mozilla.fenix.GleanMetrics.QrScanner
import org.mozilla.fenix.GleanMetrics.Library import org.mozilla.fenix.GleanMetrics.Library
import org.mozilla.fenix.GleanMetrics.ErrorPage 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<T : Enum<T>>( private class EventWrapper<T : Enum<T>>(
private val recorder: ((Map<T, String>?) -> Unit), private val recorder: ((Map<T, String>?) -> Unit),
@ -188,6 +192,27 @@ private val Event.wrapper
{ ErrorPage.visitedError }, { ErrorPage.visitedError },
{ ErrorPage.visitedErrorKeys.valueOf(it) } { ErrorPage.visitedErrorKeys.valueOf(it) }
) )
is Event.SyncOpened -> EventWrapper<NoExtraKeys>(
{ Sync.opened.record(it) }
)
is Event.SyncClosed -> EventWrapper<NoExtraKeys>(
{ Sync.closed.record(it) }
)
is Event.SyncSignIn -> EventWrapper<NoExtraKeys>(
{ Sync.signIn.record(it) }
)
is Event.SyncScanPairing -> EventWrapper<NoExtraKeys>(
{ Sync.scanPairing.record(it) }
)
is Event.SyncCreateAccount -> EventWrapper<NoExtraKeys>(
{ Sync.createAccount.record(it) }
)
is Event.SyncSyncNow -> EventWrapper<NoExtraKeys>(
{ Sync.syncNow.record(it) }
)
is Event.SyncSignOut -> EventWrapper<NoExtraKeys>(
{ Sync.signOut.record(it) }
)
// Don't track other events with Glean // Don't track other events with Glean
else -> null else -> null
@ -217,6 +242,11 @@ class GleanMetricsService(private val context: Context) : MetricsService {
defaultBrowser.set(Browsers.all(context).isDefaultBrowser) defaultBrowser.set(Browsers.all(context).isDefaultBrowser)
defaultMozBrowser.set(MozillaProductDetector.getMozillaBrowserDefault(context) ?: "") defaultMozBrowser.set(MozillaProductDetector.getMozillaBrowserDefault(context) ?: "")
mozillaProducts.set(MozillaProductDetector.getInstalledMozillaProducts(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 { SearchDefaultEngine.apply {

View File

@ -81,6 +81,13 @@ sealed class Event {
object QRScannerNavigationDenied : Event() object QRScannerNavigationDenied : Event()
object LibraryOpened : Event() object LibraryOpened : Event()
object LibraryClosed : 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() { data class PreferenceToggled(val preferenceKey: String, val enabled: Boolean, val context: Context) : Event() {
private val switchPreferenceTelemetryAllowList = listOf( private val switchPreferenceTelemetryAllowList = listOf(

View File

@ -9,8 +9,11 @@ import android.os.Bundle
import android.text.format.DateUtils import android.text.format.DateUtils
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.preference.CheckBoxPreference
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.forEach
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -24,8 +27,10 @@ import mozilla.components.service.fxa.FxaPanicException
import mozilla.components.service.fxa.manager.FxaAccountManager import mozilla.components.service.fxa.manager.FxaAccountManager
import mozilla.components.support.base.log.logger.Logger import mozilla.components.support.base.log.logger.Logger
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.getPreferenceKey import org.mozilla.fenix.ext.getPreferenceKey
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.utils.Settings
import java.lang.Exception import java.lang.Exception
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -92,6 +97,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope {
private fun getClickListenerForSignOut(): Preference.OnPreferenceClickListener { private fun getClickListenerForSignOut(): Preference.OnPreferenceClickListener {
return Preference.OnPreferenceClickListener { return Preference.OnPreferenceClickListener {
requireComponents.analytics.metrics.track(Event.SyncSignOut)
launch { launch {
accountManager.logoutAsync().await() accountManager.logoutAsync().await()
Navigation.findNavController(view!!).popBackStack() Navigation.findNavController(view!!).popBackStack()
@ -103,6 +109,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope {
private fun getClickListenerForSyncNow(): Preference.OnPreferenceClickListener { private fun getClickListenerForSyncNow(): Preference.OnPreferenceClickListener {
return Preference.OnPreferenceClickListener { return Preference.OnPreferenceClickListener {
// Trigger a sync. // Trigger a sync.
requireComponents.analytics.metrics.track(Event.SyncSyncNow)
requireComponents.backgroundServices.syncManager.syncNow() requireComponents.backgroundServices.syncManager.syncNow()
// Poll for device events. // Poll for device events.
launch { launch {
@ -146,6 +153,8 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope {
view?.announceForAccessibility(getString(R.string.sync_syncing)) view?.announceForAccessibility(getString(R.string.sync_syncing))
pref?.title = getString(R.string.sync_syncing) pref?.title = getString(R.string.sync_syncing)
pref?.isEnabled = false pref?.isEnabled = false
updateSyncingItemsPreference()
} }
} }
@ -174,6 +183,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope {
} }
} }
private val deviceConstellationObserver = object : DeviceConstellationObserver { private val deviceConstellationObserver = object : DeviceConstellationObserver {
override fun onDevicesUpdate(constellation: ConstellationState) { override fun onDevicesUpdate(constellation: ConstellationState) {
val deviceNameKey = context!!.getPreferenceKey(R.string.pref_key_sync_device_name) 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<Preference>(syncCategory) as PreferenceCategory
val stringSet = mutableSetOf<String>()
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) { fun updateLastSyncedTimePref(context: Context, pref: Preference, failed: Boolean = false) {
val lastSyncTime = getLastSynced(context) val lastSyncTime = getLastSynced(context)

View File

@ -203,6 +203,7 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
private fun getClickListenerForSignIn(): OnPreferenceClickListener { private fun getClickListenerForSignIn(): OnPreferenceClickListener {
return OnPreferenceClickListener { return OnPreferenceClickListener {
requireComponents.analytics.metrics.track(Event.SyncOpened)
val directions = SettingsFragmentDirections.actionSettingsFragmentToTurnOnSyncFragment() val directions = SettingsFragmentDirections.actionSettingsFragmentToTurnOnSyncFragment()
Navigation.findNavController(view!!).navigate(directions) Navigation.findNavController(view!!).navigate(directions)
true true

View File

@ -12,11 +12,22 @@ import androidx.preference.PreferenceFragmentCompat
import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.getPreferenceKey import org.mozilla.fenix.ext.getPreferenceKey
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
class TurnOnSyncFragment : PreferenceFragmentCompat() { 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() { override fun onResume() {
super.onResume() super.onResume()
(activity as AppCompatActivity).title = getString(R.string.preferences_sync) (activity as AppCompatActivity).title = getString(R.string.preferences_sync)
@ -33,7 +44,7 @@ class TurnOnSyncFragment : PreferenceFragmentCompat() {
val preferencePairSignIn = val preferencePairSignIn =
findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_pair)) findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_pair))
preferenceSignIn?.onPreferenceClickListener = getClickListenerForSignIn() preferenceSignIn?.onPreferenceClickListener = getClickListenerForSignIn()
preferenceNewAccount?.onPreferenceClickListener = getClickListenerForSignIn() preferenceNewAccount?.onPreferenceClickListener = getClickListenerForCreateAccount()
preferencePairSignIn?.onPreferenceClickListener = getClickListenerForPairing() preferencePairSignIn?.onPreferenceClickListener = getClickListenerForPairing()
} }
@ -45,6 +56,19 @@ class TurnOnSyncFragment : PreferenceFragmentCompat() {
// session history stack. // session history stack.
// We could auto-close this tab once we get to the end of the authentication process? // We could auto-close this tab once we get to the end of the authentication process?
// Via an interceptor, perhaps. // 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 { view?.let {
(activity as HomeActivity).openToBrowser(BrowserDirection.FromTurnOnSync) (activity as HomeActivity).openToBrowser(BrowserDirection.FromTurnOnSync)
} }
@ -56,6 +80,7 @@ class TurnOnSyncFragment : PreferenceFragmentCompat() {
return Preference.OnPreferenceClickListener { return Preference.OnPreferenceClickListener {
val directions = TurnOnSyncFragmentDirections.actionTurnOnSyncFragmentToPairInstructionsFragment() val directions = TurnOnSyncFragmentDirections.actionTurnOnSyncFragmentToPairInstructionsFragment()
Navigation.findNavController(view!!).navigate(directions) Navigation.findNavController(view!!).navigate(directions)
requireComponents.analytics.metrics.track(Event.SyncScanPairing)
true true
} }

View File

@ -44,6 +44,7 @@
<string name="pref_key_sync_pair" translatable="false">pref_key_sync_pair</string> <string name="pref_key_sync_pair" translatable="false">pref_key_sync_pair</string>
<string name="pref_key_sync_sign_in" translatable="false">pref_key_sync_sign_in</string> <string name="pref_key_sync_sign_in" translatable="false">pref_key_sync_sign_in</string>
<string name="pref_key_sync_create_account" translatable="false">pref_key_sync_create_account</string> <string name="pref_key_sync_create_account" translatable="false">pref_key_sync_create_account</string>
<string name="pref_key_sync_syncing_items" translatable="false">pref_key_sync_syncing_items</string>
<!-- Search Settings --> <!-- Search Settings -->
<string name="pref_key_show_search_suggestions" translatable="false">pref_key_show_search_suggestions</string> <string name="pref_key_show_search_suggestions" translatable="false">pref_key_show_search_suggestions</string>

View File

@ -9,6 +9,7 @@
android:title="@string/preferences_sync_now" /> android:title="@string/preferences_sync_now" />
<PreferenceCategory <PreferenceCategory
android:key="@string/preferences_sync_category"
android:title="@string/preferences_sync_category"> android:title="@string/preferences_sync_category">
<CheckBoxPreference <CheckBoxPreference