diff --git a/app/metrics.yaml b/app/metrics.yaml index 065588a02..002b4108a 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -5712,6 +5712,155 @@ awesomebar: - android-probes@mozilla.com expires: "2022-02-01" +android_autofill: + supported: + type: boolean + description: | + Whether or not Android Autofill is supported by the device and is + supported for this user. + bugs: + - https://github.com/mozilla-mobile/android-components/issues/10301 + data_reviews: + - TBD + data_sensitivity: + - technical + notification_emails: + - android-probes@mozilla.com + - skaspari@mozilla.com + expires: "2022-01-31" + enabled: + type: boolean + description: | + Whether or not Firefox is the Android Autofill provider for this user. + provider. + bugs: + - https://github.com/mozilla-mobile/android-components/issues/10301 + data_reviews: + - TBD + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + - skaspari@mozilla.com + expires: "2022-01-31" + request_matching_logins: + type: event + description: | + The app received an Android Autofill request from the system and was + able to find matching logins for the request + bugs: + - https://github.com/mozilla-mobile/android-components/issues/10301 + data_reviews: + - TBD + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + - skaspari@mozilla.com + expires: "2022-01-31" + request_no_matching_logins: + type: event + description: | + The app received an Android Autofill request from the system and was + not able to find matching logins for the request + bugs: + - https://github.com/mozilla-mobile/android-components/issues/10301 + data_reviews: + - TBD + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + - skaspari@mozilla.com + expires: "2022-01-31" + search_displayed: + type: event + description: | + The user has selected the search option to manually search a + matching login + bugs: + - https://github.com/mozilla-mobile/android-components/issues/10301 + data_reviews: + - TBD + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + - skaspari@mozilla.com + expires: "2022-01-31" + search_item_selected: + type: event + description: | + The user has selected a search result for autofilling. + bugs: + - https://github.com/mozilla-mobile/android-components/issues/10301 + data_reviews: + - TBD + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + - skaspari@mozilla.com + expires: "2022-01-31" + unlock_cancelled: + type: event + description: | + The user needed to unlock the app in order to autofill + logins, but the process was cancelled. + bugs: + - https://github.com/mozilla-mobile/android-components/issues/10301 + data_reviews: + - TBD + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + - skaspari@mozilla.com + expires: "2022-01-31" + unlock_successful: + type: event + description: | + The user successfully unlock the app in order to autofill logins + bugs: + - https://github.com/mozilla-mobile/android-components/issues/10301 + data_reviews: + - TBD + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + - skaspari@mozilla.com + expires: "2022-01-31" + confirm_cancelled: + type: event + description: | + The user needed to confirm autofilling an unauthenticated + application and decided to cancel + bugs: + - https://github.com/mozilla-mobile/android-components/issues/10301 + data_reviews: + - TBD + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + - skaspari@mozilla.com + expires: "2022-01-31" + confirm_successful: + type: event + description: | + The user confirmed autofilling an unauthenticated application + bugs: + - https://github.com/mozilla-mobile/android-components/issues/10301 + data_reviews: + - TBD + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + - skaspari@mozilla.com + expires: "2022-01-31" + home_menu: settings_item_clicked: type: event diff --git a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt index 32bed7d53..d5e45e300 100644 --- a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt +++ b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt @@ -65,10 +65,12 @@ import org.mozilla.fenix.telemetry.TelemetryLifecycleObserver import org.mozilla.fenix.utils.BrowsersCache import java.util.concurrent.TimeUnit import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.feature.autofill.AutofillUseCases import mozilla.components.feature.search.ext.buildSearchUrl import mozilla.components.feature.search.ext.waitForSelectedOrDefaultSearchEngine import mozilla.components.service.fxa.manager.SyncEnginesStorage import org.mozilla.fenix.GleanMetrics.Addons +import org.mozilla.fenix.GleanMetrics.AndroidAutofill import org.mozilla.fenix.GleanMetrics.Preferences import org.mozilla.fenix.GleanMetrics.SearchDefaultEngine import org.mozilla.fenix.components.metrics.Event @@ -613,6 +615,12 @@ open class FenixApplication : LocaleAwareApplication(), Provider { closeTabSetting.set(settings.getTabTimeoutPingString()) } + with(AndroidAutofill) { + val autofillUseCases = AutofillUseCases() + supported.set(autofillUseCases.isSupported(applicationContext)) + enabled.set(autofillUseCases.isEnabled(applicationContext)) + } + browserStore.waitForSelectedOrDefaultSearchEngine { searchEngine -> if (searchEngine != null) { SearchDefaultEngine.apply { 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 07091a485..a4ff902d3 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 @@ -249,6 +249,16 @@ sealed class Event { object OpenRecentTab : Event() object OpenInProgressMediaTab : Event() + // Android Autofill + object AndroidAutofillUnlockSuccessful : Event() + object AndroidAutofillUnlockCanceled : Event() + object AndroidAutofillSearchDisplayed : Event() + object AndroidAutofillSearchItemSelected : Event() + object AndroidAutofillConfirmationSuccessful : Event() + object AndroidAutofillConfirmationCanceled : Event() + object AndroidAutofillRequestWithLogins : Event() + object AndroidAutofillRequestWithoutLogins : 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 6a5bee9e2..93294e8e3 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 @@ -10,6 +10,7 @@ import mozilla.components.service.glean.private.NoExtraKeys import mozilla.components.support.base.log.logger.Logger import org.mozilla.fenix.GleanMetrics.AboutPage import org.mozilla.fenix.GleanMetrics.Addons +import org.mozilla.fenix.GleanMetrics.AndroidAutofill import org.mozilla.fenix.GleanMetrics.AndroidKeystoreExperiment import org.mozilla.fenix.GleanMetrics.AppTheme import org.mozilla.fenix.GleanMetrics.Autoplay @@ -862,6 +863,31 @@ private val Event.wrapper: EventWrapper<*>? { RecentTabs.showAllClicked.record(it) } ) + is Event.AndroidAutofillRequestWithLogins -> EventWrapper( + { AndroidAutofill.requestMatchingLogins.record(it) } + ) + is Event.AndroidAutofillRequestWithoutLogins -> EventWrapper( + { AndroidAutofill.requestNoMatchingLogins.record(it) } + ) + is Event.AndroidAutofillSearchDisplayed -> EventWrapper( + { AndroidAutofill.searchDisplayed.record(it) } + ) + is Event.AndroidAutofillSearchItemSelected -> EventWrapper( + { AndroidAutofill.searchItemSelected.record(it) } + ) + is Event.AndroidAutofillUnlockCanceled -> EventWrapper( + { AndroidAutofill.unlockCancelled.record(it) } + ) + is Event.AndroidAutofillUnlockSuccessful -> EventWrapper( + { AndroidAutofill.unlockSuccessful.record(it) } + ) + is Event.AndroidAutofillConfirmationCanceled -> EventWrapper( + { AndroidAutofill.confirmCancelled.record(it) } + ) + is Event.AndroidAutofillConfirmationSuccessful -> EventWrapper( + { AndroidAutofill.confirmSuccessful.record(it) } + ) + // 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 c51192b4b..2895d0e2b 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 @@ -9,6 +9,7 @@ import mozilla.components.browser.awesomebar.facts.BrowserAwesomeBarFacts import mozilla.components.browser.menu.facts.BrowserMenuFacts import mozilla.components.browser.toolbar.facts.ToolbarFacts import mozilla.components.concept.awesomebar.AwesomeBar +import mozilla.components.feature.autofill.facts.AutofillFacts import mozilla.components.feature.awesomebar.facts.AwesomeBarFacts import mozilla.components.feature.awesomebar.provider.BookmarksStorageSuggestionProvider import mozilla.components.feature.awesomebar.provider.ClipboardSuggestionProvider @@ -326,6 +327,35 @@ internal class ReleaseMetricController( Component.FEATURE_SEARCH to InContentTelemetry.IN_CONTENT_SEARCH -> { Event.SearchInContent(value!!) } + Component.FEATURE_AUTOFILL to AutofillFacts.Items.AUTOFILL_REQUEST -> { + val hasMatchingLogins = metadata?.get(AutofillFacts.Metadata.HAS_MATCHING_LOGINS) as Boolean? + if (hasMatchingLogins == true) { + Event.AndroidAutofillRequestWithLogins + } else { + Event.AndroidAutofillRequestWithoutLogins + } + } + Component.FEATURE_AUTOFILL to AutofillFacts.Items.AUTOFILL_SEARCH -> { + if (action == Action.SELECT) { + Event.AndroidAutofillSearchItemSelected + } else { + Event.AndroidAutofillSearchDisplayed + } + } + Component.FEATURE_AUTOFILL to AutofillFacts.Items.AUTOFILL_LOCK -> { + if (action == Action.CONFIRM) { + Event.AndroidAutofillUnlockSuccessful + } else { + Event.AndroidAutofillUnlockCanceled + } + } + Component.FEATURE_AUTOFILL to AutofillFacts.Items.AUTOFILL_CONFIRMATION -> { + if (action == Action.CONFIRM) { + Event.AndroidAutofillConfirmationSuccessful + } else { + Event.AndroidAutofillConfirmationCanceled + } + } else -> null }