For #1190: Adds telemetry for FxA login
parent
2ad6875f09
commit
62bed0cd06
|
@ -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"
|
|
@ -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 {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue