Closes #19147: Move startup metrics to right after Glean initialization (#19252)

upstream-sync
Roger Yang 3 years ago committed by GitHub
parent 2bd933054f
commit 74047cdceb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1269,8 +1269,8 @@ metrics:
expires: "2021-08-11"
preferences:
show_search_suggestions:
type: string_list
search_suggestions_enabled:
type: boolean
description: >
Whether or not the user has search suggestions enabled
default: true
@ -1286,8 +1286,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
remote_debugging:
type: string_list
remote_debugging_enabled:
type: boolean
description: >
Whether or not the user has remote debugging enabled
default: false
@ -1303,8 +1303,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
telemetry:
type: string_list
telemetry_enabled:
type: boolean
description: >
Whether or not the user has telemetry enabled. Note we should
never receive a "false" value for this since telemetry would
@ -1322,8 +1322,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
tracking_protection:
type: string_list
enhanced_tracking_protection:
type: string
description: >
What type of enhanced tracking protection the user has enabled.
"standard," "strict," "custom," or "" (if disabled)
@ -1340,8 +1340,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
search_bookmarks:
type: string_list
bookmarks_suggestion:
type: boolean
description: >
Whether or not the user has enabled bookmark search suggestions
default: true
@ -1357,8 +1357,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
search_browsing_history:
type: string_list
browsing_history_suggestion:
type: boolean
description: >
Whether or not the user has enabled browsing history suggestions.
default: true
@ -1374,8 +1374,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
show_clipboard_suggestions:
type: string_list
clipboard_suggestions_enabled:
type: boolean
description: >
Whether or not the user has enabled clipboard search suggestions.
default: true
@ -1391,8 +1391,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
show_search_shortcuts:
type: string_list
search_shortcuts_enabled:
type: boolean
description: >
Whether or not the user has enabled search shortcuts.
default: true
@ -1408,8 +1408,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
open_links_in_a_private_tab:
type: string_list
open_links_in_private:
type: boolean
description: >
Whether or not the user has enabled open links in a private tab.
default: false
@ -1425,8 +1425,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
sync:
type: string_list
signed_in_sync:
type: boolean
description: >
Whether or not the user is signed into FxA
default: false
@ -1461,8 +1461,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
show_voice_search:
type: string_list
voice_search_enabled:
type: boolean
description: >
Whether or not the user has enabled the voice search button.
default: true
@ -1478,8 +1478,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
search_suggestions_private:
type: string_list
private_search_suggestions:
type: boolean
description: >
Whether or not the user has enabled showing search suggestions
in private mode.
@ -1496,8 +1496,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
toolbar_position:
type: string_list
toolbar_position_setting:
type: string
description: >
The position of the toolbar
default: bottom (defaults to top if the user has accessibility services)
@ -1531,8 +1531,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
open_links_in_app:
type: string_list
open_links_in_app_enabled:
type: boolean
description: >
Whether or not the user has the open links in apps feature enabled.
default: false
@ -1548,8 +1548,8 @@ preferences:
notification_emails:
- fenix-core@mozilla.com
expires: "2021-08-01"
theme:
type: string_list
user_theme:
type: string
description: >
The theme the user has enabled. "light," "dark," "system," or "battery"
default: "system" for API 28+, else "light"

@ -63,6 +63,17 @@ import org.mozilla.fenix.session.VisibilityLifecycleCallback
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.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.Preferences
import org.mozilla.fenix.GleanMetrics.SearchDefaultEngine
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MozillaProductDetector
import org.mozilla.fenix.components.toolbar.ToolbarPosition
import org.mozilla.fenix.utils.Settings
/**
*The main application class for Fenix. Records data to measure initialization performance.
@ -130,13 +141,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
buildInfo = GleanBuildInfo.buildInfo
)
// Set this early to guarantee it's in every ping from here on.
Metrics.distributionId.set(
when (Config.channel.isMozillaOnline) {
true -> "MozillaOnline"
false -> "Mozilla"
}
)
setStartupMetrics(components.core.store, settings())
}
@CallSuper
@ -499,6 +504,172 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
}
}
/**
* This function is called right after Glean is initialized. Part of this function depends on
* shared preferences to be updated so the correct value is sent with the metrics ping.
*
* The reason we're using shared preferences to track these values is due to the limitations of
* the current metrics ping design. The values set here will be sent in every metrics ping even
* if these values have not changed since the last startup.
*/
@Suppress("ComplexMethod", "LongMethod")
@VisibleForTesting
internal fun setStartupMetrics(
browserStore: BrowserStore,
settings: Settings,
browsersCache: BrowsersCache = BrowsersCache,
mozillaProductDetector: MozillaProductDetector = MozillaProductDetector
) {
setPreferenceMetrics(settings)
with(Metrics) {
// Set this early to guarantee it's in every ping from here on.
distributionId.set(
when (Config.channel.isMozillaOnline) {
true -> "MozillaOnline"
false -> "Mozilla"
}
)
defaultBrowser.set(browsersCache.all(applicationContext).isDefaultBrowser)
mozillaProductDetector.getMozillaBrowserDefault(applicationContext)?.also {
defaultMozBrowser.set(it)
}
mozillaProducts.set(mozillaProductDetector.getInstalledMozillaProducts(applicationContext))
adjustCampaign.set(settings.adjustCampaignId)
adjustAdGroup.set(settings.adjustAdGroup)
adjustCreative.set(settings.adjustCreative)
adjustNetwork.set(settings.adjustNetwork)
searchWidgetInstalled.set(settings.searchWidgetInstalled)
val openTabsCount = settings.openTabsCount
hasOpenTabs.set(openTabsCount > 0)
if (openTabsCount > 0) {
tabsOpenCount.add(openTabsCount)
}
val topSitesSize = settings.topSitesSize
hasTopSites.set(topSitesSize > 0)
if (topSitesSize > 0) {
topSitesCount.add(topSitesSize)
}
val installedAddonSize = settings.installedAddonsCount
Addons.hasInstalledAddons.set(installedAddonSize > 0)
if (installedAddonSize > 0) {
Addons.installedAddons.set(settings.installedAddonsList.split(','))
}
val enabledAddonSize = settings.enabledAddonsCount
Addons.hasEnabledAddons.set(enabledAddonSize > 0)
if (enabledAddonSize > 0) {
Addons.enabledAddons.set(settings.enabledAddonsList.split(','))
}
val desktopBookmarksSize = settings.desktopBookmarksSize
hasDesktopBookmarks.set(desktopBookmarksSize > 0)
if (desktopBookmarksSize > 0) {
desktopBookmarksCount.add(desktopBookmarksSize)
}
val mobileBookmarksSize = settings.mobileBookmarksSize
hasMobileBookmarks.set(mobileBookmarksSize > 0)
if (mobileBookmarksSize > 0) {
mobileBookmarksCount.add(mobileBookmarksSize)
}
toolbarPosition.set(
when (settings.toolbarPosition) {
ToolbarPosition.BOTTOM -> Event.ToolbarPositionChanged.Position.BOTTOM.name
ToolbarPosition.TOP -> Event.ToolbarPositionChanged.Position.TOP.name
}
)
tabViewSetting.set(settings.getTabViewPingString())
closeTabSetting.set(settings.getTabTimeoutPingString())
}
browserStore.waitForSelectedOrDefaultSearchEngine { searchEngine ->
if (searchEngine != null) {
SearchDefaultEngine.apply {
code.set(searchEngine.id)
name.set(searchEngine.name)
submissionUrl.set(searchEngine.buildSearchUrl(""))
}
}
}
}
@Suppress("ComplexMethod")
private fun setPreferenceMetrics(
settings: Settings
) {
with(Preferences) {
searchSuggestionsEnabled.set(settings.shouldShowSearchSuggestions)
remoteDebuggingEnabled.set(settings.isRemoteDebuggingEnabled)
telemetryEnabled.set(settings.isTelemetryEnabled)
browsingHistorySuggestion.set(settings.shouldShowHistorySuggestions)
bookmarksSuggestion.set(settings.shouldShowBookmarkSuggestions)
clipboardSuggestionsEnabled.set(settings.shouldShowClipboardSuggestions)
searchShortcutsEnabled.set(settings.shouldShowSearchShortcuts)
openLinksInPrivate.set(settings.openLinksInAPrivateTab)
privateSearchSuggestions.set(settings.shouldShowSearchSuggestionsInPrivate)
voiceSearchEnabled.set(settings.shouldShowVoiceSearch)
openLinksInAppEnabled.set(settings.openLinksInExternalApp)
val isLoggedIn =
components.backgroundServices.accountManager.accountProfile() != null
signedInSync.set(isLoggedIn)
val syncedItems = SyncEnginesStorage(applicationContext).getStatus().entries.filter {
it.value
}.map { it.key.nativeName }
syncItems.set(syncedItems)
toolbarPositionSetting.set(
when {
settings.shouldUseFixedTopToolbar -> "fixed_top"
settings.shouldUseBottomToolbar -> "bottom"
else -> "top"
}
)
enhancedTrackingProtection.set(
when {
!settings.shouldUseTrackingProtection -> ""
settings.useStandardTrackingProtection -> "standard"
settings.useStrictTrackingProtection -> "strict"
settings.useCustomTrackingProtection -> "custom"
else -> ""
}
)
val accessibilitySelection = mutableListOf<String>()
if (settings.switchServiceIsEnabled) {
accessibilitySelection.add("switch")
}
if (settings.touchExplorationIsEnabled) {
accessibilitySelection.add("touch exploration")
}
accessibilityServices.set(accessibilitySelection.toList())
userTheme.set(
when {
settings.shouldUseLightTheme -> "light"
settings.shouldUseDarkTheme -> "dark"
settings.shouldFollowDeviceTheme -> "system"
settings.shouldUseAutoBatteryTheme -> "battery"
else -> ""
}
)
}
}
protected fun recordOnInit() {
// This gets called by more than one process. Ideally we'd only run this in the main process
// but the code to check which process we're in crashes because the Context isn't valid yet.

@ -92,7 +92,7 @@ class Analytics(
val metrics: MetricController by lazyMonitored {
MetricController.create(
listOf(
GleanMetricsService(context, lazy { context.components.core.store }),
GleanMetricsService(context),
AdjustMetricsService(context as Application)
),
isDataTelemetryEnabled = { context.settings().isTelemetryEnabled },

@ -5,10 +5,6 @@
package org.mozilla.fenix.components.metrics
import android.content.Context
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.feature.search.ext.buildSearchUrl
import mozilla.components.feature.search.ext.waitForSelectedOrDefaultSearchEngine
import mozilla.components.service.fxa.manager.SyncEnginesStorage
import mozilla.components.service.glean.Glean
import mozilla.components.service.glean.private.NoExtraKeys
import mozilla.components.support.base.log.logger.Logger
@ -46,12 +42,10 @@ import org.mozilla.fenix.GleanMetrics.Metrics
import org.mozilla.fenix.GleanMetrics.Onboarding
import org.mozilla.fenix.GleanMetrics.Pings
import org.mozilla.fenix.GleanMetrics.Pocket
import org.mozilla.fenix.GleanMetrics.Preferences
import org.mozilla.fenix.GleanMetrics.PrivateBrowsingMode
import org.mozilla.fenix.GleanMetrics.PrivateBrowsingShortcut
import org.mozilla.fenix.GleanMetrics.ProgressiveWebApp
import org.mozilla.fenix.GleanMetrics.ReaderMode
import org.mozilla.fenix.GleanMetrics.SearchDefaultEngine
import org.mozilla.fenix.GleanMetrics.SearchShortcuts
import org.mozilla.fenix.GleanMetrics.SearchSuggestions
import org.mozilla.fenix.GleanMetrics.SearchWidget
@ -70,11 +64,7 @@ import org.mozilla.fenix.GleanMetrics.TopSites
import org.mozilla.fenix.GleanMetrics.TrackingProtection
import org.mozilla.fenix.GleanMetrics.UserSpecifiedSearchEngines
import org.mozilla.fenix.GleanMetrics.VoiceSearch
import org.mozilla.fenix.components.toolbar.ToolbarPosition
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.utils.BrowsersCache
import org.mozilla.fenix.utils.Settings
private class EventWrapper<T : Enum<T>>(
private val recorder: ((Map<T, String>?) -> Unit),
@ -855,11 +845,11 @@ private val Event.wrapper: EventWrapper<*>?
is Event.SyncAuthFromSharedReuse, Event.SyncAuthFromSharedCopy -> null
}
/**
* Service responsible for sending the activation and installation pings.
*/
class GleanMetricsService(
private val context: Context,
private val store: Lazy<BrowserStore>,
private val browsersCache: BrowsersCache = BrowsersCache,
private val mozillaProductDetector: MozillaProductDetector = MozillaProductDetector
private val context: Context
) : MetricsService {
override val type = MetricServiceType.Data
@ -887,181 +877,11 @@ class GleanMetricsService(
// can handle events being recorded before it's initialized.
Glean.registerPings(Pings)
// setStartupMetrics is not a fast function. It does not need to be done before we can consider
// ourselves initialized. So, let's do it, well, later.
setStartupMetrics(context.settings())
}
}
/**
* This function is called before the metrics ping is sent. Part of this function depends on
* shared preferences to be updated so the correct value is sent with the metrics ping.
*
* The reason we're using shared preferences to track some of these values is due to the
* limitations of the metrics ping. Events are only sent in a metrics ping if the user have made
* changes between each ping. However, in some cases we want current values to be sent even if
* the user have not changed anything between pings.
*/
internal fun setStartupMetrics(settings: Settings) {
setPreferenceMetrics()
with(Metrics) {
defaultBrowser.set(browsersCache.all(context).isDefaultBrowser)
mozillaProductDetector.getMozillaBrowserDefault(context)?.also {
defaultMozBrowser.set(it)
}
mozillaProducts.set(mozillaProductDetector.getInstalledMozillaProducts(context))
adjustCampaign.set(settings.adjustCampaignId)
adjustAdGroup.set(settings.adjustAdGroup)
adjustCreative.set(settings.adjustCreative)
adjustNetwork.set(settings.adjustNetwork)
searchWidgetInstalled.set(settings.searchWidgetInstalled)
val openTabsCount = settings.openTabsCount
hasOpenTabs.set(openTabsCount > 0)
if (openTabsCount > 0) {
tabsOpenCount.add(openTabsCount)
}
val topSitesSize = settings.topSitesSize
hasTopSites.set(topSitesSize > 0)
if (topSitesSize > 0) {
topSitesCount.add(topSitesSize)
}
val installedAddonSize = settings.installedAddonsCount
Addons.hasInstalledAddons.set(installedAddonSize > 0)
if (installedAddonSize > 0) {
Addons.installedAddons.set(settings.installedAddonsList.split(','))
}
val enabledAddonSize = settings.enabledAddonsCount
Addons.hasEnabledAddons.set(enabledAddonSize > 0)
if (enabledAddonSize > 0) {
Addons.enabledAddons.set(settings.enabledAddonsList.split(','))
}
val desktopBookmarksSize = settings.desktopBookmarksSize
hasDesktopBookmarks.set(desktopBookmarksSize > 0)
if (desktopBookmarksSize > 0) {
desktopBookmarksCount.add(desktopBookmarksSize)
}
val mobileBookmarksSize = settings.mobileBookmarksSize
hasMobileBookmarks.set(mobileBookmarksSize > 0)
if (mobileBookmarksSize > 0) {
mobileBookmarksCount.add(mobileBookmarksSize)
}
toolbarPosition.set(
when (settings.toolbarPosition) {
ToolbarPosition.BOTTOM -> Event.ToolbarPositionChanged.Position.BOTTOM.name
ToolbarPosition.TOP -> Event.ToolbarPositionChanged.Position.TOP.name
}
)
tabViewSetting.set(settings.getTabViewPingString())
closeTabSetting.set(settings.getTabTimeoutPingString())
}
store.value.waitForSelectedOrDefaultSearchEngine { searchEngine ->
if (searchEngine != null) {
SearchDefaultEngine.apply {
code.set(searchEngine.id)
name.set(searchEngine.name)
submissionUrl.set(searchEngine.buildSearchUrl(""))
}
}
activationPing.checkAndSend()
installationPing.checkAndSend()
}
}
private fun setPreferenceMetrics() {
// We purposefully make all of our preferences the string_list format to make data analysis
// simpler. While it makes things like booleans a bit more complicated, it means all our
// preferences can be analyzed with the same dashboard and compared.
with(Preferences) {
showSearchSuggestions.set(context.settings().shouldShowSearchSuggestions.toStringList())
remoteDebugging.set(context.settings().isRemoteDebuggingEnabled.toStringList())
telemetry.set(context.settings().isTelemetryEnabled.toStringList())
searchBrowsingHistory.set(context.settings().shouldShowHistorySuggestions.toStringList())
searchBookmarks.set(context.settings().shouldShowBookmarkSuggestions.toStringList())
showClipboardSuggestions.set(context.settings().shouldShowClipboardSuggestions.toStringList())
showSearchShortcuts.set(context.settings().shouldShowSearchShortcuts.toStringList())
openLinksInAPrivateTab.set(context.settings().openLinksInAPrivateTab.toStringList())
searchSuggestionsPrivate.set(context.settings().shouldShowSearchSuggestionsInPrivate.toStringList())
showVoiceSearch.set(context.settings().shouldShowVoiceSearch.toStringList())
openLinksInApp.set(context.settings().openLinksInExternalApp.toStringList())
val isLoggedIn =
context.components.backgroundServices.accountManager.accountProfile() != null
sync.set(isLoggedIn.toStringList())
val syncedItems = SyncEnginesStorage(context).getStatus().entries.filter {
it.value
}.map { it.key.nativeName }
syncItems.set(syncedItems)
val toolbarPositionSelection =
if (context.settings().shouldUseFixedTopToolbar) {
"fixed_top"
} else if (context.settings().shouldUseBottomToolbar) {
"bottom"
} else {
"top"
}
toolbarPosition.set(listOf(toolbarPositionSelection))
val etpSelection =
if (!context.settings().shouldUseTrackingProtection) {
""
} else if (context.settings().useStandardTrackingProtection) {
"standard"
} else if (context.settings().useStrictTrackingProtection) {
"strict"
} else if (context.settings().useCustomTrackingProtection) {
"custom"
} else {
""
}
trackingProtection.set(listOf(etpSelection))
val accessibilitySelection = mutableListOf<String>()
if (context.settings().switchServiceIsEnabled) {
accessibilitySelection.add("switch")
}
if (context.settings().touchExplorationIsEnabled) {
accessibilitySelection.add("touch exploration")
}
accessibilityServices.set(accessibilitySelection.toList())
val themeSelection =
if (context.settings().shouldUseLightTheme) {
"light"
} else if (context.settings().shouldUseDarkTheme) {
"dark"
} else if (context.settings().shouldFollowDeviceTheme) {
"system"
} else if (context.settings().shouldUseAutoBatteryTheme) {
"battery"
} else {
""
}
theme.set(listOf(themeSelection))
}
}
override fun stop() {
Glean.setUploadEnabled(false)
}

@ -8,19 +8,30 @@ import androidx.test.core.app.ApplicationProvider
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.webextension.DisabledFlags
import mozilla.components.concept.engine.webextension.Metadata
import mozilla.components.concept.engine.webextension.WebExtension
import mozilla.components.feature.addons.migration.DefaultSupportedAddonsChecker
import mozilla.components.service.glean.testing.GleanTestRule
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.GleanMetrics.Addons
import org.mozilla.fenix.GleanMetrics.Metrics
import org.mozilla.fenix.GleanMetrics.PerfStartup
import org.mozilla.fenix.GleanMetrics.Preferences
import org.mozilla.fenix.GleanMetrics.SearchDefaultEngine
import org.mozilla.fenix.components.metrics.MozillaProductDetector
import org.mozilla.fenix.components.toolbar.ToolbarPosition
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.utils.BrowsersCache
import org.mozilla.fenix.utils.Settings
@RunWith(FenixRobolectricTestRunner::class)
class FenixApplicationTest {
@ -28,10 +39,16 @@ class FenixApplicationTest {
@get:Rule val gleanTestRule = GleanTestRule(ApplicationProvider.getApplicationContext())
private lateinit var application: FenixApplication
private lateinit var browsersCache: BrowsersCache
private lateinit var mozillaProductDetector: MozillaProductDetector
private lateinit var browserStore: BrowserStore
@Before
fun setUp() {
application = ApplicationProvider.getApplicationContext()
browsersCache = mockk(relaxed = true)
mozillaProductDetector = mockk(relaxed = true)
browserStore = BrowserStore()
}
@Ignore("See https://github.com/mozilla-mobile/fenix/issues/18102")
@ -69,4 +86,90 @@ class FenixApplicationTest {
verify { checker.unregisterForChecks() }
}
@Test
fun `WHEN setStartupMetrics is called THEN sets some base metrics`() {
val expectedAppName = "org.mozilla.fenix"
val settings: Settings = mockk()
every { browsersCache.all(any()).isDefaultBrowser } returns true
every { mozillaProductDetector.getMozillaBrowserDefault(any()) } returns expectedAppName
every { mozillaProductDetector.getInstalledMozillaProducts(any()) } returns listOf(expectedAppName)
every { settings.adjustCampaignId } returns "ID"
every { settings.adjustAdGroup } returns "group"
every { settings.adjustCreative } returns "creative"
every { settings.adjustNetwork } returns "network"
every { settings.searchWidgetInstalled } returns true
every { settings.openTabsCount } returns 1
every { settings.topSitesSize } returns 2
every { settings.installedAddonsCount } returns 3
every { settings.installedAddonsList } returns "test1,test2,test3"
every { settings.enabledAddonsCount } returns 2
every { settings.enabledAddonsList } returns "test1,test2"
every { settings.desktopBookmarksSize } returns 4
every { settings.mobileBookmarksSize } returns 5
every { settings.toolbarPosition } returns ToolbarPosition.BOTTOM
every { settings.getTabViewPingString() } returns "test"
every { settings.getTabTimeoutPingString() } returns "test"
every { settings.shouldShowSearchSuggestions } returns true
every { settings.shouldUseTrackingProtection } returns true
every { settings.isRemoteDebuggingEnabled } returns true
every { settings.isTelemetryEnabled } returns true
every { settings.shouldShowHistorySuggestions } returns true
every { settings.shouldShowBookmarkSuggestions } returns true
every { settings.shouldShowClipboardSuggestions } returns true
every { settings.shouldShowSearchShortcuts } returns true
every { settings.openLinksInAPrivateTab } returns true
every { settings.shouldShowSearchSuggestionsInPrivate } returns true
every { settings.shouldShowVoiceSearch } returns true
every { settings.openLinksInExternalApp } returns true
every { settings.shouldUseFixedTopToolbar } returns true
every { settings.useStandardTrackingProtection } returns true
every { settings.switchServiceIsEnabled } returns true
every { settings.touchExplorationIsEnabled } returns true
every { settings.shouldUseLightTheme } returns true
application.setStartupMetrics(browserStore, settings, browsersCache, mozillaProductDetector)
// Verify that browser defaults metrics are set.
assertEquals("Mozilla", Metrics.distributionId.testGetValue())
assertEquals(true, Metrics.defaultBrowser.testGetValue())
assertEquals(expectedAppName, Metrics.defaultMozBrowser.testGetValue())
assertEquals(listOf(expectedAppName), Metrics.mozillaProducts.testGetValue())
assertEquals("ID", Metrics.adjustCampaign.testGetValue())
assertEquals("group", Metrics.adjustAdGroup.testGetValue())
assertEquals("creative", Metrics.adjustCreative.testGetValue())
assertEquals("network", Metrics.adjustNetwork.testGetValue())
assertEquals(true, Metrics.searchWidgetInstalled.testGetValue())
assertEquals(true, Metrics.hasOpenTabs.testGetValue())
assertEquals(1, Metrics.tabsOpenCount.testGetValue())
assertEquals(true, Metrics.hasTopSites.testGetValue())
assertEquals(2, Metrics.topSitesCount.testGetValue())
assertEquals(true, Addons.hasInstalledAddons.testGetValue())
assertEquals(listOf("test1", "test2", "test3"), Addons.installedAddons.testGetValue())
assertEquals(true, Addons.hasEnabledAddons.testGetValue())
assertEquals(listOf("test1", "test2"), Addons.enabledAddons.testGetValue())
assertEquals(true, Preferences.searchSuggestionsEnabled.testGetValue())
assertEquals(true, Preferences.remoteDebuggingEnabled.testGetValue())
assertEquals(true, Preferences.telemetryEnabled.testGetValue())
assertEquals(true, Preferences.browsingHistorySuggestion.testGetValue())
assertEquals(true, Preferences.bookmarksSuggestion.testGetValue())
assertEquals(true, Preferences.clipboardSuggestionsEnabled.testGetValue())
assertEquals(true, Preferences.searchShortcutsEnabled.testGetValue())
assertEquals(true, Preferences.openLinksInPrivate.testGetValue())
assertEquals(true, Preferences.privateSearchSuggestions.testGetValue())
assertEquals(true, Preferences.voiceSearchEnabled.testGetValue())
assertEquals(true, Preferences.openLinksInAppEnabled.testGetValue())
assertEquals(true, Preferences.signedInSync.testGetValue())
assertEquals(emptyList<String>(), Preferences.syncItems.testGetValue())
assertEquals("fixed_top", Preferences.toolbarPositionSetting.testGetValue())
assertEquals("standard", Preferences.enhancedTrackingProtection.testGetValue())
assertEquals(listOf("switch", "touch exploration"), Preferences.accessibilityServices.testGetValue())
assertEquals("light", Preferences.userTheme.testGetValue())
// Verify that search engine defaults are NOT set. This test does
// not mock most of the objects telemetry is collected from.
assertFalse(SearchDefaultEngine.code.testHasValue())
assertFalse(SearchDefaultEngine.name.testHasValue())
assertFalse(SearchDefaultEngine.submissionUrl.testHasValue())
}
}

@ -5,10 +5,6 @@
package org.mozilla.fenix.components.metrics
import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.mockk
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.service.glean.testing.GleanTestRule
import mozilla.components.support.test.robolectric.testContext
import org.junit.Assert.assertEquals
@ -23,15 +19,10 @@ import org.mozilla.fenix.GleanMetrics.Awesomebar
import org.mozilla.fenix.GleanMetrics.BookmarksManagement
import org.mozilla.fenix.GleanMetrics.Events
import org.mozilla.fenix.GleanMetrics.History
import org.mozilla.fenix.GleanMetrics.Metrics
import org.mozilla.fenix.GleanMetrics.SearchDefaultEngine
import org.mozilla.fenix.GleanMetrics.SyncedTabs
import org.mozilla.fenix.GleanMetrics.TabsTray
import org.mozilla.fenix.GleanMetrics.TabsTrayCfr
import org.mozilla.fenix.components.toolbar.ToolbarPosition
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.utils.BrowsersCache
import org.mozilla.fenix.utils.Settings
@RunWith(FenixRobolectricTestRunner::class)
class GleanMetricsServiceTest {
@ -40,66 +31,11 @@ class GleanMetricsServiceTest {
private lateinit var gleanService: GleanMetricsService
@MockK private lateinit var browsersCache: BrowsersCache
@MockK private lateinit var mozillaProductDetector: MozillaProductDetector
@Before
fun setup() {
MockKAnnotations.init(this)
val store = BrowserStore()
gleanService = GleanMetricsService(testContext, lazy { store }, browsersCache, mozillaProductDetector)
}
@Test
fun `setStartupMetrics sets some base metrics`() {
val expectedAppName = "org.mozilla.fenix"
val settings: Settings = mockk()
every { browsersCache.all(any()).isDefaultBrowser } returns true
every { mozillaProductDetector.getMozillaBrowserDefault(any()) } returns expectedAppName
every { mozillaProductDetector.getInstalledMozillaProducts(any()) } returns listOf(expectedAppName)
every { settings.adjustCampaignId } returns "ID"
every { settings.adjustAdGroup } returns "group"
every { settings.adjustCreative } returns "creative"
every { settings.adjustNetwork } returns "network"
every { settings.searchWidgetInstalled } returns true
every { settings.openTabsCount } returns 1
every { settings.topSitesSize } returns 2
every { settings.installedAddonsCount } returns 3
every { settings.installedAddonsList } returns "test1,test2,test3"
every { settings.enabledAddonsCount } returns 2
every { settings.enabledAddonsList } returns "test1,test2"
every { settings.desktopBookmarksSize } returns 4
every { settings.mobileBookmarksSize } returns 5
every { settings.toolbarPosition } returns ToolbarPosition.BOTTOM
every { settings.getTabViewPingString() } returns "test"
every { settings.getTabTimeoutPingString() } returns "test"
gleanService.setStartupMetrics(settings)
// Verify that browser defaults metrics are set.
assertEquals(true, Metrics.defaultBrowser.testGetValue())
assertEquals(expectedAppName, Metrics.defaultMozBrowser.testGetValue())
assertEquals(listOf(expectedAppName), Metrics.mozillaProducts.testGetValue())
assertEquals("ID", Metrics.adjustCampaign.testGetValue())
assertEquals("group", Metrics.adjustAdGroup.testGetValue())
assertEquals("creative", Metrics.adjustCreative.testGetValue())
assertEquals("network", Metrics.adjustNetwork.testGetValue())
assertEquals(true, Metrics.searchWidgetInstalled.testGetValue())
assertEquals(true, Metrics.hasOpenTabs.testGetValue())
assertEquals(1, Metrics.tabsOpenCount.testGetValue())
assertEquals(true, Metrics.hasTopSites.testGetValue())
assertEquals(2, Metrics.topSitesCount.testGetValue())
assertEquals(true, Addons.hasInstalledAddons.testGetValue())
assertEquals(listOf("test1", "test2", "test3"), Addons.installedAddons.testGetValue())
assertEquals(true, Addons.hasEnabledAddons.testGetValue())
assertEquals(listOf("test1", "test2"), Addons.enabledAddons.testGetValue())
// Verify that search engine defaults are NOT set. This test does
// not mock most of the objects telemetry is collected from.
assertFalse(SearchDefaultEngine.code.testHasValue())
assertFalse(SearchDefaultEngine.name.testHasValue())
assertFalse(SearchDefaultEngine.submissionUrl.testHasValue())
gleanService = GleanMetricsService(testContext)
}
@Test

@ -369,22 +369,22 @@ In addition to those built-in metrics, the following metrics are added to the pi
| perf.startup.home_fragment_on_view_created |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |The duration of `HomeFragment.onViewCreated`. |[mozilla-mobile/fenix#18558](https://github.com/mozilla-mobile/fenix/pull/18558#issue-596791848)||2021-08-11 |1 |
| perf.startup.startup_type |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |Indicates how the browser was started. The label is divided into two variables. `state` is how cached the browser is when started. `path` is what code path we are expected to take. Together, they create a combined label: `state_path`. For brevity, the specific states are documented in the [Fenix perf glossary](https://wiki.mozilla.org/index.php?title=Performance/Fenix/Glossary). <br><br> This implementation is intended to be simple, not comprehensive. We list the implications below. <br><br> These ways of opening the app undesirably adds events to our primary buckets (non-`unknown` cases): <br>- App switcher cold/warm: `cold/warm_` + duplicates path from previous launch <br>- Home screen shortcuts: `*_view` <br>- An Intent is sent internally that's uses `ACTION_MAIN` or `ACTION_VIEW` could be: `*_main/view` (unknown if this ever happens) <br>- A command-line launch uses `ACTION_MAIN` or `ACTION_VIEW` could be: `*_main/view` <br><br> These ways of opening the app undesirably do not add their events to our primary buckets: <br>- Close and reopen the app very quickly: no event is recorded. <br><br> These ways of opening the app don't affect our primary buckets: <br>- App switcher hot: `hot_unknown` <br>- PWA (all states): `unknown_unknown` <br>- Custom tab: `unknown_view` <br>- Cold start where a service or other non-activity starts the process (not manually tested) - this seems to happen if you have the homescreen widget: `unknown_*` <br>- Another activity is drawn before HomeActivity (e.g. widget voice search): `unknown_*` <br>- Widget text search: `*_unknown` <br><br> In addition to the events above, the `unknown` state may be chosen when we were unable to determine a cause due to implementation details or the API was used incorrectly. We may be able to record the events listed above into different buckets but we kept the implementation simple for now. <br><br> N.B.: for implementation simplicity, we duplicate the logic in app that determines `path` so it's not perfectly accurate. In one way, we record we is intended to happen rather than what actually happened (e.g. the user may click a link so we record VIEW but the app does a MAIN by going to the homescreen because the link was invalid). |[mozilla-mobile/fenix#19028](https://github.com/mozilla-mobile/fenix/pull/19028)|<ul><li>cold_main</li><li>cold_view</li><li>cold_unknown</li><li>warm_main</li><li>warm_view</li><li>warm_unknown</li><li>hot_main</li><li>hot_view</li><li>hot_unknown</li><li>unknown_main</li><li>unknown_view</li><li>unknown_unknown</li></ul>|2021-10-09 |2 |
| preferences.accessibility_services |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user has touch exploration or switch services enabled. These are built into the Android OS, not Fenix prefs. default: "" |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.open_links_in_a_private_tab |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user has enabled open links in a private tab. default: false |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.open_links_in_app |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user has the open links in apps feature enabled. default: false |[mozilla-mobile/fenix#11446](https://github.com/mozilla-mobile/fenix/pull/11446), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.remote_debugging |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user has remote debugging enabled default: false |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.search_bookmarks |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user has enabled bookmark search suggestions default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.search_browsing_history |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user has enabled browsing history suggestions. default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.search_suggestions_private |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user has enabled showing search suggestions in private mode. default: false (we prompt the user, asking them to make a selection) |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.show_clipboard_suggestions |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user has enabled clipboard search suggestions. default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.show_search_shortcuts |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user has enabled search shortcuts. default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.show_search_suggestions |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user has search suggestions enabled default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.show_voice_search |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user has enabled the voice search button. default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.sync |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user is signed into FxA default: false |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.bookmarks_suggestion |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has enabled bookmark search suggestions default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.browsing_history_suggestion |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has enabled browsing history suggestions. default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.clipboard_suggestions_enabled |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has enabled clipboard search suggestions. default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.enhanced_tracking_protection |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |What type of enhanced tracking protection the user has enabled. "standard," "strict," "custom," or "" (if disabled) default: "standard" |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.open_links_in_app_enabled |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has the open links in apps feature enabled. default: false |[mozilla-mobile/fenix#11446](https://github.com/mozilla-mobile/fenix/pull/11446), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.open_links_in_private |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has enabled open links in a private tab. default: false |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.private_search_suggestions |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has enabled showing search suggestions in private mode. default: false (we prompt the user, asking them to make a selection) |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.remote_debugging_enabled |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has remote debugging enabled default: false |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.search_shortcuts_enabled |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has enabled search shortcuts. default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.search_suggestions_enabled |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has search suggestions enabled default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.signed_in_sync |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user is signed into FxA default: false |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.sync_items |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |The list of items the user has chosen to sync with FxA. default: "" if the user is signed out. Otherwise defaults to whatever is set in their FxA account. New accounts set: [bookmarks, history, passwords, tabs] |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.telemetry |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |Whether or not the user has telemetry enabled. Note we should never receive a "false" value for this since telemetry would not send in that case. default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.theme |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |The theme the user has enabled. "light," "dark," "system," or "battery" default: "system" for API 28+, else "light" |[mozilla-mobile/fenix#11446](https://github.com/mozilla-mobile/fenix/pull/11446), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.toolbar_position |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |The position of the toolbar default: bottom (defaults to top if the user has accessibility services) |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.tracking_protection |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |What type of enhanced tracking protection the user has enabled. "standard," "strict," "custom," or "" (if disabled) default: "standard" |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.telemetry_enabled |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has telemetry enabled. Note we should never receive a "false" value for this since telemetry would not send in that case. default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.toolbar_position_setting |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |The position of the toolbar default: bottom (defaults to top if the user has accessibility services) |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.user_theme |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |The theme the user has enabled. "light," "dark," "system," or "battery" default: "system" for API 28+, else "light" |[mozilla-mobile/fenix#11446](https://github.com/mozilla-mobile/fenix/pull/11446), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| preferences.voice_search_enabled |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has enabled the voice search button. default: true |[mozilla-mobile/fenix#11211](https://github.com/mozilla-mobile/fenix/pull/11211), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |2 |
| search.default_engine.code |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |If the search engine is pre-loaded with Fenix this value will be the search engine identifier. If it's a custom search engine (defined: https://github.com/mozilla-mobile/fenix/issues/1607) the value will be "custom" |[mozilla-mobile/fenix#1606](https://github.com/mozilla-mobile/fenix/pull/1606), [mozilla-mobile/fenix#5216](https://github.com/mozilla-mobile/fenix/pull/5216), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |1, 2 |
| search.default_engine.name |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |If the search engine is pre-loaded with Fenix this value will be the search engine name. If it's a custom search engine (defined: https://github.com/mozilla-mobile/fenix/issues/1607) the value will be "custom" |[mozilla-mobile/fenix#1606](https://github.com/mozilla-mobile/fenix/pull/1606), [mozilla-mobile/fenix#5216](https://github.com/mozilla-mobile/fenix/pull/5216), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |1, 2 |
| search.default_engine.submission_url |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |If the search engine is pre-loaded with Fenix this value will be he base URL we use to build the search query for the search engine. For example: https://mysearchengine.com/?query=%s. If it's a custom search engine (defined: https://github.com/mozilla-mobile/fenix/issues/1607) the value will be "custom" |[mozilla-mobile/fenix#1606](https://github.com/mozilla-mobile/fenix/pull/1606), [mozilla-mobile/fenix#5216](https://github.com/mozilla-mobile/fenix/pull/5216), [mozilla-mobile/fenix#15713](https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068)||2021-08-01 |1, 2 |

Loading…
Cancel
Save