diff --git a/app/metrics.yaml b/app/metrics.yaml index 81ec80ee3..b58088a2f 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -5394,3 +5394,53 @@ set_default_setting_experiment: notification_emails: - fenix-core@mozilla.com expires: "2021-10-01" + +credit_cards: + manual_save: + type: counter + description: | + A counter of the number of credit cards that have been saved + manually by the user. + send_in_pings: + - metrics + bugs: + - https://github.com/mozilla-mobile/fenix/issues/18711 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/19548#issuecomment-848811030 + data_sensitivity: + - interaction + notification_emails: + - fenix-core@mozilla.com + expires: "2021-10-01" + delete_card: + type: counter + description: | + A counter of the number of credit cards that have been deleted by + the user. + send_in_pings: + - metrics + bugs: + - https://github.com/mozilla-mobile/fenix/issues/18711 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/19548#issuecomment-848811030 + data_sensitivity: + - interaction + notification_emails: + - fenix-core@mozilla.com + expires: "2021-10-01" + autofill_card: + type: counter + description: | + A counter of the number of times the user has autofilled + a credit card. + send_in_pings: + - metrics + bugs: + - https://github.com/mozilla-mobile/fenix/issues/18711 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/19548#issuecomment-848811030 + data_sensitivity: + - interaction + notification_emails: + - fenix-core@mozilla.com + expires: "2021-10-01" diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt index aff2f88d8..69be9083c 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt @@ -236,6 +236,11 @@ sealed class Event { object HomeMenuSettingsItemClicked : Event() object HomeScreenDisplayed : Event() + // Credit cards + object CreditCardManualSave : Event() + object CreditCardDelete : Event() + object CreditCardAutofill : Event() + // Interaction events with extras data class TopSiteSwipeCarousel(val page: Int) : Event() { 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 74f49ccfa..0da296449 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 @@ -22,6 +22,7 @@ import org.mozilla.fenix.GleanMetrics.ContextMenu import org.mozilla.fenix.GleanMetrics.ContextualHintTrackingProtection import org.mozilla.fenix.GleanMetrics.ContextualMenu import org.mozilla.fenix.GleanMetrics.CrashReporter +import org.mozilla.fenix.GleanMetrics.CreditCards import org.mozilla.fenix.GleanMetrics.CustomTab import org.mozilla.fenix.GleanMetrics.DownloadNotification import org.mozilla.fenix.GleanMetrics.DownloadsMisc @@ -833,6 +834,17 @@ private val Event.wrapper: EventWrapper<*>? { HomeScreen.homeScreenDisplayed.record(it) } ) + // Credit cards + is Event.CreditCardManualSave -> EventWrapper( + { CreditCards.manualSave.add(1) } + ) + is Event.CreditCardDelete -> EventWrapper( + { CreditCards.deleteCard.add(1) } + ) + is Event.CreditCardAutofill -> EventWrapper( + { CreditCards.autofillCard.add(1) } + ) + // Don't record other events in Glean: is Event.AddBookmark -> null is Event.OpenedAppFirstRun -> null diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt index 3fb56ad58..924040b52 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt @@ -21,6 +21,7 @@ import mozilla.components.feature.downloads.facts.DownloadsFacts import mozilla.components.feature.findinpage.facts.FindInPageFacts import mozilla.components.feature.media.facts.MediaFacts import mozilla.components.feature.prompts.facts.LoginDialogFacts +import mozilla.components.feature.prompts.facts.CreditCardAutofillDialogFacts import mozilla.components.feature.pwa.ProgressiveWebAppFacts import mozilla.components.feature.syncedtabs.facts.SyncedTabsFacts import mozilla.components.feature.top.sites.facts.TopSitesFacts @@ -161,6 +162,8 @@ internal class ReleaseMetricController( Component.FEATURE_PROMPTS to LoginDialogFacts.Items.CANCEL -> Event.LoginDialogPromptCancelled Component.FEATURE_PROMPTS to LoginDialogFacts.Items.NEVER_SAVE -> Event.LoginDialogPromptNeverSave Component.FEATURE_PROMPTS to LoginDialogFacts.Items.SAVE -> Event.LoginDialogPromptSave + Component.FEATURE_PROMPTS to CreditCardAutofillDialogFacts.Items.AUTOFILL_CREDIT_CARD_SUCCESS -> + Event.CreditCardAutofill Component.FEATURE_FINDINPAGE to FindInPageFacts.Items.CLOSE -> Event.FindInPageClosed Component.FEATURE_FINDINPAGE to FindInPageFacts.Items.INPUT -> Event.FindInPageSearchCommitted diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt index f9571b32b..c1f972638 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt @@ -55,6 +55,7 @@ class CreditCardEditorFragment : SecureFragment(R.layout.fragment_credit_card_ed val storage = requireContext().components.core.autofillStorage interactor = DefaultCreditCardEditorInteractor( controller = DefaultCreditCardEditorController( + context = requireContext(), storage = storage, lifecycleScope = lifecycleScope, navController = findNavController() diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardEditorController.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardEditorController.kt index 18fae576e..7296f952c 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardEditorController.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardEditorController.kt @@ -4,6 +4,7 @@ package org.mozilla.fenix.settings.creditcards.controller +import android.content.Context import androidx.navigation.NavController import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope @@ -12,8 +13,10 @@ import kotlinx.coroutines.launch import mozilla.components.concept.storage.NewCreditCardFields import mozilla.components.concept.storage.UpdatableCreditCardFields import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage +import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment import org.mozilla.fenix.settings.creditcards.interactor.CreditCardEditorInteractor +import org.mozilla.fenix.ext.components /** * [CreditCardEditorFragment] controller. An interface that handles the view manipulation of the @@ -52,12 +55,15 @@ interface CreditCardEditorController { * @param ioDispatcher [CoroutineDispatcher] used for executing async tasks. Defaults to [Dispatchers.IO]. */ class DefaultCreditCardEditorController( + context: Context, private val storage: AutofillCreditCardsAddressesStorage, private val lifecycleScope: CoroutineScope, private val navController: NavController, private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO ) : CreditCardEditorController { + private val metrics = context.components.analytics.metrics + override fun handleCancelButtonClicked() { navController.popBackStack() } @@ -65,6 +71,7 @@ class DefaultCreditCardEditorController( override fun handleDeleteCreditCard(guid: String) { lifecycleScope.launch(ioDispatcher) { storage.deleteCreditCard(guid) + metrics.track(Event.CreditCardDelete) lifecycleScope.launch(Dispatchers.Main) { navController.popBackStack() @@ -75,6 +82,7 @@ class DefaultCreditCardEditorController( override fun handleSaveCreditCard(creditCardFields: NewCreditCardFields) { lifecycleScope.launch(ioDispatcher) { storage.addCreditCard(creditCardFields) + metrics.track(Event.CreditCardManualSave) lifecycleScope.launch(Dispatchers.Main) { navController.popBackStack() diff --git a/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorControllerTest.kt b/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorControllerTest.kt index f9429242f..2b76ab8b7 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorControllerTest.kt @@ -4,8 +4,10 @@ package org.mozilla.fenix.settings.creditcards +import android.content.Context import androidx.navigation.NavController import io.mockk.coVerify +import io.mockk.every import io.mockk.mockk import io.mockk.spyk import io.mockk.verify @@ -23,9 +25,15 @@ import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.components.metrics.MetricController +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.settings.creditcards.controller.DefaultCreditCardEditorController @ExperimentalCoroutinesApi +@RunWith(FenixRobolectricTestRunner::class) class DefaultCreditCardEditorControllerTest { private val storage: AutofillCreditCardsAddressesStorage = mockk(relaxed = true) @@ -35,14 +43,22 @@ class DefaultCreditCardEditorControllerTest { private val testDispatcher = TestCoroutineDispatcher() private lateinit var controller: DefaultCreditCardEditorController + private lateinit var context: Context + private lateinit var metrics: MetricController @get:Rule val coroutinesTestRule = MainCoroutineRule(testDispatcher) @Before fun setup() { + metrics = mockk() + context = mockk() + every { metrics.track(any()) } returns Unit + every { context.components.analytics.metrics } returns metrics + controller = spyk( DefaultCreditCardEditorController( + context = context, storage = storage, lifecycleScope = testCoroutineScope, navController = navController, @@ -75,6 +91,7 @@ class DefaultCreditCardEditorControllerTest { coVerify { storage.deleteCreditCard(creditCardId) navController.popBackStack() + metrics.track(Event.CreditCardDelete) } } @@ -94,6 +111,7 @@ class DefaultCreditCardEditorControllerTest { coVerify { storage.addCreditCard(creditCardFields) navController.popBackStack() + metrics.track(Event.CreditCardManualSave) } }