diff --git a/README.md b/README.md index b93808d9a..ef1d872d0 100644 --- a/README.md +++ b/README.md @@ -105,21 +105,23 @@ you want these variants to be: #### Performance Build Variants For accurate performance measurements, read this section! -If you want to analyze performance during **local development** (note: there is a non-trivial performance impact - see caveats): -- Recommendation: use a debuggable variant (see "local.properties helpers" below) with local Leanplum, Adjust, & Sentry API tokens: contact the front-end perf group for access to them -- Rationale: There are numerous performance-impacting differences between debug and release variants so we need a release variant. To profile, we also need debuggable, which is disabled by default for release variants. If API tokens are not provided, the SDKs may change their behavior in non-trivial ways. -- Caveats: - - debuggable has a non-trivial & variable impact on performance but is needed to take profiles. - - Random experiment opt-in & feature flags may impact performance (see [perf-frontend-issues#45](https://github.com/mozilla-mobile/perf-frontend-issues/issues/45) for mitigation). - - This is slower to build than debug builds because it does additional tasks (e.g. minification) similar to other release builds +To analyze performance during **local development** build a production variant locally (this could either be the Nightly, beta or release). Otherwise, you could also grab a pre-existing APK if you don't need to test some local changes. Then, use the Firefox profiler to profile what you need! -If you want to run **performance tests/benchmarks** in automation or locally: -- Recommendation: production builds. If debuggable is required, use recommendation above but note the caveat above. If your needs are not met, please contact the front-end perf group to identify a new solution. -- Rationale: like the rationale above, we need release variants so the choice is based on the debuggable flag. +For more information on how to use the profiler or how to use the build, refer to this [how to measure performance with the build](https://wiki.mozilla.org/Performance/How_to_get_started_on_Fenix) -For additional context on these recommendations, see [the perf build variant analysis](https://docs.google.com/document/d/1aW-m0HYncTDDiRz_2x6EjcYkjBpL9SHhhYix13Vil30/edit#). +If you want to run **performance tests/benchmarks** in automation or locally use a production build since it is much closer in behavior compared to what users see in the wild. -Before you can install any release variants, **you will need to sign them:** see [Automatically signing release builds](#automatically-sign-release-builds) for details. +Before you can install any release builds, **You will need to sign production build variants:** see [Automatically signing release builds](#automatically-sign-release-builds) for details. + +##### Known disabled-by-default features +Some features are disabled by default when Fenix is built locally. This can be problematic at times for checking performance since you might want to know how your code behaves with those features. +The known features that are disabled by default are: +- Sentry +- Leanplum +- Adjust +- Mozilla Location Services (also known as MLS) +- Firebase Push Services +- Telemetry (only disabled by default in debug builds) ## Pre-push hooks To reduce review turn-around time, we'd like all pushes to run tests locally. We'd diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt index 9beaf4524..2b47a32a0 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/HomeActivityTestRule.kt @@ -5,7 +5,9 @@ package org.mozilla.fenix.helpers import androidx.test.espresso.intent.rule.IntentsTestRule +import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.ActivityTestRule +import androidx.test.uiautomator.UiDevice import org.mozilla.fenix.HomeActivity /** @@ -16,7 +18,12 @@ import org.mozilla.fenix.HomeActivity */ class HomeActivityTestRule(initialTouchMode: Boolean = false, launchActivity: Boolean = true) : - ActivityTestRule(HomeActivity::class.java, initialTouchMode, launchActivity) + ActivityTestRule(HomeActivity::class.java, initialTouchMode, launchActivity) { + override fun beforeActivityLaunched() { + super.beforeActivityLaunched() + setLongTapTimeout() + } +} /** * A [org.junit.Rule] to handle shared test set up for tests on [HomeActivity]. This adds @@ -26,5 +33,19 @@ class HomeActivityTestRule(initialTouchMode: Boolean = false, launchActivity: Bo * @param launchActivity See [IntentsTestRule] */ -class HomeActivityIntentTestRule(initialTouchMode: Boolean = false, launchActivity: Boolean = true) : - IntentsTestRule(HomeActivity::class.java, initialTouchMode, launchActivity) +class HomeActivityIntentTestRule( + initialTouchMode: Boolean = false, + launchActivity: Boolean = true +) : + IntentsTestRule(HomeActivity::class.java, initialTouchMode, launchActivity) { + override fun beforeActivityLaunched() { + super.beforeActivityLaunched() + setLongTapTimeout() + } +} + +// changing the device preference for Touch and Hold delay, to avoid long-clicks instead of a single-click +fun setLongTapTimeout() { + val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + mDevice.executeShellCommand("settings put secure long_press_timeout 3000") +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAboutTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAboutTest.kt index b9963cb98..26368bd0a 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAboutTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAboutTest.kt @@ -10,7 +10,6 @@ import okhttp3.mockwebserver.MockWebServer import org.junit.Rule import org.junit.Before import org.junit.After -import org.junit.Ignore import org.junit.Test import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.HomeActivityIntentTestRule @@ -69,7 +68,7 @@ class SettingsAboutTest { } } - @Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/13219") + @Test fun verifyAboutFirefoxPreview() { homeScreen { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt index 4e6a9e3ef..54ae398c4 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAboutRobot.kt @@ -222,7 +222,7 @@ private fun assertLibrariesUsed() { .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) .perform(click()) - onView(withId(R.id.action_bar)).check(matches(hasDescendant(withText(containsString("Firefox Preview | OSS Libraries"))))) + onView(withId(R.id.toolbar)).check(matches(hasDescendant(withText(containsString("Firefox Preview | OSS Libraries"))))) Espresso.pressBack() } diff --git a/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt b/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt index f23c51c31..841305b36 100644 --- a/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt +++ b/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt @@ -31,5 +31,6 @@ enum class BrowserDirection(@IdRes val fragmentId: Int) { FromEditCustomSearchEngineFragment(R.id.editCustomSearchEngineFragment), FromAddonDetailsFragment(R.id.addonDetailsFragment), FromAddonPermissionsDetailsFragment(R.id.addonPermissionsDetailFragment), - FromLoginDetailFragment(R.id.loginDetailFragment) + FromLoginDetailFragment(R.id.loginDetailFragment), + FromTabTray(R.id.tabTrayDialogFragment) } diff --git a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt index c3b944f2e..352f44a44 100644 --- a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt +++ b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt @@ -20,14 +20,11 @@ object FeatureFlags { const val loginsEdit = true /** - * Enable tab sync feature + * Shows Synced Tabs in the tabs tray. + * + * Tracking issue: https://github.com/mozilla-mobile/fenix/issues/13892 */ - const val syncedTabs = true - - /** - * Enables new tab tray pref - */ - val tabTray = Config.channel.isNightlyOrDebug + val syncedTabsInTabsTray = Config.channel.isNightlyOrDebug /** * Enables viewing tab history @@ -48,4 +45,9 @@ object FeatureFlags { * Enables downloads with external download managers. */ val externalDownloadManager = Config.channel.isNightlyOrDebug + + /** + * Enables viewing downloads in browser. + */ + val viewDownloads = Config.channel.isNightlyOrDebug } diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 02496dca7..86f26ed9e 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -100,6 +100,7 @@ import org.mozilla.fenix.settings.search.EditCustomSearchEngineFragmentDirection import org.mozilla.fenix.share.AddNewDeviceFragmentDirections import org.mozilla.fenix.sync.SyncedTabsFragmentDirections import org.mozilla.fenix.tabtray.TabTrayDialogFragment +import org.mozilla.fenix.tabtray.TabTrayDialogFragmentDirections import org.mozilla.fenix.theme.DefaultThemeManager import org.mozilla.fenix.theme.ThemeManager import org.mozilla.fenix.utils.BrowsersCache @@ -597,6 +598,8 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { AddonPermissionsDetailsFragmentDirections.actionGlobalBrowser(customTabSessionId) BrowserDirection.FromLoginDetailFragment -> LoginDetailFragmentDirections.actionGlobalBrowser(customTabSessionId) + BrowserDirection.FromTabTray -> + TabTrayDialogFragmentDirections.actionGlobalBrowser(customTabSessionId) } /** diff --git a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt index f4b5a7710..44f4131fe 100644 --- a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt +++ b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt @@ -32,7 +32,6 @@ import mozilla.components.service.fxa.sync.GlobalSyncableStoreProvider import mozilla.components.service.sync.logins.SyncableLoginsStorage import mozilla.components.support.utils.RunWhenReadyQueue import org.mozilla.fenix.Config -import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.MetricController @@ -85,11 +84,8 @@ class BackgroundServices( ) @VisibleForTesting - val supportedEngines = if (FeatureFlags.syncedTabs) { + val supportedEngines = setOf(SyncEngine.History, SyncEngine.Bookmarks, SyncEngine.Passwords, SyncEngine.Tabs) - } else { - setOf(SyncEngine.History, SyncEngine.Bookmarks, SyncEngine.Passwords) - } private val syncConfig = SyncConfig(supportedEngines, syncPeriodInMinutes = 240L) // four hours init { @@ -98,10 +94,7 @@ class BackgroundServices( GlobalSyncableStoreProvider.configureStore(SyncEngine.History to historyStorage) GlobalSyncableStoreProvider.configureStore(SyncEngine.Bookmarks to bookmarkStorage) GlobalSyncableStoreProvider.configureStore(SyncEngine.Passwords to passwordsStorage) - - if (FeatureFlags.syncedTabs) { - GlobalSyncableStoreProvider.configureStore(SyncEngine.Tabs to remoteTabsStorage) - } + GlobalSyncableStoreProvider.configureStore(SyncEngine.Tabs to remoteTabsStorage) } private val telemetryAccountObserver = TelemetryAccountObserver( 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 83d5ef93d..6039adc8c 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 @@ -488,7 +488,7 @@ sealed class Event { NEW_PRIVATE_TAB, SHARE, BACK, FORWARD, RELOAD, STOP, OPEN_IN_FENIX, SAVE_TO_COLLECTION, ADD_TO_TOP_SITES, ADD_TO_HOMESCREEN, QUIT, READER_MODE_ON, READER_MODE_OFF, OPEN_IN_APP, BOOKMARK, READER_MODE_APPEARANCE, ADDONS_MANAGER, - BOOKMARKS, HISTORY, SYNC_TABS + BOOKMARKS, HISTORY, SYNC_TABS, DOWNLOADS } override val extras: Map? diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt index 5fd5b8ec6..436b8136d 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt @@ -380,6 +380,13 @@ class DefaultBrowserToolbarController( BrowserFragmentDirections.actionGlobalHistoryFragment() ) } + + ToolbarMenu.Item.Downloads -> browserAnimator.captureEngineViewAndDrawStatically { + navController.nav( + R.id.browserFragment, + BrowserFragmentDirections.actionGlobalDownloadsFragment() + ) + } } } @@ -414,6 +421,7 @@ class DefaultBrowserToolbarController( ToolbarMenu.Item.AddonsManager -> Event.BrowserMenuItemTapped.Item.ADDONS_MANAGER ToolbarMenu.Item.Bookmarks -> Event.BrowserMenuItemTapped.Item.BOOKMARKS ToolbarMenu.Item.History -> Event.BrowserMenuItemTapped.Item.HISTORY + ToolbarMenu.Item.Downloads -> Event.BrowserMenuItemTapped.Item.DOWNLOADS } activity.components.analytics.metrics.track(Event.BrowserMenuItemTapped(eventItem)) diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt index dc98afa23..4ae5b3f59 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt @@ -24,7 +24,6 @@ import mozilla.components.browser.state.selector.findTab import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.storage.BookmarksStorage import mozilla.components.support.ktx.android.content.getColorFromAttr -import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode @@ -177,11 +176,14 @@ class DefaultToolbarMenu( ?.browsingModeManager?.mode == BrowsingMode.Normal val shouldDeleteDataOnQuit = context.components.settings .shouldDeleteBrowsingDataOnQuit + val syncedTabsInTabsTray = context.components.settings + .syncedTabsInTabsTray val menuItems = listOfNotNull( + if (FeatureFlags.viewDownloads) downloadsItem else null, historyItem, bookmarksItem, - if (FeatureFlags.syncedTabs) syncedTabs else null, + if (syncedTabsInTabsTray) null else syncedTabs, settings, if (shouldDeleteDataOnQuit) deleteDataOnQuit else null, BrowserMenuDivider(), @@ -333,6 +335,14 @@ class DefaultToolbarMenu( onItemTapped.invoke(ToolbarMenu.Item.Bookmarks) } + val downloadsItem = BrowserMenuImageText( + "Downloads", + R.drawable.ic_download, + primaryTextColor() + ) { + onItemTapped.invoke(ToolbarMenu.Item.Downloads) + } + @ColorRes private fun primaryTextColor() = ThemeManager.resolveAttribute(R.attr.primaryText, context) diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt index 5a8d88b13..27b47c309 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt @@ -30,6 +30,7 @@ interface ToolbarMenu { object ReaderModeAppearance : Item() object Bookmarks : Item() object History : Item() + object Downloads : Item() } val menuBuilder: BrowserMenuBuilder diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 1becb7b8d..a914d33b1 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -771,6 +771,15 @@ class HomeFragment : Fragment() { HomeFragmentDirections.actionGlobalHistoryFragment() ) } + + HomeMenu.Item.Downloads -> { + hideOnboardingIfNeeded() + nav( + R.id.homeFragment, + HomeFragmentDirections.actionGlobalDownloadsFragment() + ) + } + HomeMenu.Item.Help -> { hideOnboardingIfNeeded() (activity as HomeActivity).openToBrowserAndLoad( diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt b/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt index 1ab68040b..8036399ea 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt @@ -21,7 +21,6 @@ import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.AuthType import mozilla.components.concept.sync.OAuthAccount import mozilla.components.support.ktx.android.content.getColorFromAttr -import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings @@ -43,6 +42,7 @@ class HomeMenu( object SyncedTabs : Item() object History : Item() object Bookmarks : Item() + object Downloads : Item() object Quit : Item() object Sync : Item() } @@ -144,6 +144,14 @@ class HomeMenu( onItemTapped.invoke(Item.Help) } + val downloadsItem = BrowserMenuImageText( + "Downloads", + R.drawable.ic_download, + primaryTextColor + ) { + onItemTapped.invoke(Item.Downloads) + } + // Only query account manager if it has been initialized. // We don't want to cause its initialization just for this check. val accountAuthItem = if (context.components.backgroundServices.accountManagerAvailableQueue.isReady()) { @@ -158,9 +166,10 @@ class HomeMenu( if (settings.shouldDeleteBrowsingDataOnQuit) quitItem else null, settingsItem, BrowserMenuDivider(), - if (FeatureFlags.syncedTabs) syncedTabsItem else null, + if (settings.syncedTabsInTabsTray) null else syncedTabsItem, bookmarksItem, historyItem, + if (FeatureFlags.viewDownloads) downloadsItem else null, BrowserMenuDivider(), addons, BrowserMenuDivider(), diff --git a/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadAdapter.kt b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadAdapter.kt new file mode 100644 index 000000000..95ce6f247 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadAdapter.kt @@ -0,0 +1,41 @@ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.library.downloads + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import org.mozilla.fenix.library.SelectionHolder +import org.mozilla.fenix.library.downloads.viewholders.DownloadsListItemViewHolder + +class DownloadAdapter( + private val downloadInteractor: DownloadInteractor +) : RecyclerView.Adapter(), SelectionHolder { + private var downloads: List = listOf() + private var mode: DownloadFragmentState.Mode = DownloadFragmentState.Mode.Normal + override val selectedItems get() = mode.selectedItems + + override fun getItemCount(): Int = downloads.size + override fun getItemViewType(position: Int): Int = DownloadsListItemViewHolder.LAYOUT_ID + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DownloadsListItemViewHolder { + val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false) + return DownloadsListItemViewHolder(view, downloadInteractor, this) + } + + fun updateMode(mode: DownloadFragmentState.Mode) { + this.mode = mode + } + + override fun onBindViewHolder(holder: DownloadsListItemViewHolder, position: Int) { + holder.bind(downloads[position]) + } + + fun updateDownloads(downloads: List) { + this.downloads = downloads + notifyDataSetChanged() + } +} diff --git a/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadController.kt b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadController.kt new file mode 100644 index 000000000..9cc676272 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadController.kt @@ -0,0 +1,31 @@ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.library.downloads + +import org.mozilla.fenix.browser.browsingmode.BrowsingMode + +interface DownloadController { + fun handleOpen(item: DownloadItem, mode: BrowsingMode? = null) + fun handleBackPressed(): Boolean +} + +class DefaultDownloadController( + private val store: DownloadFragmentStore, + private val openToFileManager: (item: DownloadItem, mode: BrowsingMode?) -> Unit +) : DownloadController { + override fun handleOpen(item: DownloadItem, mode: BrowsingMode?) { + openToFileManager(item, mode) + } + + override fun handleBackPressed(): Boolean { + return if (store.state.mode is DownloadFragmentState.Mode.Editing) { + store.dispatch(DownloadFragmentAction.ExitEditMode) + true + } else { + false + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragment.kt b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragment.kt new file mode 100644 index 000000000..82ed98e0a --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragment.kt @@ -0,0 +1,108 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.library.downloads + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import kotlinx.android.synthetic.main.fragment_downloads.view.* +import kotlinx.coroutines.ExperimentalCoroutinesApi +import mozilla.components.feature.downloads.AbstractFetchDownloadService +import mozilla.components.lib.state.ext.consumeFrom +import mozilla.components.support.base.feature.UserInteractionHandler +import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.R +import org.mozilla.fenix.browser.browsingmode.BrowsingMode +import org.mozilla.fenix.components.StoreProvider +import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.ext.requireComponents +import org.mozilla.fenix.ext.showToolbar +import org.mozilla.fenix.library.LibraryPageFragment + +@SuppressWarnings("TooManyFunctions", "LargeClass") +class DownloadFragment : LibraryPageFragment(), UserInteractionHandler { + private lateinit var downloadStore: DownloadFragmentStore + private lateinit var downloadView: DownloadView + private lateinit var downloadInteractor: DownloadInteractor + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val view = inflater.inflate(R.layout.fragment_downloads, container, false) + + val items = requireComponents.core.store.state.downloads.map { + DownloadItem( + it.value.id, + it.value.fileName, + it.value.filePath, + it.value.contentLength.toString(), + it.value.contentType + ) + } + + downloadStore = StoreProvider.get(this) { + DownloadFragmentStore( + DownloadFragmentState( + items = items, + mode = DownloadFragmentState.Mode.Normal + ) + ) + } + + val downloadController: DownloadController = DefaultDownloadController( + downloadStore, + ::openItem + ) + downloadInteractor = DownloadInteractor( + downloadController + ) + downloadView = DownloadView(view.downloadsLayout, downloadInteractor) + + return view + } + + override val selectedItems get() = downloadStore.state.mode.selectedItems + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + requireComponents.analytics.metrics.track(Event.HistoryOpened) + + setHasOptionsMenu(false) + } + + @ExperimentalCoroutinesApi + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + consumeFrom(downloadStore) { + downloadView.update(it) + } + } + + override fun onResume() { + super.onResume() + showToolbar(getString(R.string.library_downloads)) + } + + override fun onBackPressed(): Boolean { + return downloadView.onBackPressed() + } + + private fun openItem(item: DownloadItem, mode: BrowsingMode? = null) { + + mode?.let { (activity as HomeActivity).browsingModeManager.mode = it } + context?.let { + AbstractFetchDownloadService.openFile( + context = it, + contentType = item.contentType, + filePath = item.filePath + ) + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragmentStore.kt b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragmentStore.kt new file mode 100644 index 000000000..2078064a7 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragmentStore.kt @@ -0,0 +1,61 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.library.downloads + +import mozilla.components.lib.state.Action +import mozilla.components.lib.state.State +import mozilla.components.lib.state.Store + +/** + * Class representing a history entry + * @property id Unique id of the download item + * @property fileName File name of the download item + * @property filePath Full path of the download item + * @property size The size in bytes of the download item + * @property contentType The type of file the download is + */ +data class DownloadItem(val id: Long, val fileName: String?, val filePath: String, val size: String, val contentType: String?) + +/** + * The [Store] for holding the [DownloadFragmentState] and applying [DownloadFragmentAction]s. + */ +class DownloadFragmentStore(initialState: DownloadFragmentState) : + Store(initialState, ::downloadStateReducer) + +/** + * Actions to dispatch through the `DownloadStore` to modify `DownloadState` through the reducer. + */ +sealed class DownloadFragmentAction : Action { + object ExitEditMode : DownloadFragmentAction() +} + +/** + * The state for the Download Screen + * @property items List of DownloadItem to display + * @property mode Current Mode of Download + */ +data class DownloadFragmentState( + val items: List, + val mode: Mode +) : State { + sealed class Mode { + open val selectedItems = emptySet() + + object Normal : Mode() + data class Editing(override val selectedItems: Set) : DownloadFragmentState.Mode() + } +} + +/** + * The DownloadState Reducer. + */ +private fun downloadStateReducer( + state: DownloadFragmentState, + action: DownloadFragmentAction +): DownloadFragmentState { + return when (action) { + is DownloadFragmentAction.ExitEditMode -> state.copy(mode = DownloadFragmentState.Mode.Normal) + } +} diff --git a/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadInteractor.kt b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadInteractor.kt new file mode 100644 index 000000000..244444634 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadInteractor.kt @@ -0,0 +1,29 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.library.downloads +/** + * Interactor for the download screen + * Provides implementations for the DownloadViewInteractor + */ +@SuppressWarnings("TooManyFunctions") +class DownloadInteractor( + private val downloadController: DownloadController +) : DownloadViewInteractor { + override fun open(item: DownloadItem) { + downloadController.handleOpen(item) + } + + override fun select(item: DownloadItem) { + TODO("Not yet implemented") + } + + override fun deselect(item: DownloadItem) { + TODO("Not yet implemented") + } + + override fun onBackPressed(): Boolean { + return downloadController.handleBackPressed() + } +} diff --git a/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadView.kt b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadView.kt new file mode 100644 index 000000000..3261ee91e --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadView.kt @@ -0,0 +1,74 @@ + + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.library.downloads + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.SimpleItemAnimator +import kotlinx.android.synthetic.main.component_downloads.view.* +import mozilla.components.support.base.feature.UserInteractionHandler +import org.mozilla.fenix.R +import org.mozilla.fenix.library.LibraryPageView +import org.mozilla.fenix.library.SelectionInteractor + +/** + * Interface for the DownloadViewInteractor. This interface is implemented by objects that want + * to respond to user interaction on the DownloadView + */ +interface DownloadViewInteractor : SelectionInteractor { + + /** + * Called on backpressed to exit edit mode + */ + fun onBackPressed(): Boolean +} + +/** + * View that contains and configures the Downloads List + */ +class DownloadView( + container: ViewGroup, + val interactor: DownloadInteractor +) : LibraryPageView(container), UserInteractionHandler { + + val view: View = LayoutInflater.from(container.context) + .inflate(R.layout.component_downloads, container, true) + + var mode: DownloadFragmentState.Mode = DownloadFragmentState.Mode.Normal + private set + + val downloadAdapter = DownloadAdapter(interactor) + private val layoutManager = LinearLayoutManager(container.context) + + init { + view.download_list.apply { + layoutManager = this@DownloadView.layoutManager + adapter = downloadAdapter + (itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false + } + } + + fun update(state: DownloadFragmentState) { + + view.swipe_refresh.isEnabled = + state.mode === DownloadFragmentState.Mode.Normal + mode = state.mode + + downloadAdapter.updateMode(state.mode) + downloadAdapter.updateDownloads(state.items) + + setUiForNormalMode( + context.getString(R.string.library_downloads) + ) + } + + override fun onBackPressed(): Boolean { + return interactor.onBackPressed() + } +} diff --git a/app/src/main/java/org/mozilla/fenix/library/downloads/viewholders/DownloadsListItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/downloads/viewholders/DownloadsListItemViewHolder.kt new file mode 100644 index 000000000..4126b2cd7 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/library/downloads/viewholders/DownloadsListItemViewHolder.kt @@ -0,0 +1,46 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.library.downloads.viewholders + +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import kotlinx.android.synthetic.main.download_list_item.view.* +import kotlinx.android.synthetic.main.library_site_item.view.* +import org.mozilla.fenix.R +import org.mozilla.fenix.ext.hideAndDisable +import org.mozilla.fenix.library.SelectionHolder +import org.mozilla.fenix.library.downloads.DownloadInteractor +import org.mozilla.fenix.library.downloads.DownloadItem +import mozilla.components.feature.downloads.toMegabyteString + +class DownloadsListItemViewHolder( + view: View, + private val downloadInteractor: DownloadInteractor, + private val selectionHolder: SelectionHolder +) : RecyclerView.ViewHolder(view) { + + private var item: DownloadItem? = null + + fun bind( + item: DownloadItem + ) { + itemView.download_layout.visibility = View.VISIBLE + itemView.download_layout.titleView.text = item.fileName + itemView.download_layout.urlView.text = item.size.toLong().toMegabyteString() + + itemView.download_layout.setSelectionInteractor(item, selectionHolder, downloadInteractor) + itemView.download_layout.changeSelected(item in selectionHolder.selectedItems) + + itemView.overflow_menu.hideAndDisable() + itemView.favicon.setImageResource(R.drawable.ic_download_default) + itemView.favicon.isClickable = false + + this.item = item + } + + companion object { + const val LAYOUT_ID = R.layout.download_list_item + } +} diff --git a/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt index c3e663104..7040af768 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt @@ -36,5 +36,11 @@ class SecretSettingsFragment : PreferenceFragmentCompat() { isChecked = context.settings().waitToShowPageUntilFirstPaint onPreferenceChangeListener = SharedPreferenceUpdater() } + + requirePreference(R.string.pref_key_synced_tabs_tabs_tray).apply { + isVisible = FeatureFlags.syncedTabsInTabsTray + isChecked = context.settings().syncedTabsInTabsTray + onPreferenceChangeListener = SharedPreferenceUpdater() + } } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt index f74e27bb4..38dc05b83 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -270,6 +270,13 @@ class SettingsFragment : PreferenceFragmentCompat() { resources.getString(R.string.pref_key_delete_browsing_data_on_quit_preference) -> { SettingsFragmentDirections.actionSettingsFragmentToDeleteBrowsingDataOnQuitFragment() } + resources.getString(R.string.pref_key_notifications) -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) + startActivity(intent) + } + null + } resources.getString(R.string.pref_key_customize) -> { SettingsFragmentDirections.actionSettingsFragmentToCustomizationFragment() } @@ -352,6 +359,10 @@ class SettingsFragment : PreferenceFragmentCompat() { findPreference( getPreferenceKey(R.string.pref_key_debug_settings) )?.isVisible = requireContext().settings().showSecretDebugMenuThisSession + + findPreference( + getPreferenceKey(R.string.pref_key_notifications) + )?.isVisible = requireContext().settings().showNotificationsSetting } private fun getClickListenerForMakeDefaultBrowser(): Preference.OnPreferenceClickListener { diff --git a/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt index 0eab4909c..732f89671 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt @@ -36,7 +36,6 @@ import mozilla.components.service.fxa.sync.SyncStatusObserver import mozilla.components.service.fxa.sync.getLastSynced import mozilla.components.support.ktx.android.content.getColorFromAttr import mozilla.components.support.ktx.android.util.dpToPx -import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.StoreProvider @@ -271,9 +270,8 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { isChecked = syncEnginesStatus.getOrElse(SyncEngine.Passwords) { true } } requirePreference(R.string.pref_key_sync_tabs).apply { - isVisible = FeatureFlags.syncedTabs isEnabled = syncEnginesStatus.containsKey(SyncEngine.Tabs) - isChecked = syncEnginesStatus.getOrElse(SyncEngine.Tabs) { FeatureFlags.syncedTabs } + isChecked = syncEnginesStatus.getOrElse(SyncEngine.Tabs) { true } } } diff --git a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsAdapter.kt b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsAdapter.kt index e51419df4..6e30a4711 100644 --- a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsAdapter.kt @@ -10,14 +10,18 @@ import androidx.navigation.NavController import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import mozilla.components.browser.storage.sync.SyncedDeviceTabs +import mozilla.components.feature.syncedtabs.view.SyncedTabsView import org.mozilla.fenix.sync.SyncedTabsViewHolder.DeviceViewHolder import org.mozilla.fenix.sync.SyncedTabsViewHolder.ErrorViewHolder +import org.mozilla.fenix.sync.SyncedTabsViewHolder.NoTabsViewHolder import org.mozilla.fenix.sync.SyncedTabsViewHolder.TabViewHolder +import org.mozilla.fenix.sync.SyncedTabsViewHolder.TitleViewHolder +import org.mozilla.fenix.sync.ext.toAdapterList import mozilla.components.browser.storage.sync.Tab as SyncTab import mozilla.components.concept.sync.Device as SyncDevice class SyncedTabsAdapter( - private val listener: (SyncTab) -> Unit + private val newListener: SyncedTabsView.Listener ) : ListAdapter(DiffCallback) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SyncedTabsViewHolder { @@ -27,30 +31,26 @@ class SyncedTabsAdapter( DeviceViewHolder.LAYOUT_ID -> DeviceViewHolder(itemView) TabViewHolder.LAYOUT_ID -> TabViewHolder(itemView) ErrorViewHolder.LAYOUT_ID -> ErrorViewHolder(itemView) + TitleViewHolder.LAYOUT_ID -> TitleViewHolder(itemView) + NoTabsViewHolder.LAYOUT_ID -> NoTabsViewHolder(itemView) else -> throw IllegalStateException() } } override fun onBindViewHolder(holder: SyncedTabsViewHolder, position: Int) { - holder.bind(getItem(position), listener) + holder.bind(getItem(position), newListener) } override fun getItemViewType(position: Int) = when (getItem(position)) { is AdapterItem.Device -> DeviceViewHolder.LAYOUT_ID is AdapterItem.Tab -> TabViewHolder.LAYOUT_ID is AdapterItem.Error -> ErrorViewHolder.LAYOUT_ID + is AdapterItem.Title -> TitleViewHolder.LAYOUT_ID + is AdapterItem.NoTabs -> NoTabsViewHolder.LAYOUT_ID } fun updateData(syncedTabs: List) { - val allDeviceTabs = mutableListOf() - - syncedTabs.forEach { (device, tabs) -> - if (tabs.isNotEmpty()) { - allDeviceTabs.add(AdapterItem.Device(device)) - tabs.mapTo(allDeviceTabs) { AdapterItem.Tab(it) } - } - } - + val allDeviceTabs = syncedTabs.toAdapterList() submitList(allDeviceTabs) } @@ -59,7 +59,11 @@ class SyncedTabsAdapter( when (oldItem) { is AdapterItem.Device -> newItem is AdapterItem.Device && oldItem.device.id == newItem.device.id - is AdapterItem.Tab, is AdapterItem.Error -> + is AdapterItem.NoTabs -> + newItem is AdapterItem.NoTabs && oldItem.device.id == newItem.device.id + is AdapterItem.Tab, + is AdapterItem.Error, + is AdapterItem.Title -> oldItem == newItem } @@ -68,9 +72,35 @@ class SyncedTabsAdapter( oldItem == newItem } + /** + * The various types of adapter items that can be found in a [SyncedTabsAdapter]. + */ sealed class AdapterItem { + + /** + * A title header of the Synced Tabs UI that has a refresh button in it. This may be seen + * only in some views depending on where the Synced Tabs UI is displayed. + */ + object Title : AdapterItem() + + /** + * A device header for displaying a synced device. + */ data class Device(val device: SyncDevice) : AdapterItem() + + /** + * A tab that was synced. + */ data class Tab(val tab: SyncTab) : AdapterItem() + + /** + * A placeholder for a device that has no tabs synced. + */ + data class NoTabs(val device: SyncDevice) : AdapterItem() + + /** + * A message displayed if an error was encountered. + */ data class Error( val descriptionResId: Int, val navController: NavController? = null diff --git a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsFragment.kt b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsFragment.kt index 4059d5159..cd67fe06b 100644 --- a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsFragment.kt @@ -13,6 +13,7 @@ import mozilla.components.browser.storage.sync.Tab import mozilla.components.feature.syncedtabs.SyncedTabsFeature import mozilla.components.support.base.feature.ViewBoundFeatureWrapper import org.mozilla.fenix.BrowserDirection +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.ext.components @@ -22,6 +23,11 @@ import org.mozilla.fenix.library.LibraryPageFragment class SyncedTabsFragment : LibraryPageFragment() { private val syncedTabsFeature = ViewBoundFeatureWrapper() + init { + // Sanity-check: Remove this class when the feature flag is always enabled. + FeatureFlags.syncedTabsInTabsTray + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, diff --git a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsLayout.kt b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsLayout.kt index 8308692ba..2d3b5c0a4 100644 --- a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsLayout.kt +++ b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsLayout.kt @@ -7,7 +7,6 @@ package org.mozilla.fenix.sync import android.content.Context import android.util.AttributeSet import android.widget.FrameLayout -import androidx.annotation.StringRes import androidx.fragment.app.findFragment import androidx.navigation.NavController import androidx.navigation.fragment.findNavController @@ -18,8 +17,12 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import mozilla.components.browser.storage.sync.SyncedDeviceTabs +import mozilla.components.browser.storage.sync.Tab import mozilla.components.feature.syncedtabs.view.SyncedTabsView +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R +import org.mozilla.fenix.sync.ext.toAdapterItem +import org.mozilla.fenix.sync.ext.toStringRes import java.lang.IllegalStateException class SyncedTabsLayout @JvmOverloads constructor( @@ -30,7 +33,7 @@ class SyncedTabsLayout @JvmOverloads constructor( override var listener: SyncedTabsView.Listener? = null - private val adapter = SyncedTabsAdapter { listener?.onTabClicked(it) } + private val adapter = SyncedTabsAdapter(ListenerDelegate { listener }) private val coroutineScope = CoroutineScope(Dispatchers.Main) init { @@ -40,6 +43,9 @@ class SyncedTabsLayout @JvmOverloads constructor( synced_tabs_list.adapter = adapter synced_tabs_pull_to_refresh.setOnRefreshListener { listener?.onRefresh() } + + // Sanity-check: Remove this class when the feature flag is always enabled. + FeatureFlags.syncedTabsInTabsTray } override fun onError(error: SyncedTabsView.ErrorType) { @@ -53,8 +59,8 @@ class SyncedTabsLayout @JvmOverloads constructor( null } - val descriptionResId = stringResourceForError(error) - val errorItem = getErrorItem(navController, error, descriptionResId) + val descriptionResId = error.toStringRes() + val errorItem = error.toAdapterItem(descriptionResId, navController) val errorList: List = listOf(errorItem) adapter.submitList(errorList) @@ -96,27 +102,21 @@ class SyncedTabsLayout @JvmOverloads constructor( SyncedTabsView.ErrorType.MULTIPLE_DEVICES_UNAVAILABLE, SyncedTabsView.ErrorType.NO_TABS_AVAILABLE -> true } - - internal fun stringResourceForError(error: SyncedTabsView.ErrorType) = when (error) { - SyncedTabsView.ErrorType.MULTIPLE_DEVICES_UNAVAILABLE -> R.string.synced_tabs_connect_another_device - SyncedTabsView.ErrorType.SYNC_ENGINE_UNAVAILABLE -> R.string.synced_tabs_enable_tab_syncing - SyncedTabsView.ErrorType.SYNC_UNAVAILABLE -> R.string.synced_tabs_sign_in_message - SyncedTabsView.ErrorType.SYNC_NEEDS_REAUTHENTICATION -> R.string.synced_tabs_reauth - SyncedTabsView.ErrorType.NO_TABS_AVAILABLE -> R.string.synced_tabs_no_tabs - } - - internal fun getErrorItem( - navController: NavController?, - error: SyncedTabsView.ErrorType, - @StringRes stringResId: Int - ): SyncedTabsAdapter.AdapterItem = when (error) { - SyncedTabsView.ErrorType.MULTIPLE_DEVICES_UNAVAILABLE, - SyncedTabsView.ErrorType.SYNC_ENGINE_UNAVAILABLE, - SyncedTabsView.ErrorType.SYNC_NEEDS_REAUTHENTICATION, - SyncedTabsView.ErrorType.NO_TABS_AVAILABLE -> SyncedTabsAdapter.AdapterItem - .Error(descriptionResId = stringResId) - SyncedTabsView.ErrorType.SYNC_UNAVAILABLE -> SyncedTabsAdapter.AdapterItem - .Error(descriptionResId = stringResId, navController = navController) - } + } +} + +/** + * We have to do this weird daisy-chaining of callbacks because the listener is nullable and + * when we get a null reference, we never get a new binding to the non-null listener. + */ +class ListenerDelegate( + private val listener: (() -> SyncedTabsView.Listener?) +) : SyncedTabsView.Listener { + override fun onRefresh() { + listener.invoke()?.onRefresh() + } + + override fun onTabClicked(tab: Tab) { + listener.invoke()?.onTabClicked(tab) } } diff --git a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsViewHolder.kt b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsViewHolder.kt index 95abada88..4549f570e 100644 --- a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsViewHolder.kt @@ -7,29 +7,36 @@ package org.mozilla.fenix.sync import android.view.View import android.view.View.GONE import android.view.View.VISIBLE +import android.view.animation.Animation +import android.view.animation.AnimationUtils import android.widget.LinearLayout import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.sync_tabs_error_row.view.* import kotlinx.android.synthetic.main.sync_tabs_list_item.view.* import kotlinx.android.synthetic.main.view_synced_tabs_group.view.* -import mozilla.components.browser.storage.sync.Tab +import kotlinx.android.synthetic.main.view_synced_tabs_title.view.* import mozilla.components.concept.sync.DeviceType +import mozilla.components.feature.syncedtabs.view.SyncedTabsView import mozilla.components.support.ktx.android.util.dpToPx import org.mozilla.fenix.NavGraphDirections import org.mozilla.fenix.R import org.mozilla.fenix.sync.SyncedTabsAdapter.AdapterItem +/** + * The various view-holders that can be found in a [SyncedTabsAdapter]. For more + * descriptive information on the different types, see the docs for [AdapterItem]. + */ sealed class SyncedTabsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - abstract fun bind(item: T, interactor: (Tab) -> Unit) + abstract fun bind(item: T, interactor: SyncedTabsView.Listener) class TabViewHolder(itemView: View) : SyncedTabsViewHolder(itemView) { - override fun bind(item: T, interactor: (Tab) -> Unit) { + override fun bind(item: T, interactor: SyncedTabsView.Listener) { bindTab(item as AdapterItem.Tab) itemView.setOnClickListener { - interactor(item.tab) + interactor.onTabClicked(item.tab) } } @@ -46,7 +53,7 @@ sealed class SyncedTabsViewHolder(itemView: View) : RecyclerView.ViewHolder(item class ErrorViewHolder(itemView: View) : SyncedTabsViewHolder(itemView) { - override fun bind(item: T, interactor: (Tab) -> Unit) { + override fun bind(item: T, interactor: SyncedTabsView.Listener) { val errorItem = item as AdapterItem.Error setErrorMargins() @@ -69,7 +76,7 @@ sealed class SyncedTabsViewHolder(itemView: View) : RecyclerView.ViewHolder(item class DeviceViewHolder(itemView: View) : SyncedTabsViewHolder(itemView) { - override fun bind(item: T, interactor: (Tab) -> Unit) { + override fun bind(item: T, interactor: SyncedTabsView.Listener) { bindHeader(item as AdapterItem.Device) } @@ -93,6 +100,36 @@ sealed class SyncedTabsViewHolder(itemView: View) : RecyclerView.ViewHolder(item } } + class NoTabsViewHolder(itemView: View) : SyncedTabsViewHolder(itemView) { + override fun bind(item: T, interactor: SyncedTabsView.Listener) = Unit + + companion object { + const val LAYOUT_ID = R.layout.view_synced_tabs_no_item + } + } + + class TitleViewHolder(itemView: View) : SyncedTabsViewHolder(itemView) { + + override fun bind(item: T, interactor: SyncedTabsView.Listener) { + itemView.refresh_icon.setOnClickListener { v -> + val rotation = AnimationUtils.loadAnimation( + itemView.context, + R.anim.full_rotation + ).apply { + repeatCount = Animation.ABSOLUTE + } + + v.startAnimation(rotation) + + interactor.onRefresh() + } + } + + companion object { + const val LAYOUT_ID = R.layout.view_synced_tabs_title + } + } + internal fun setErrorMargins() { val lp = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, diff --git a/app/src/main/java/org/mozilla/fenix/sync/ext/ErrorType.kt b/app/src/main/java/org/mozilla/fenix/sync/ext/ErrorType.kt new file mode 100644 index 000000000..1a24ba455 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/sync/ext/ErrorType.kt @@ -0,0 +1,38 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.sync.ext + +import androidx.annotation.StringRes +import androidx.navigation.NavController +import mozilla.components.feature.syncedtabs.view.SyncedTabsView.ErrorType +import org.mozilla.fenix.R +import org.mozilla.fenix.sync.SyncedTabsAdapter + +/** + * Converts the error type to the appropriate matching string resource for displaying to the user. + */ +fun ErrorType.toStringRes() = when (this) { + ErrorType.MULTIPLE_DEVICES_UNAVAILABLE -> R.string.synced_tabs_connect_another_device + ErrorType.SYNC_ENGINE_UNAVAILABLE -> R.string.synced_tabs_enable_tab_syncing + ErrorType.SYNC_UNAVAILABLE -> R.string.synced_tabs_sign_in_message + ErrorType.SYNC_NEEDS_REAUTHENTICATION -> R.string.synced_tabs_reauth + ErrorType.NO_TABS_AVAILABLE -> R.string.synced_tabs_no_tabs +} + +/** + * Converts an error type to an [SyncedTabsAdapter.AdapterItem.Error]. + */ +fun ErrorType.toAdapterItem( + @StringRes stringResId: Int, + navController: NavController? = null +) = when (this) { + ErrorType.MULTIPLE_DEVICES_UNAVAILABLE, + ErrorType.SYNC_ENGINE_UNAVAILABLE, + ErrorType.SYNC_NEEDS_REAUTHENTICATION, + ErrorType.NO_TABS_AVAILABLE -> SyncedTabsAdapter.AdapterItem + .Error(descriptionResId = stringResId) + ErrorType.SYNC_UNAVAILABLE -> SyncedTabsAdapter.AdapterItem + .Error(descriptionResId = stringResId, navController = navController) +} diff --git a/app/src/main/java/org/mozilla/fenix/sync/ext/SyncedTabsAdapter.kt b/app/src/main/java/org/mozilla/fenix/sync/ext/SyncedTabsAdapter.kt new file mode 100644 index 000000000..18c2c1be9 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/sync/ext/SyncedTabsAdapter.kt @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.sync.ext + +import mozilla.components.browser.storage.sync.SyncedDeviceTabs +import org.mozilla.fenix.sync.SyncedTabsAdapter.AdapterItem + +/** + * Converts a list of [SyncedDeviceTabs] into a list of [AdapterItem]. + */ +fun List.toAdapterList() = asSequence().flatMap { (device, tabs) -> + + val deviceTabs = if (tabs.isEmpty()) { + sequenceOf(AdapterItem.NoTabs(device)) + } else { + tabs.asSequence().map { AdapterItem.Tab(it) } + } + + sequenceOf(AdapterItem.Device(device)) + deviceTabs +}.toList() diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/SyncedTabsController.kt b/app/src/main/java/org/mozilla/fenix/tabtray/SyncedTabsController.kt new file mode 100644 index 000000000..8fbb87c63 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/tabtray/SyncedTabsController.kt @@ -0,0 +1,85 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.tabtray + +import android.view.View +import androidx.fragment.app.FragmentManager.findFragment +import androidx.lifecycle.LifecycleOwner +import androidx.navigation.NavController +import androidx.navigation.fragment.findNavController +import androidx.recyclerview.widget.ConcatAdapter +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.drop +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch +import mozilla.components.browser.storage.sync.SyncedDeviceTabs +import mozilla.components.feature.syncedtabs.view.SyncedTabsView +import mozilla.components.lib.state.ext.flowScoped +import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged +import org.mozilla.fenix.sync.ListenerDelegate +import org.mozilla.fenix.sync.SyncedTabsAdapter +import org.mozilla.fenix.sync.ext.toAdapterList +import org.mozilla.fenix.sync.ext.toAdapterItem +import org.mozilla.fenix.sync.ext.toStringRes +import kotlin.coroutines.CoroutineContext + +@OptIn(ExperimentalCoroutinesApi::class) +class SyncedTabsController( + lifecycleOwner: LifecycleOwner, + private val view: View, + store: TabTrayDialogFragmentStore, + private val concatAdapter: ConcatAdapter, + coroutineContext: CoroutineContext = Dispatchers.Main +) : SyncedTabsView { + override var listener: SyncedTabsView.Listener? = null + + val adapter = SyncedTabsAdapter(ListenerDelegate { listener }) + + private val scope: CoroutineScope = CoroutineScope(coroutineContext) + + init { + store.flowScoped(lifecycleOwner) { flow -> + flow.map { it.mode } + .ifChanged() + .drop(1) + .collect { mode -> + when (mode) { + is TabTrayDialogFragmentState.Mode.Normal -> { + concatAdapter.addAdapter(0, adapter) + } + is TabTrayDialogFragmentState.Mode.MultiSelect -> { + concatAdapter.removeAdapter(adapter) + } + } + } + } + } + + override fun displaySyncedTabs(syncedTabs: List) { + scope.launch { + val tabsList = listOf(SyncedTabsAdapter.AdapterItem.Title) + syncedTabs.toAdapterList() + // Reverse layout for TabTrayView which does things backwards. + adapter.submitList(tabsList.reversed()) + } + } + + override fun onError(error: SyncedTabsView.ErrorType) { + scope.launch { + val navController: NavController? = try { + findFragment(view).findNavController() + } catch (exception: IllegalStateException) { + null + } + + val descriptionResId = error.toStringRes() + val errorItem = error.toAdapterItem(descriptionResId, navController) + + adapter.submitList(listOf(errorItem)) + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayController.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayController.kt index ad71ced1c..7a3a03eee 100644 --- a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayController.kt +++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayController.kt @@ -9,10 +9,12 @@ import androidx.navigation.NavController import kotlinx.coroutines.ExperimentalCoroutinesApi import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager +import mozilla.components.browser.storage.sync.Tab as SyncTab import mozilla.components.concept.engine.profiler.Profiler import mozilla.components.concept.engine.prompt.ShareData import mozilla.components.concept.tabstray.Tab import mozilla.components.feature.tabs.TabsUseCases +import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager @@ -30,6 +32,7 @@ interface TabTrayController { fun onNewTabTapped(private: Boolean) fun onTabTrayDismissed() fun onShareTabsClicked(private: Boolean) + fun onSyncedTabClicked(syncTab: SyncTab) fun onSaveToCollectionClicked(selectedTabs: Set) fun onCloseAllTabsClicked(private: Boolean) fun handleBackPressed(): Boolean @@ -59,6 +62,7 @@ interface TabTrayController { */ @Suppress("TooManyFunctions") class DefaultTabTrayController( + private val activity: HomeActivity, private val profiler: Profiler?, private val sessionManager: SessionManager, private val browsingModeManager: BrowsingModeManager, @@ -117,6 +121,14 @@ class DefaultTabTrayController( navController.navigate(directions) } + override fun onSyncedTabClicked(syncTab: SyncTab) { + activity.openToBrowserAndLoad( + searchTermOrURL = syncTab.active().url, + newTab = true, + from = BrowserDirection.FromTabTray + ) + } + @OptIn(ExperimentalCoroutinesApi::class) override fun onCloseAllTabsClicked(private: Boolean) { val sessionsToClose = if (private) { diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayDialogFragment.kt index cfe8b0f1c..3b64217f4 100644 --- a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayDialogFragment.kt @@ -177,6 +177,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler adapter, interactor = TabTrayFragmentInteractor( DefaultTabTrayController( + activity = activity, profiler = activity.components.core.engine.profiler, sessionManager = activity.components.core.sessionManager, browsingModeManager = activity.browsingModeManager, @@ -191,10 +192,11 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler showAddNewCollectionDialog = ::showAddNewCollectionDialog ) ), + store = tabTrayDialogStore, isPrivate = isPrivate, startingInLandscape = requireContext().resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE, - lifecycleScope = viewLifecycleOwner.lifecycleScope + lifecycleOwner = viewLifecycleOwner ) { private -> val filter: (TabSessionState) -> Boolean = { state -> private == state.content.private } diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractor.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractor.kt index 33bef403a..b6a65dd77 100644 --- a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractor.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.tabtray import mozilla.components.concept.tabstray.Tab +import mozilla.components.browser.storage.sync.Tab as SyncTab @Suppress("TooManyFunctions") interface TabTrayInteractor { @@ -33,6 +34,11 @@ interface TabTrayInteractor { */ fun onCloseAllTabsClicked(private: Boolean) + /** + * Called when the user clicks on a synced tab entry. + */ + fun onSyncedTabClicked(syncTab: SyncTab) + /** * Called when the physical back button is clicked. */ @@ -89,6 +95,10 @@ class TabTrayFragmentInteractor(private val controller: TabTrayController) : Tab controller.onCloseAllTabsClicked(private) } + override fun onSyncedTabClicked(syncTab: SyncTab) { + controller.onSyncedTabClicked(syncTab) + } + override fun onBackPressed(): Boolean { return controller.handleBackPressed() } diff --git a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt index 9b78836ff..76574c692 100644 --- a/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt +++ b/app/src/main/java/org/mozilla/fenix/tabtray/TabTrayView.kt @@ -16,7 +16,8 @@ import androidx.constraintlayout.widget.ConstraintSet import androidx.core.content.ContextCompat import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams -import androidx.lifecycle.LifecycleCoroutineScope +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.ConcatAdapter import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.bottomsheet.BottomSheetBehavior @@ -35,7 +36,10 @@ import mozilla.components.browser.state.selector.getNormalOrPrivateTabs import mozilla.components.browser.state.selector.normalTabs import mozilla.components.browser.state.selector.privateTabs import mozilla.components.browser.state.state.BrowserState +import mozilla.components.browser.storage.sync.Tab as SyncTab import mozilla.components.browser.tabstray.TabViewHolder +import mozilla.components.feature.syncedtabs.SyncedTabsFeature +import mozilla.components.support.base.feature.ViewBoundFeatureWrapper import mozilla.components.support.ktx.android.util.dpToPx import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event @@ -56,11 +60,13 @@ class TabTrayView( private val container: ViewGroup, private val tabsAdapter: FenixTabsAdapter, private val interactor: TabTrayInteractor, + store: TabTrayDialogFragmentStore, isPrivate: Boolean, startingInLandscape: Boolean, - lifecycleScope: LifecycleCoroutineScope, + lifecycleOwner: LifecycleOwner, private val filterTabs: (Boolean) -> Unit ) : LayoutContainer, TabLayout.OnTabSelectedListener { + val lifecycleScope = lifecycleOwner.lifecycleScope val fabView = LayoutInflater.from(container.context) .inflate(R.layout.component_tabstray_fab, container, true) @@ -73,19 +79,25 @@ class TabTrayView( private val behavior = BottomSheetBehavior.from(view.tab_wrapper) + private val concatAdapter = ConcatAdapter(tabsAdapter) private val tabTrayItemMenu: TabTrayItemMenu private var menu: BrowserMenu? = null private var tabsTouchHelper: TabsTouchHelper private val collectionsButtonAdapter = SaveToCollectionsButtonAdapter(interactor, isPrivate) + private val syncedTabsController = SyncedTabsController(lifecycleOwner, view, store, concatAdapter) + private val syncedTabsFeature = ViewBoundFeatureWrapper() + private var hasLoaded = false override val containerView: View? get() = container + private val components = container.context.components + init { - container.context.components.analytics.metrics.track(Event.TabsTrayOpened) + components.analytics.metrics.track(Event.TabsTrayOpened) toggleFabText(isPrivate) @@ -102,7 +114,7 @@ class TabTrayView( override fun onStateChanged(bottomSheet: View, newState: Int) { if (newState == BottomSheetBehavior.STATE_HIDDEN) { - container.context.components.analytics.metrics.track(Event.TabsTrayClosed) + components.analytics.metrics.track(Event.TabsTrayClosed) interactor.onTabTrayDismissed() } } @@ -135,7 +147,20 @@ class TabTrayView( setTopOffset(startingInLandscape) - val concatAdapter = ConcatAdapter(tabsAdapter) + if (view.context.settings().syncedTabsInTabsTray) { + syncedTabsFeature.set( + feature = SyncedTabsFeature( + context = container.context, + storage = components.backgroundServices.syncedTabsStorage, + accountManager = components.backgroundServices.accountManager, + view = syncedTabsController, + lifecycleOwner = lifecycleOwner, + onTabClicked = ::handleTabClicked + ), + owner = lifecycleOwner, + view = view + ) + } view.tabsTray.apply { layoutManager = LinearLayoutManager(container.context).apply { @@ -156,6 +181,9 @@ class TabTrayView( // Put the 'Add to collections' button after the tabs have loaded. concatAdapter.addAdapter(0, collectionsButtonAdapter) + // Put the Synced Tabs adapter at the end. + concatAdapter.addAdapter(0, syncedTabsController.adapter) + if (hasAccessibilityEnabled) { tabsAdapter.notifyDataSetChanged() } @@ -193,7 +221,7 @@ class TabTrayView( } view.tab_tray_overflow.setOnClickListener { - container.context.components.analytics.metrics.track(Event.TabsTrayMenuOpened) + components.analytics.metrics.track(Event.TabsTrayMenuOpened) menu = tabTrayItemMenu.menuBuilder.build(container.context) menu?.show(it) ?.also { pu -> @@ -209,6 +237,10 @@ class TabTrayView( adjustNewTabButtonsForNormalMode() } + private fun handleTabClicked(tab: SyncTab) { + interactor.onSyncedTabClicked(tab) + } + private fun adjustNewTabButtonsForNormalMode() { view.tab_tray_new_tab.apply { isVisible = hasAccessibilityEnabled @@ -234,7 +266,7 @@ class TabTrayView( Event.NewTabTapped } - container.context.components.analytics.metrics.track(eventToSend) + components.analytics.metrics.track(eventToSend) } fun expand() { @@ -261,17 +293,14 @@ class TabTrayView( scrollToTab(view.context.components.core.store.state.selectedTabId) if (isPrivateModeSelected) { - container.context.components.analytics.metrics.track(Event.TabsTrayPrivateModeTapped) + components.analytics.metrics.track(Event.TabsTrayPrivateModeTapped) } else { - container.context.components.analytics.metrics.track(Event.TabsTrayNormalModeTapped) + components.analytics.metrics.track(Event.TabsTrayNormalModeTapped) } } - override fun onTabReselected(tab: TabLayout.Tab?) { /*noop*/ - } - - override fun onTabUnselected(tab: TabLayout.Tab?) { /*noop*/ - } + override fun onTabReselected(tab: TabLayout.Tab?) = Unit + override fun onTabUnselected(tab: TabLayout.Tab?) = Unit var mode: Mode = Mode.Normal private set @@ -513,7 +542,9 @@ class TabTrayView( // We offset the tab index by the number of items in the other adapters. // We add the offset, because the layoutManager is initialized with `reverseLayout`. - val recyclerViewIndex = selectedBrowserTabIndex + collectionsButtonAdapter.itemCount + val recyclerViewIndex = selectedBrowserTabIndex + + collectionsButtonAdapter.itemCount + + syncedTabsController.adapter.itemCount layoutManager?.scrollToPosition(recyclerViewIndex) } diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index ba2390b3f..885720d07 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -109,6 +109,12 @@ class Settings(private val appContext: Context) : PreferencesHolder { featureFlag = FeatureFlags.waitUntilPaintToDraw ) + var syncedTabsInTabsTray by featureFlagPreference( + appContext.getPreferenceKey(R.string.pref_key_synced_tabs_tabs_tray), + default = false, + featureFlag = FeatureFlags.syncedTabsInTabsTray + ) + var forceEnableZoom by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_accessibility_force_enable_zoom), default = false @@ -279,6 +285,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { !trackingProtectionOnboardingShownThisSession) var showSecretDebugMenuThisSession = false + var showNotificationsSetting = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O val shouldShowSecurityPinWarningSync: Boolean get() = loginsSecureWarningSyncCount < showLoginsSecureWarningSyncMaxCount diff --git a/app/src/main/res/anim/full_rotation.xml b/app/src/main/res/anim/full_rotation.xml new file mode 100644 index 000000000..eefb51740 --- /dev/null +++ b/app/src/main/res/anim/full_rotation.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_download_default.xml b/app/src/main/res/drawable/ic_download_default.xml new file mode 100644 index 000000000..c7387d54b --- /dev/null +++ b/app/src/main/res/drawable/ic_download_default.xml @@ -0,0 +1,15 @@ + + + + diff --git a/app/src/main/res/layout/component_downloads.xml b/app/src/main/res/layout/component_downloads.xml new file mode 100644 index 000000000..a6bcbe35e --- /dev/null +++ b/app/src/main/res/layout/component_downloads.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/layout/download_list_item.xml b/app/src/main/res/layout/download_list_item.xml new file mode 100644 index 000000000..7e9ddafd4 --- /dev/null +++ b/app/src/main/res/layout/download_list_item.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_downloads.xml b/app/src/main/res/layout/fragment_downloads.xml new file mode 100644 index 000000000..11fc15df2 --- /dev/null +++ b/app/src/main/res/layout/fragment_downloads.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/sync_tabs_error_row.xml b/app/src/main/res/layout/sync_tabs_error_row.xml index f9005af30..1e104150e 100644 --- a/app/src/main/res/layout/sync_tabs_error_row.xml +++ b/app/src/main/res/layout/sync_tabs_error_row.xml @@ -19,6 +19,7 @@ android:layout_marginTop="4dp" android:textSize="14sp" android:textAlignment="viewStart" + android:textColor="@color/tab_tray_item_text_normal_theme" tools:text="@string/synced_tabs_no_tabs"/> @@ -16,7 +18,6 @@ android:layout_height="wrap_content" android:layout_marginStart="72dp" android:layout_marginEnd="48dp" - android:layout_marginTop="6dp" android:singleLine="true" android:textAlignment="viewStart" android:textColor="?primaryText" @@ -42,16 +43,4 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/synced_tab_item_title" /> - - diff --git a/app/src/main/res/layout/view_synced_tabs_no_item.xml b/app/src/main/res/layout/view_synced_tabs_no_item.xml new file mode 100644 index 000000000..769081cd6 --- /dev/null +++ b/app/src/main/res/layout/view_synced_tabs_no_item.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_synced_tabs_title.xml b/app/src/main/res/layout/view_synced_tabs_title.xml new file mode 100644 index 000000000..5cb4a47c7 --- /dev/null +++ b/app/src/main/res/layout/view_synced_tabs_title.xml @@ -0,0 +1,30 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index a142bf363..d8f6cef7d 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -70,6 +70,9 @@ + + @@ -239,6 +242,12 @@ android:label="@string/library_history" tools:layout="@layout/fragment_history" /> + + Označeno %1$s + + Neizabrano %1$s Izašao iz režima s više izbora @@ -164,8 +166,8 @@ Skeniraj - - Pretraživač + + Pretraživač Postavke pretraživača @@ -294,6 +296,8 @@ Postavke računa Otvori linkove u aplikacijama + + Vanjski menadžer preuzimanja Add-oni @@ -1442,9 +1446,7 @@ Prijava sa tim korisničkim imenom već postoji - - Povežite se sa Firefox računom. - + Povežite drugi uređaj Ponovo potvrdite identitet. @@ -1465,13 +1467,4 @@ OK, razumijem - - - Prečice - - Traži na - - Ovaj put, traži na: - - Prikaži prečice za pretraživanje diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 81bc9bbb3..962a21a6c 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -34,6 +34,11 @@ Επιλογή συλλογής + + Τέλος λειτουργίας πολλαπλής επιλογής + + Αποθήκευση επιλεγμένων καρτελών στη συλλογή + Το %1$s αναπτύσσεται από τη Mozilla. @@ -255,6 +260,8 @@ Εργαλεία προγραμματιστή Απομακρυσμένος εντοπισμός σφαλμάτων μέσω USB + + Εμφάνιση μηχανών αναζήτησης Εμφάνιση προτάσεων αναζήτησης @@ -271,6 +278,8 @@ Ρυθμίσεις λογαριασμού Άνοιγμα συνδέσμων σε εφαρμογές + + Εξωτερική διαχείριση λήψεων Πρόσθετα @@ -322,17 +331,25 @@ Προστασία από καταγραφή Εξαιρέσεις + + Ενεργοποίηση για όλες τις σελίδες Μάθετε περισσότερα Τηλεμετρία + + Δεδομένα χρήσης και τεχνικά δεδομένα Δεδομένα μάρκετινγκ Πειράματα + + Επιτρέπει στη Mozilla την εγκατάσταση και συλλογή δεδομένων για πειραματικές λειτουργίες + + Αναφορά καταρρεύσεων Υπηρεσία τοποθεσίας Mozilla @@ -645,6 +662,8 @@ Ανενεργό Αποδοχή ήχου και βίντεο + + Η αναπαραγωγή ήχων/βίντεο θα γίνεται σε Wi-Fi Φραγή ήχου μόνο @@ -661,6 +680,8 @@ Μενού συλλογής Συλλέξτε όλα όσα έχουν σημασία για εσάς + + Ομαδοποιήστε παρόμοιες αναζητήσεις, σελίδες και καρτέλες για γρήγορη πρόσβαση αργότερα. Επιλέξτε καρτέλες @@ -681,6 +702,12 @@ Επιλέχθηκε %d καρτέλα + + Οι καρτέλες αποθηκεύτηκαν! + + Η συλλογή αποθηκεύτηκε! + + Η καρτέλα αποθηκεύτηκε! Κλείσιμο @@ -718,8 +745,12 @@ Εκτός σύνδεσης Σύνδεση άλλης συσκευής + + Για να στείλετε μια καρτέλα, συνδεθείτε στο Firefox σε άλλη μία τουλάχιστον συσκευή. Το κατάλαβα + + Αδυναμία κοινοποίησης σε αυτή την εφαρμογή Αποστολή σε συσκευή @@ -847,17 +878,29 @@ Το Firefox Preview είναι πλέον το Firefox Nightly + + + Το Firefox Nightly ενημερώνεται κάθε βράδυ και διαθέτει νέες, πειραματικές λειτουργίες. + Ωστόσο, ενδέχεται να είναι λιγότερο σταθερό. Κάντε λήψη του beta προγράμματος περιήγησής μας για μια πιο σταθερή εμπειρία. Λήψη του Firefox για Android Beta Το Firefox Nightly έχει μετακινηθεί + + + Αυτή η εφαρμογή δεν θα λαμβάνει πλέον ενημερώσεις ασφαλείας. Σταματήστε τη χρήση αυτής της εφαρμογής και μεταβείτε στο νέο Nightly. + \n\nΓια να μεταφέρετε τους σελιδοδείκτες, τις συνδέσεις και το ιστορικό σας σε άλλη εφαρμογή, δημιουργήστε ένα λογαριασμό Firefox. Εναλλαγή στο νέο Nightly Το Firefox Nightly έχει μετακινηθεί + + + Αυτή η εφαρμογή δεν θα λαμβάνει πλέον ενημερώσεις ασφαλείας. Αποκτήστε το νέο Nightly και σταματήστε τη χρήση αυτής της εφαρμογής. + \n\nΓια να μεταφέρετε τους σελιδοδείκτες, τις συνδέσεις και το ιστορικό σας σε άλλη εφαρμογή, δημιουργήστε ένα λογαριασμό Firefox. Αποκτήστε το νέο Nightly @@ -872,6 +915,11 @@ Γνωρίστε το %s Δείτε τι νέο υπάρχει + + Έχετε ερωτήσεις σχετικά με το επανασχεδιασμένο %s; Θέλετε να μάθετε τι έχει αλλάξει; + + Λάβετε απαντήσεις εδώ Αξιοποιήστε στο έπακρο το %s. @@ -888,6 +936,9 @@ Αυτόματο απόρρητο + + Οι ρυθμίσεις απορρήτου και ασφάλειας αποκλείουν ιχνηλάτες, κακόβουλο λογισμικό και εταιρείες που σας ακολουθούν. Τυπική (προεπιλογή) @@ -900,6 +951,8 @@ Άνοιγμα ρυθμίσεων Το απόρρητό σας + + Διαβάστε τη σημείωση απορρήτου μας Κλείσιμο @@ -918,6 +971,10 @@ Φωτεινό θέμα + + Οι καρτέλες απεστάλησαν! + + Η καρτέλα απεστάλη! Δεν ήταν δυνατή η αποστολή @@ -933,11 +990,18 @@ Χρήση email + + Το Firefox θα σταματήσει να συγχρονίζεται με το λογαριασμό σας, αλλά δεν θα διαγράψει τα δεδομένα περιήγησης από αυτή τη συσκευή. + + Το %s θα σταματήσει να συγχρονίζεται με το λογαριασμό σας, αλλά δεν θα διαγράψει τα δεδομένα περιήγησης από αυτή τη συσκευή. Αποσύνδεση Ακύρωση + + Δεν είναι δυνατή η επεξεργασία προεπιλεγμένων φακέλων + Ρυθμίσεις προστασίας @@ -951,12 +1015,22 @@ Μάθετε περισσότερα Τυπική (προεπιλογή) + + Φραγή λιγότερων ιχνηλατών. Οι σελίδες θα φορτώνονται κανονικά. + + Τι αποκλείει η τυπική προστασία από καταγραφή Αυστηρή + + Φραγή περισσότερων ιχνηλατών, διαφημίσεων και αναδυόμενων παραθύρων. Οι σελίδες φορτώνονται ταχύτερα, αλλά ορισμένα μέρη ενδέχεται να μην λειτουργούν. + + Τι αποκλείει η αυστηρή προστασία από καταγραφή Προσαρμοσμένη Επιλέξτε ιχνηλάτες και σενάρια για αποκλεισμό. + + Τι αποκλείει η προσαρμοσμένη προστασία από καταγραφή Cookies @@ -980,6 +1054,9 @@ Cryptominers Fingerprinters + Αποκλείεται + + Επιτρέπεται Ιχνηλάτες κοινωνικών δικτύων @@ -990,6 +1067,15 @@ Fingerprinters Περιεχόμενο καταγραφής + + Η προστασία είναι ΕΝΕΡΓΗ για αυτή τη σελίδα + + Η προστασία είναι ΑΝΕΝΕΡΓΗ για αυτή τη σελίδα + + Η ενισχυμένη προστασία από καταγραφή είναι ανενεργή για αυτή τη σελίδα + + Πλοήγηση προς τα πίσω Τα δικαιώματά σας @@ -1088,6 +1174,8 @@ Όνομα χρήστη Κωδικός πρόσβασης + + Εισάγετε ξανά το PIN σας Αυτή η σύνδεση δεν είναι ασφαλής. Οι λογαριασμοί που εισάγονται εδώ ενδέχεται να παραβιαστούν. diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index b12c2a8e5..b77ebff5f 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -1402,7 +1402,7 @@ %s dihapus - Selamat datang ke %s yang benar-benar baru + Selamat datang di %s terbaru Sebuah peramban yang telah didesain ulang sepenuhnya, dengan peningkatan kinerja dan fitur untuk membantu anda dalam melakukan sesuatu secara daring.\n\nHarap tunggu selama kami memperbarui %s dengan milik anda diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 573324abf..76d43f528 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -36,12 +36,18 @@ Naam Collectie selecteren + + Multiselectiemodus verlaten Geselecteerde tabbladen in collectie opslaan %1$s geselecteerd Selectie %1$s ongedaan gemaakt + + Multiselectiemodus verlaten + + Multiselectiemodus geactiveerd, selecteer tabbladen om in een collectie op te slaan Geselecteerd diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index 317651afd..6b0042d96 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -20,6 +20,7 @@ pref_key_privacy_link pref_key_delete_browsing_data pref_key_delete_browsing_data_on_quit_preference + pref_key_notifications pref_key_delete_browsing_data_on_quit pref_key_delete_open_tabs_on_quit pref_key_delete_browsing_history_on_quit @@ -178,6 +179,8 @@ pref_key_wait_first_paint + pref_key_synced_tabs_tabs_tray + pref_key_debug_settings pref_key_open_tabs_count diff --git a/app/src/main/res/values/static_strings.xml b/app/src/main/res/values/static_strings.xml index e51388ca3..4a76e78b4 100644 --- a/app/src/main/res/values/static_strings.xml +++ b/app/src/main/res/values/static_strings.xml @@ -36,6 +36,8 @@ Use New Search Experience Wait Until First Paint To Show Page Content + + Show Synced Tabs in the tabs tray link diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3040ca5cd..e83485f4d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -300,6 +300,8 @@ External download manager Add-ons + + Notifications @@ -563,6 +565,13 @@ No history here + + + No downloads here + + %1$d selected + Sorry. %1$s can’t load that page. @@ -1446,6 +1455,8 @@ View a list of tabs from your other devices. Sign in to sync + + No open tabs diff --git a/app/src/main/res/xml/account_settings_preferences.xml b/app/src/main/res/xml/account_settings_preferences.xml index bdf69b790..0e409fbc4 100644 --- a/app/src/main/res/xml/account_settings_preferences.xml +++ b/app/src/main/res/xml/account_settings_preferences.xml @@ -43,7 +43,6 @@ diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index f3bf4c39b..c161e4c96 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -109,6 +109,11 @@ android:key="@string/pref_key_delete_browsing_data_on_quit_preference" android:title="@string/preferences_delete_browsing_data_on_quit" /> + + + diff --git a/app/src/test/java/org/mozilla/fenix/library/downloads/DownloadAdapterTest.kt b/app/src/test/java/org/mozilla/fenix/library/downloads/DownloadAdapterTest.kt new file mode 100644 index 000000000..79ba1a8ab --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/library/downloads/DownloadAdapterTest.kt @@ -0,0 +1,56 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.library.downloads + +import androidx.recyclerview.widget.RecyclerView +import io.mockk.Runs +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.verify +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner + +@RunWith(FenixRobolectricTestRunner::class) +class DownloadAdapterTest { + + private lateinit var interactor: DownloadInteractor + private lateinit var adapter: DownloadAdapter + + @Before + fun setup() { + interactor = mockk() + adapter = DownloadAdapter(interactor) + + every { interactor.select(any()) } just Runs + } + + @Test + fun `getItemCount should return the number of tab collections`() { + val download = mockk() + + assertEquals(0, adapter.itemCount) + + adapter.updateDownloads( + downloads = listOf(download) + ) + assertEquals(1, adapter.itemCount) + } + + @Test + fun `updateData inserts item`() { + val download = mockk { + } + val observer = mockk(relaxed = true) + adapter.registerAdapterDataObserver(observer) + adapter.updateDownloads( + downloads = listOf(download) + ) + verify { observer.onChanged() } + } +} diff --git a/app/src/test/java/org/mozilla/fenix/library/downloads/DownloadControllerTest.kt b/app/src/test/java/org/mozilla/fenix/library/downloads/DownloadControllerTest.kt new file mode 100644 index 000000000..68ae555dd --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/library/downloads/DownloadControllerTest.kt @@ -0,0 +1,63 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.library.downloads + +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestCoroutineScope +import org.junit.Assert.assertFalse +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.browser.browsingmode.BrowsingMode +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner + +@ExperimentalCoroutinesApi +@RunWith(FenixRobolectricTestRunner::class) +class DownloadControllerTest { + private val downloadItem = DownloadItem(0, "title", "url", "77", "jpg") + private val scope: CoroutineScope = TestCoroutineScope() + private val store: DownloadFragmentStore = mockk(relaxed = true) + private val state: DownloadFragmentState = mockk(relaxed = true) + private val openToFileManager: (DownloadItem, BrowsingMode?) -> Unit = mockk(relaxed = true) + private val invalidateOptionsMenu: () -> Unit = mockk(relaxed = true) + private val controller = DefaultDownloadController( + store, + openToFileManager + ) + + @Before + fun setUp() { + every { store.state } returns state + } + + @Test + fun onPressDownloadItemInNormalMode() { + controller.handleOpen(downloadItem) + + verify { + openToFileManager(downloadItem, null) + } + } + + @Test + fun onOpenItemInNormalMode() { + controller.handleOpen(downloadItem, BrowsingMode.Normal) + + verify { + openToFileManager(downloadItem, BrowsingMode.Normal) + } + } + + @Test + fun onBackPressedInNormalMode() { + every { state.mode } returns DownloadFragmentState.Mode.Normal + + assertFalse(controller.handleBackPressed()) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/library/downloads/DownloadInteractorTest.kt b/app/src/test/java/org/mozilla/fenix/library/downloads/DownloadInteractorTest.kt new file mode 100644 index 000000000..3e552d6ab --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/library/downloads/DownloadInteractorTest.kt @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.library.downloads + +import io.mockk.every +import io.mockk.mockk +import io.mockk.verifyAll +import org.junit.Assert.assertTrue +import org.junit.Test + +class DownloadInteractorTest { + private val downloadItem = DownloadItem(0, "title", "url", "5.6 mb", "png") + val controller: DownloadController = mockk(relaxed = true) + val interactor = DownloadInteractor(controller) + + @Test + fun onOpen() { + interactor.open(downloadItem) + + verifyAll { + controller.handleOpen(downloadItem) + } + } + + @Test + fun onBackPressed() { + every { + controller.handleBackPressed() + } returns true + + val backpressHandled = interactor.onBackPressed() + + verifyAll { + controller.handleBackPressed() + } + assertTrue(backpressHandled) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/sync/ListenerDelegateTest.kt b/app/src/test/java/org/mozilla/fenix/sync/ListenerDelegateTest.kt new file mode 100644 index 000000000..f1863bd60 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/sync/ListenerDelegateTest.kt @@ -0,0 +1,26 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.sync + +import io.mockk.mockk +import io.mockk.verify +import mozilla.components.feature.syncedtabs.view.SyncedTabsView +import org.junit.Test + +class ListenerDelegateTest { + @Test + fun `delegate invokes nullable listener`() { + val listener: SyncedTabsView.Listener? = mockk(relaxed = true) + val delegate = ListenerDelegate { listener } + + delegate.onRefresh() + + verify { listener?.onRefresh() } + + delegate.onTabClicked(mockk()) + + verify { listener?.onTabClicked(any()) } + } +} diff --git a/app/src/test/java/org/mozilla/fenix/sync/SyncedTabsAdapterTest.kt b/app/src/test/java/org/mozilla/fenix/sync/SyncedTabsAdapterTest.kt index e22bbb181..f1f7f3fea 100644 --- a/app/src/test/java/org/mozilla/fenix/sync/SyncedTabsAdapterTest.kt +++ b/app/src/test/java/org/mozilla/fenix/sync/SyncedTabsAdapterTest.kt @@ -11,6 +11,7 @@ import mozilla.components.browser.storage.sync.SyncedDeviceTabs import mozilla.components.browser.storage.sync.Tab import mozilla.components.browser.storage.sync.TabEntry import mozilla.components.concept.sync.DeviceType +import mozilla.components.feature.syncedtabs.view.SyncedTabsView import mozilla.components.support.test.robolectric.testContext import org.junit.Assert.assertEquals import org.junit.Before @@ -21,7 +22,7 @@ import org.mozilla.fenix.helpers.FenixRobolectricTestRunner @RunWith(FenixRobolectricTestRunner::class) class SyncedTabsAdapterTest { - private lateinit var listener: (Tab) -> Unit + private lateinit var listener: SyncedTabsView.Listener private lateinit var adapter: SyncedTabsAdapter private val oneTabDevice = SyncedDeviceTabs( @@ -77,10 +78,12 @@ class SyncedTabsAdapterTest { fun `updateData() adds items for each device and tab`() { assertEquals(0, adapter.itemCount) - adapter.updateData(listOf( - oneTabDevice, - threeTabDevice - )) + adapter.updateData( + listOf( + oneTabDevice, + threeTabDevice + ) + ) assertEquals(5, adapter.itemCount) assertEquals(SyncedTabsViewHolder.DeviceViewHolder.LAYOUT_ID, adapter.getItemViewType(0)) diff --git a/app/src/test/java/org/mozilla/fenix/sync/SyncedTabsLayoutTest.kt b/app/src/test/java/org/mozilla/fenix/sync/SyncedTabsLayoutTest.kt index a04bfbb51..8c1f6514a 100644 --- a/app/src/test/java/org/mozilla/fenix/sync/SyncedTabsLayoutTest.kt +++ b/app/src/test/java/org/mozilla/fenix/sync/SyncedTabsLayoutTest.kt @@ -4,16 +4,10 @@ package org.mozilla.fenix.sync -import androidx.navigation.NavController -import io.mockk.mockk import mozilla.components.feature.syncedtabs.view.SyncedTabsView.ErrorType -import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse -import org.junit.Assert.assertNotNull -import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Test -import org.mozilla.fenix.R class SyncedTabsLayoutTest { @@ -25,73 +19,4 @@ class SyncedTabsLayoutTest { assertFalse(SyncedTabsLayout.pullToRefreshEnableState(ErrorType.SYNC_NEEDS_REAUTHENTICATION)) assertFalse(SyncedTabsLayout.pullToRefreshEnableState(ErrorType.SYNC_UNAVAILABLE)) } - - @Test - fun `string resource for error`() { - assertEquals( - R.string.synced_tabs_connect_another_device, - SyncedTabsLayout.stringResourceForError(ErrorType.MULTIPLE_DEVICES_UNAVAILABLE) - ) - assertEquals( - R.string.synced_tabs_enable_tab_syncing, - SyncedTabsLayout.stringResourceForError(ErrorType.SYNC_ENGINE_UNAVAILABLE) - ) - assertEquals( - R.string.synced_tabs_sign_in_message, - SyncedTabsLayout.stringResourceForError(ErrorType.SYNC_UNAVAILABLE) - ) - assertEquals( - R.string.synced_tabs_reauth, - SyncedTabsLayout.stringResourceForError(ErrorType.SYNC_NEEDS_REAUTHENTICATION) - ) - assertEquals( - R.string.synced_tabs_no_tabs, - SyncedTabsLayout.stringResourceForError(ErrorType.NO_TABS_AVAILABLE) - ) - } - - @Test - fun `get error item`() { - val navController = mockk() - - var errorItem = SyncedTabsLayout.getErrorItem( - navController, - ErrorType.MULTIPLE_DEVICES_UNAVAILABLE, - R.string.synced_tabs_connect_another_device - ) - assertNull((errorItem as SyncedTabsAdapter.AdapterItem.Error).navController) - assertEquals(R.string.synced_tabs_connect_another_device, errorItem.descriptionResId) - - errorItem = SyncedTabsLayout.getErrorItem( - navController, - ErrorType.SYNC_ENGINE_UNAVAILABLE, - R.string.synced_tabs_enable_tab_syncing - ) - assertNull((errorItem as SyncedTabsAdapter.AdapterItem.Error).navController) - assertEquals(R.string.synced_tabs_enable_tab_syncing, errorItem.descriptionResId) - - errorItem = SyncedTabsLayout.getErrorItem( - navController, - ErrorType.SYNC_NEEDS_REAUTHENTICATION, - R.string.synced_tabs_reauth - ) - assertNull((errorItem as SyncedTabsAdapter.AdapterItem.Error).navController) - assertEquals(R.string.synced_tabs_reauth, errorItem.descriptionResId) - - errorItem = SyncedTabsLayout.getErrorItem( - navController, - ErrorType.NO_TABS_AVAILABLE, - R.string.synced_tabs_no_tabs - ) - assertNull((errorItem as SyncedTabsAdapter.AdapterItem.Error).navController) - assertEquals(R.string.synced_tabs_no_tabs, errorItem.descriptionResId) - - errorItem = SyncedTabsLayout.getErrorItem( - navController, - ErrorType.SYNC_UNAVAILABLE, - R.string.synced_tabs_sign_in_message - ) - assertNotNull((errorItem as SyncedTabsAdapter.AdapterItem.Error).navController) - assertEquals(R.string.synced_tabs_sign_in_message, errorItem.descriptionResId) - } } diff --git a/app/src/test/java/org/mozilla/fenix/sync/SyncedTabsViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/sync/SyncedTabsViewHolderTest.kt index b81a0fc3b..3f8b06fd2 100644 --- a/app/src/test/java/org/mozilla/fenix/sync/SyncedTabsViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/sync/SyncedTabsViewHolderTest.kt @@ -7,15 +7,18 @@ package org.mozilla.fenix.sync import android.view.LayoutInflater import android.view.View import android.widget.TextView +import io.mockk.Called import io.mockk.every import io.mockk.mockk import io.mockk.verify import kotlinx.android.synthetic.main.sync_tabs_list_item.view.* import kotlinx.android.synthetic.main.view_synced_tabs_group.view.* +import kotlinx.android.synthetic.main.view_synced_tabs_title.view.* import mozilla.components.browser.storage.sync.Tab import mozilla.components.browser.storage.sync.TabEntry import mozilla.components.concept.sync.Device import mozilla.components.concept.sync.DeviceType +import mozilla.components.feature.syncedtabs.view.SyncedTabsView import mozilla.components.support.test.robolectric.testContext import org.junit.Assert.assertEquals import org.junit.Before @@ -32,6 +35,10 @@ class SyncedTabsViewHolderTest { private lateinit var deviceViewHolder: SyncedTabsViewHolder.DeviceViewHolder private lateinit var deviceView: View private lateinit var deviceViewGroupName: TextView + private lateinit var titleView: View + private lateinit var titleViewHolder: SyncedTabsViewHolder.TitleViewHolder + private lateinit var noTabsView: View + private lateinit var noTabsViewHolder: SyncedTabsViewHolder.NoTabsViewHolder private val tab = Tab( history = listOf( @@ -59,6 +66,12 @@ class SyncedTabsViewHolderTest { every { synced_tabs_group_name } returns deviceViewGroupName } deviceViewHolder = SyncedTabsViewHolder.DeviceViewHolder(deviceView) + + titleView = inflater.inflate(SyncedTabsViewHolder.TitleViewHolder.LAYOUT_ID, null) + titleViewHolder = SyncedTabsViewHolder.TitleViewHolder(titleView) + + noTabsView = inflater.inflate(SyncedTabsViewHolder.NoTabsViewHolder.LAYOUT_ID, null) + noTabsViewHolder = SyncedTabsViewHolder.NoTabsViewHolder(noTabsView) } @Test @@ -71,11 +84,11 @@ class SyncedTabsViewHolderTest { @Test fun `TabViewHolder calls interactor on click`() { - val interactor = mockk<(Tab) -> Unit>(relaxed = true) + val interactor = mockk(relaxed = true) tabViewHolder.bind(SyncedTabsAdapter.AdapterItem.Tab(tab), interactor) tabView.performClick() - verify { interactor(tab) } + verify { interactor.onTabClicked(tab) } } @Test @@ -109,4 +122,28 @@ class SyncedTabsViewHolderTest { ) } } + + @Test + fun `TitleViewHolder calls interactor refresh`() { + val interactor = mockk(relaxed = true) + titleViewHolder.bind(SyncedTabsAdapter.AdapterItem.Title, interactor) + + titleView.findViewById(R.id.refresh_icon).performClick() + + verify { interactor.onRefresh() } + } + + @Test + fun `NoTabsViewHolder does nothing`() { + val device = mockk { + every { displayName } returns "Charcoal" + every { deviceType } returns DeviceType.DESKTOP + } + val interactor = mockk(relaxed = true) + noTabsViewHolder.bind(SyncedTabsAdapter.AdapterItem.NoTabs(device), interactor) + + titleView.performClick() + + verify { interactor wasNot Called } + } } diff --git a/app/src/test/java/org/mozilla/fenix/sync/ext/ErrorTypeKtTest.kt b/app/src/test/java/org/mozilla/fenix/sync/ext/ErrorTypeKtTest.kt new file mode 100644 index 000000000..180ed0878 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/sync/ext/ErrorTypeKtTest.kt @@ -0,0 +1,72 @@ +package org.mozilla.fenix.sync.ext + +import org.junit.Test +import androidx.navigation.NavController +import io.mockk.mockk +import mozilla.components.feature.syncedtabs.view.SyncedTabsView.ErrorType +import org.mozilla.fenix.R +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull +import org.junit.Assert.assertEquals + +class ErrorTypeKtTest { + + @Test + fun `string resource for error`() { + assertEquals( + R.string.synced_tabs_connect_another_device, + ErrorType.MULTIPLE_DEVICES_UNAVAILABLE.toStringRes() + ) + assertEquals( + R.string.synced_tabs_enable_tab_syncing, + ErrorType.SYNC_ENGINE_UNAVAILABLE.toStringRes() + ) + assertEquals( + R.string.synced_tabs_sign_in_message, + ErrorType.SYNC_UNAVAILABLE.toStringRes() + ) + assertEquals( + R.string.synced_tabs_reauth, + ErrorType.SYNC_NEEDS_REAUTHENTICATION.toStringRes() + ) + assertEquals( + R.string.synced_tabs_no_tabs, + ErrorType.NO_TABS_AVAILABLE.toStringRes() + ) + } + + @Test + fun `get error item`() { + val navController = mockk() + + var errorItem = ErrorType.MULTIPLE_DEVICES_UNAVAILABLE.toAdapterItem( + R.string.synced_tabs_connect_another_device, navController + ) + assertNull(errorItem.navController) + assertEquals(R.string.synced_tabs_connect_another_device, errorItem.descriptionResId) + + errorItem = ErrorType.SYNC_ENGINE_UNAVAILABLE.toAdapterItem( + R.string.synced_tabs_enable_tab_syncing, navController + ) + assertNull(errorItem.navController) + assertEquals(R.string.synced_tabs_enable_tab_syncing, errorItem.descriptionResId) + + errorItem = ErrorType.SYNC_NEEDS_REAUTHENTICATION.toAdapterItem( + R.string.synced_tabs_reauth, navController + ) + assertNull(errorItem.navController) + assertEquals(R.string.synced_tabs_reauth, errorItem.descriptionResId) + + errorItem = ErrorType.NO_TABS_AVAILABLE.toAdapterItem( + R.string.synced_tabs_no_tabs, navController + ) + assertNull(errorItem.navController) + assertEquals(R.string.synced_tabs_no_tabs, errorItem.descriptionResId) + + errorItem = ErrorType.SYNC_UNAVAILABLE.toAdapterItem( + R.string.synced_tabs_sign_in_message, navController + ) + assertNotNull(errorItem.navController) + assertEquals(R.string.synced_tabs_sign_in_message, errorItem.descriptionResId) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/sync/ext/SyncedTabsAdapterKtTest.kt b/app/src/test/java/org/mozilla/fenix/sync/ext/SyncedTabsAdapterKtTest.kt new file mode 100644 index 000000000..aa568acdd --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/sync/ext/SyncedTabsAdapterKtTest.kt @@ -0,0 +1,94 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.sync.ext + +import io.mockk.every +import io.mockk.mockk +import mozilla.components.browser.storage.sync.SyncedDeviceTabs +import mozilla.components.browser.storage.sync.Tab +import mozilla.components.browser.storage.sync.TabEntry +import mozilla.components.concept.sync.DeviceType +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import org.mozilla.fenix.sync.SyncedTabsAdapter + +class SyncedTabsAdapterKtTest { + private val noTabDevice = SyncedDeviceTabs( + device = mockk { + every { displayName } returns "Charcoal" + every { deviceType } returns DeviceType.DESKTOP + }, + tabs = emptyList() + ) + + private val oneTabDevice = SyncedDeviceTabs( + device = mockk { + every { displayName } returns "Charcoal" + every { deviceType } returns DeviceType.DESKTOP + }, + tabs = listOf(Tab( + history = listOf(TabEntry( + title = "Mozilla", + url = "https://mozilla.org", + iconUrl = null + )), + active = 0, + lastUsed = 0L + )) + ) + + private val twoTabDevice = SyncedDeviceTabs( + device = mockk { + every { displayName } returns "Emerald" + every { deviceType } returns DeviceType.MOBILE + }, + tabs = listOf( + Tab( + history = listOf(TabEntry( + title = "Mozilla", + url = "https://mozilla.org", + iconUrl = null + )), + active = 0, + lastUsed = 0L + ), + Tab( + history = listOf( + TabEntry( + title = "Firefox", + url = "https://firefox.com", + iconUrl = null + ) + ), + active = 0, + lastUsed = 0L + ) + ) + ) + + @Test + fun `verify ordering of adapter items`() { + val syncedDeviceList = listOf(oneTabDevice, twoTabDevice) + val adapterData = syncedDeviceList.toAdapterList() + + assertEquals(5, adapterData.count()) + assertTrue(adapterData[0] is SyncedTabsAdapter.AdapterItem.Device) + assertTrue(adapterData[1] is SyncedTabsAdapter.AdapterItem.Tab) + assertTrue(adapterData[2] is SyncedTabsAdapter.AdapterItem.Device) + assertTrue(adapterData[3] is SyncedTabsAdapter.AdapterItem.Tab) + assertTrue(adapterData[4] is SyncedTabsAdapter.AdapterItem.Tab) + } + + @Test + fun `verify no tabs displayed`() { + val syncedDeviceList = listOf(noTabDevice) + val adapterData = syncedDeviceList.toAdapterList() + + assertEquals(2, adapterData.count()) + assertTrue(adapterData[0] is SyncedTabsAdapter.AdapterItem.Device) + assertTrue(adapterData[1] is SyncedTabsAdapter.AdapterItem.NoTabs) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/tabtray/DefaultTabTrayControllerTest.kt b/app/src/test/java/org/mozilla/fenix/tabtray/DefaultTabTrayControllerTest.kt index 57ce54da4..c95c8bef4 100644 --- a/app/src/test/java/org/mozilla/fenix/tabtray/DefaultTabTrayControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/tabtray/DefaultTabTrayControllerTest.kt @@ -26,6 +26,8 @@ import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test +import org.mozilla.fenix.BrowserDirection +import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager @@ -34,6 +36,7 @@ import org.mozilla.fenix.ext.sessionsOfType @OptIn(ExperimentalCoroutinesApi::class) class DefaultTabTrayControllerTest { + private val activity: HomeActivity = mockk(relaxed = true) private val profiler: Profiler? = mockk(relaxed = true) private val navController: NavController = mockk() private val sessionManager: SessionManager = mockk(relaxed = true) @@ -81,6 +84,7 @@ class DefaultTabTrayControllerTest { every { tabCollection.title } returns "Collection title" controller = DefaultTabTrayController( + activity = activity, profiler = profiler, sessionManager = sessionManager, browsingModeManager = browsingModeManager, @@ -156,6 +160,15 @@ class DefaultTabTrayControllerTest { } } + @Test + fun onSyncedTabClicked() { + controller.onSyncedTabClicked(mockk(relaxed = true)) + + verify { + activity.openToBrowserAndLoad(any(), true, BrowserDirection.FromTabTray) + } + } + @Test fun handleBackPressed() { every { tabTrayFragmentStore.state.mode } returns TabTrayDialogFragmentState.Mode.MultiSelect( diff --git a/app/src/test/java/org/mozilla/fenix/tabtray/SyncedTabsControllerTest.kt b/app/src/test/java/org/mozilla/fenix/tabtray/SyncedTabsControllerTest.kt new file mode 100644 index 000000000..6ff967c84 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/tabtray/SyncedTabsControllerTest.kt @@ -0,0 +1,133 @@ +package org.mozilla.fenix.tabtray + +import android.view.LayoutInflater +import android.view.View +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LifecycleRegistry +import androidx.recyclerview.widget.ConcatAdapter +import io.mockk.Called +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestCoroutineDispatcher +import kotlinx.coroutines.test.runBlockingTest +import mozilla.components.browser.storage.sync.SyncedDeviceTabs +import mozilla.components.feature.syncedtabs.view.SyncedTabsView.ErrorType +import mozilla.components.support.test.ext.joinBlocking +import mozilla.components.support.test.robolectric.testContext +import mozilla.components.support.test.rule.MainCoroutineRule +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner +import org.mozilla.fenix.sync.SyncedTabsViewHolder +import org.mozilla.fenix.tabtray.TabTrayDialogFragmentAction.EnterMultiSelectMode +import org.mozilla.fenix.tabtray.TabTrayDialogFragmentAction.ExitMultiSelectMode +import org.mozilla.fenix.tabtray.TabTrayDialogFragmentState.Mode + +@ExperimentalCoroutinesApi +@RunWith(FenixRobolectricTestRunner::class) +class SyncedTabsControllerTest { + + private val testDispatcher = TestCoroutineDispatcher() + @get:Rule + val coroutinesTestRule = MainCoroutineRule(testDispatcher) + + private lateinit var view: View + private lateinit var controller: SyncedTabsController + private lateinit var lifecycleOwner: LifecycleOwner + private lateinit var lifecycle: LifecycleRegistry + private lateinit var concatAdapter: ConcatAdapter + private lateinit var store: TabTrayDialogFragmentStore + + @Before + fun setup() = runBlockingTest { + lifecycleOwner = mockk() + lifecycle = LifecycleRegistry(lifecycleOwner) + lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START) + every { lifecycleOwner.lifecycle } returns lifecycle + + concatAdapter = mockk() + every { concatAdapter.addAdapter(any(), any()) } returns true + every { concatAdapter.removeAdapter(any()) } returns true + + store = TabTrayDialogFragmentStore( + initialState = TabTrayDialogFragmentState( + mode = Mode.Normal, + browserState = mockk(relaxed = true) + ) + ) + + view = LayoutInflater.from(testContext).inflate(R.layout.about_list_item, null) + controller = + SyncedTabsController(lifecycleOwner, view, store, concatAdapter, coroutineContext) + } + + @Test + fun `display synced tabs in reverse`() { + val tabs = listOf( + SyncedDeviceTabs( + device = mockk(relaxed = true), + tabs = listOf( + mockk(relaxed = true), + mockk(relaxed = true) + ) + ) + ) + + controller.displaySyncedTabs(tabs) + + val itemCount = controller.adapter.itemCount + + // title + device name + 2 tabs + assertEquals(4, itemCount) + assertEquals( + SyncedTabsViewHolder.TitleViewHolder.LAYOUT_ID, + controller.adapter.getItemViewType(itemCount - 1) + ) + assertEquals( + SyncedTabsViewHolder.DeviceViewHolder.LAYOUT_ID, + controller.adapter.getItemViewType(itemCount - 2) + ) + assertEquals( + SyncedTabsViewHolder.TabViewHolder.LAYOUT_ID, + controller.adapter.getItemViewType(itemCount - 3) + ) + assertEquals( + SyncedTabsViewHolder.TabViewHolder.LAYOUT_ID, + controller.adapter.getItemViewType(itemCount - 4) + ) + } + + @Test + fun `show error when we go kaput`() { + controller.onError(ErrorType.SYNC_NEEDS_REAUTHENTICATION) + + assertEquals(1, controller.adapter.itemCount) + assertEquals( + SyncedTabsViewHolder.ErrorViewHolder.LAYOUT_ID, + controller.adapter.getItemViewType(0) + ) + } + + @Test + fun `do nothing on init, drop first event`() { + verify { concatAdapter wasNot Called } + } + + @Test + fun `concatAdapter updated on mode changes`() = testDispatcher.runBlockingTest { + store.dispatch(EnterMultiSelectMode).joinBlocking() + + verify { concatAdapter.removeAdapter(any()) } + + store.dispatch(ExitMultiSelectMode).joinBlocking() + + verify { concatAdapter.addAdapter(0, any()) } + } +} diff --git a/app/src/test/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractorTest.kt b/app/src/test/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractorTest.kt index 8a459f73f..575b3a4ec 100644 --- a/app/src/test/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractorTest.kt +++ b/app/src/test/java/org/mozilla/fenix/tabtray/TabTrayFragmentInteractorTest.kt @@ -53,6 +53,12 @@ class TabTrayFragmentInteractorTest { verify { controller.onCloseAllTabsClicked(true) } } + @Test + fun onSyncedTabClicked() { + interactor.onSyncedTabClicked(mockk(relaxed = true)) + verify { controller.onSyncedTabClicked(any()) } + } + @Test fun onBackPressed() { interactor.onBackPressed() diff --git a/docs/metrics.md b/docs/metrics.md index fdf276a7a..88633ba61 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -35,8 +35,8 @@ The following metrics are added to the ping: | Name | Type | Description | Data reviews | Extras | Expiration | [Data Sensitivity](https://wiki.mozilla.org/Firefox/Data_Collection) | | --- | --- | --- | --- | --- | --- | --- | -| activation.activation_id |[uuid](https://mozilla.github.io/glean/book/user/metrics/uuid.html) |An alternate identifier, not correlated with the client_id, generated once and only sent with the activation ping. |[1](https://github.com/mozilla-mobile/fenix/pull/1707#issuecomment-486972209)||2020-10-01 | | -| activation.identifier |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A hashed and salted version of the Google Advertising ID from the device. This will never be sent in a ping that also contains the client_id. |[1](https://github.com/mozilla-mobile/fenix/pull/1707#issuecomment-486972209)||2020-10-01 | | +| activation.activation_id |[uuid](https://mozilla.github.io/glean/book/user/metrics/uuid.html) |An alternate identifier, not correlated with the client_id, generated once and only sent with the activation ping. |[1](https://github.com/mozilla-mobile/fenix/pull/1707#issuecomment-486972209)||2020-10-01 |4 | +| activation.identifier |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A hashed and salted version of the Google Advertising ID from the device. This will never be sent in a ping that also contains the client_id. |[1](https://github.com/mozilla-mobile/fenix/pull/1707#issuecomment-486972209)||2020-10-01 |4 | ## events @@ -48,185 +48,185 @@ The following metrics are added to the ping: | Name | Type | Description | Data reviews | Extras | Expiration | [Data Sensitivity](https://wiki.mozilla.org/Firefox/Data_Collection) | | --- | --- | --- | --- | --- | --- | --- | -| about_page.libraries_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on "Libraries that we use" item from About page |[1](https://github.com/mozilla-mobile/fenix/pull/8047)||2020-10-01 | | -| about_page.licensing_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on "Licensing information" item from About page |[1](https://github.com/mozilla-mobile/fenix/pull/8047)||2020-10-01 | | -| about_page.privacy_notice_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on "Privacy notice" item from About page |[1](https://github.com/mozilla-mobile/fenix/pull/8047)||2020-10-01 | | -| about_page.rights_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on "Know your rights" item from About page |[1](https://github.com/mozilla-mobile/fenix/pull/8047)||2020-10-01 | | -| about_page.support_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on "Support" item from About page |[1](https://github.com/mozilla-mobile/fenix/pull/8047)||2020-10-01 | | -| addons.open_addon_in_toolbar_menu |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user interacted with an installed add-on in the toolbar menu |[1](https://github.com/mozilla-mobile/fenix/pull/8318)|
  • addon_id: The id of the add-on that was interacted with in the toolbar menu
|2020-10-01 | | -| addons.open_addons_in_settings |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user accessed "Add-ons" from the Settings |[1](https://github.com/mozilla-mobile/fenix/pull/8318)||2020-10-01 | | -| app_theme.dark_theme_selected |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user selected Dark Theme |[1](https://github.com/mozilla-mobile/fenix/pull/7968)|
  • source: The source from where dark theme was selected. The source can be 'SETTINGS' or 'ONBOARDING'
|2020-10-01 | | -| autoplay.setting_changed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user changed their autoplay setting to either block_cellular, block_audio, or block_all. |[1](https://github.com/mozilla-mobile/fenix/pull/13041#issuecomment-665777411)|
  • autoplay_setting: The new setting for autoplay: block_cellular, block_audio, or block_all.
|2021-02-01 | | -| autoplay.visited_setting |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user visited the autoplay settings screen |[1](https://github.com/mozilla-mobile/fenix/pull/13041#issuecomment-665777411)||2021-02-01 | | -| bookmarks_management.copied |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user copied a bookmark. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 | | -| bookmarks_management.edited |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user edited the title and/or URL of an existing bookmark. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 | | -| bookmarks_management.folder_add |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user added a new bookmark folder. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 | | -| bookmarks_management.folder_remove |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removed a bookmark folder. |[1](https://github.com/mozilla-mobile/fenix/pull/3724)||2020-10-01 | | -| bookmarks_management.moved |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user moved an existing bookmark or folder to another folder. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 | | -| bookmarks_management.multi_removed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removed multiple bookmarks at once. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 | | -| bookmarks_management.open_in_new_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a bookmark in a new tab. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 | | -| bookmarks_management.open_in_new_tabs |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened multiple bookmarks at once in new tabs. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 | | -| bookmarks_management.open_in_private_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a bookmark in a new private tab. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 | | -| bookmarks_management.open_in_private_tabs |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened multiple bookmarks at once in new private tabs. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 | | -| bookmarks_management.removed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removed a bookmark item. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 | | -| bookmarks_management.shared |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user shared a bookmark. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 | | -| collections.add_tab_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the "add tab" button in the three dot menu of collections |[1](https://github.com/mozilla-mobile/fenix/pull/4358)||2020-10-01 | | -| collections.all_tabs_restored |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped "open tabs" from collection menu |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 | | -| collections.long_press |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user long pressed on a tab, triggering the collection creation screen |[1](https://github.com/mozilla-mobile/fenix/pull/4358)||2020-10-01 | | -| collections.removed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped delete collection from collection menu |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 | | -| collections.rename_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "rename collection" button in the three dot menu |[1](https://github.com/mozilla-mobile/fenix/pull/4539)||2020-10-01 | | -| collections.renamed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user renamed a collection |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 | | -| collections.save_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "save to collection" button on either the home or browser screen, triggering the collection creation screen to open (tab_select_opened) |[1](https://github.com/mozilla-mobile/fenix/pull/4358)|
  • from_screen: A string representing the screen from which the user pressed the save button. Currently one of: `browserMenu`, `homeMenu` or `home`
|2020-10-01 | | -| collections.saved |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user saved a list of tabs to a new collection |[1](https://github.com/mozilla-mobile/fenix/pull/3935)|
  • tabs_open: The number of tabs open in the current session
  • tabs_selected: The number of tabs added to the collection
|2020-10-01 | | -| collections.shared |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped share collection |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 | | -| collections.tab_removed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped remove tab from collection tab list |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 | | -| collections.tab_restored |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user restored a tab from collection tab list |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 | | -| collections.tab_select_opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the select tabs screen (the first step of the collection creation flow) |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 | | -| collections.tabs_added |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user saved a list of tabs to an existing collection |[1](https://github.com/mozilla-mobile/fenix/pull/3935)|
  • tabs_open: The number of tabs open in the current session
  • tabs_selected: The number of tabs added to the collection
|2020-10-01 | | -| context_menu.item_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped an item in the browsers context menu |[1](https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010)|
  • named: The name of the item that was tapped. Available items are: ``` open_in_new_tab, open_in_private_tab, open_image_in_new_tab, save_image, share_link, copy_link, copy_image_location ```
|2020-10-01 | | -| contextual_hint.tracking_protection.dismiss |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The enhanced tracking protection contextual hint was dismissed by pressing the close button |[1](https://github.com/mozilla-mobile/fenix/pull/11923)||2020-10-01 | | -| contextual_hint.tracking_protection.display |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The enhanced tracking protection contextual hint was displayed. |[1](https://github.com/mozilla-mobile/fenix/pull/11923)||2020-10-01 | | -| contextual_hint.tracking_protection.inside_tap |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user tapped inside of the etp contextual hint (which brings up the etp panel for this site). |[1](https://github.com/mozilla-mobile/fenix/pull/11923)||2020-10-01 | | -| contextual_hint.tracking_protection.outside_tap |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user tapped outside of the etp contextual hint (which has no effect). |[1](https://github.com/mozilla-mobile/fenix/pull/11923)||2020-10-01 | | -| crash_reporter.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The crash reporter was closed |[1](https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708)|
  • crash_submitted: A boolean that tells us whether or not the user submitted a crash report
|2020-10-01 | | -| crash_reporter.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The crash reporter was displayed |[1](https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708)||2020-10-01 | | -| custom_tab.action_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the action button provided by the launching app |[1](https://github.com/mozilla-mobile/fenix/pull/1697)||2020-10-01 | | -| custom_tab.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed the custom tab |[1](https://github.com/mozilla-mobile/fenix/pull/1697)||2020-10-01 | | -| custom_tab.menu |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the custom tabs menu |[1](https://github.com/mozilla-mobile/fenix/pull/1697)||2020-10-01 | | -| download_notification.cancel |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user cancelled a download in the download notification |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 | | -| download_notification.in_app_open |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a downloaded file in the in-app notification link |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 | | -| download_notification.in_app_try_again |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on try again when a download fails in the in-app notification link |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 | | -| download_notification.open |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a downloaded file in the download notification |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 | | -| download_notification.pause |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user paused a download in the download notification |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 | | -| download_notification.resume |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user resumed a download in the download notification |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 | | -| download_notification.try_again |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on try again when a download fails in the download notification |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 | | -| error_page.visited_error |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user encountered an error page |[1](https://github.com/mozilla-mobile/fenix/pull/2491#issuecomment-492414486)|
  • error_type: The error type of the error page encountered
|2020-10-01 | | -| events.app_opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the app (from cold start, to the homescreen or browser) |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673)|
  • source: The method used to open Fenix. Possible values are: `app_icon`, `custom_tab` or `link`
|2020-10-01 | | -| events.app_opened_all_startup |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the app to the HomeActivity. The HomeActivity encompasses the home screen, browser screen, settings screen, collections and other screens in the nav_graph. This differs from the app_opened probe because it measures all startups, not just cold startup. Note: There is a short gap between the time application goes into background and the time android reports the application going into the background. Note: This metric does not cover the following cases: Case # 1 -> a). open a link(for example, gmail) with in-app Browser (metric report custom_tab startup) b). press home button c). open gmail again (which brings us back to in app browser). Step c will not report startup metric. Case # 2 -> a). open fenix b). press home button c). launch fenix through app switcher/recent apps. step c will not report startup type. |[1](https://github.com/mozilla-mobile/fenix/pull/12114#pullrequestreview-445245341)|
  • source: The method used to open Fenix. Possible values are `app_icon`, `custom_tab`, `link` or `unknown`
|2020-12-01 | | +| about_page.libraries_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on "Libraries that we use" item from About page |[1](https://github.com/mozilla-mobile/fenix/pull/8047)||2020-10-01 |2 | +| about_page.licensing_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on "Licensing information" item from About page |[1](https://github.com/mozilla-mobile/fenix/pull/8047)||2020-10-01 |2 | +| about_page.privacy_notice_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on "Privacy notice" item from About page |[1](https://github.com/mozilla-mobile/fenix/pull/8047)||2020-10-01 |2 | +| about_page.rights_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on "Know your rights" item from About page |[1](https://github.com/mozilla-mobile/fenix/pull/8047)||2020-10-01 |2 | +| about_page.support_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on "Support" item from About page |[1](https://github.com/mozilla-mobile/fenix/pull/8047)||2020-10-01 |2 | +| addons.open_addon_in_toolbar_menu |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user interacted with an installed add-on in the toolbar menu |[1](https://github.com/mozilla-mobile/fenix/pull/8318)|
  • addon_id: The id of the add-on that was interacted with in the toolbar menu
|2020-10-01 |2 | +| addons.open_addons_in_settings |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user accessed "Add-ons" from the Settings |[1](https://github.com/mozilla-mobile/fenix/pull/8318)||2020-10-01 |2 | +| app_theme.dark_theme_selected |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user selected Dark Theme |[1](https://github.com/mozilla-mobile/fenix/pull/7968)|
  • source: The source from where dark theme was selected. The source can be 'SETTINGS' or 'ONBOARDING'
|2020-10-01 |2 | +| autoplay.setting_changed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user changed their autoplay setting to either block_cellular, block_audio, or block_all. |[1](https://github.com/mozilla-mobile/fenix/pull/13041#issuecomment-665777411)|
  • autoplay_setting: The new setting for autoplay: block_cellular, block_audio, or block_all.
|2021-02-01 |2 | +| autoplay.visited_setting |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user visited the autoplay settings screen |[1](https://github.com/mozilla-mobile/fenix/pull/13041#issuecomment-665777411)||2021-02-01 |2 | +| bookmarks_management.copied |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user copied a bookmark. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 |2 | +| bookmarks_management.edited |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user edited the title and/or URL of an existing bookmark. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 |2 | +| bookmarks_management.folder_add |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user added a new bookmark folder. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 |2 | +| bookmarks_management.folder_remove |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removed a bookmark folder. |[1](https://github.com/mozilla-mobile/fenix/pull/3724)||2020-10-01 |2 | +| bookmarks_management.moved |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user moved an existing bookmark or folder to another folder. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 |2 | +| bookmarks_management.multi_removed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removed multiple bookmarks at once. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 |2 | +| bookmarks_management.open_in_new_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a bookmark in a new tab. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 |2 | +| bookmarks_management.open_in_new_tabs |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened multiple bookmarks at once in new tabs. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 |2 | +| bookmarks_management.open_in_private_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a bookmark in a new private tab. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 |2 | +| bookmarks_management.open_in_private_tabs |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened multiple bookmarks at once in new private tabs. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 |2 | +| bookmarks_management.removed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removed a bookmark item. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 |2 | +| bookmarks_management.shared |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user shared a bookmark. |[1](https://github.com/mozilla-mobile/fenix/pull/1708)||2020-10-01 |2 | +| collections.add_tab_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the "add tab" button in the three dot menu of collections |[1](https://github.com/mozilla-mobile/fenix/pull/4358)||2020-10-01 |2 | +| collections.all_tabs_restored |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped "open tabs" from collection menu |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 |1, 2 | +| collections.long_press |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user long pressed on a tab, triggering the collection creation screen |[1](https://github.com/mozilla-mobile/fenix/pull/4358)||2020-10-01 |2 | +| collections.removed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped delete collection from collection menu |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 |1, 2 | +| collections.rename_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "rename collection" button in the three dot menu |[1](https://github.com/mozilla-mobile/fenix/pull/4539)||2020-10-01 |2 | +| collections.renamed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user renamed a collection |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 |1, 2 | +| collections.save_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "save to collection" button on either the home or browser screen, triggering the collection creation screen to open (tab_select_opened) |[1](https://github.com/mozilla-mobile/fenix/pull/4358)|
  • from_screen: A string representing the screen from which the user pressed the save button. Currently one of: `browserMenu`, `homeMenu` or `home`
|2020-10-01 |2 | +| collections.saved |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user saved a list of tabs to a new collection |[1](https://github.com/mozilla-mobile/fenix/pull/3935)|
  • tabs_open: The number of tabs open in the current session
  • tabs_selected: The number of tabs added to the collection
|2020-10-01 |1, 2 | +| collections.shared |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped share collection |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 |1, 2 | +| collections.tab_removed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped remove tab from collection tab list |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 |1, 2 | +| collections.tab_restored |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user restored a tab from collection tab list |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 |1, 2 | +| collections.tab_select_opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the select tabs screen (the first step of the collection creation flow) |[1](https://github.com/mozilla-mobile/fenix/pull/3935)||2020-10-01 |1, 2 | +| collections.tabs_added |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user saved a list of tabs to an existing collection |[1](https://github.com/mozilla-mobile/fenix/pull/3935)|
  • tabs_open: The number of tabs open in the current session
  • tabs_selected: The number of tabs added to the collection
|2020-10-01 |1, 2 | +| context_menu.item_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped an item in the browsers context menu |[1](https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010)|
  • named: The name of the item that was tapped. Available items are: ``` open_in_new_tab, open_in_private_tab, open_image_in_new_tab, save_image, share_link, copy_link, copy_image_location ```
|2020-10-01 |2 | +| contextual_hint.tracking_protection.dismiss |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The enhanced tracking protection contextual hint was dismissed by pressing the close button |[1](https://github.com/mozilla-mobile/fenix/pull/11923)||2020-10-01 |2 | +| contextual_hint.tracking_protection.display |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The enhanced tracking protection contextual hint was displayed. |[1](https://github.com/mozilla-mobile/fenix/pull/11923)||2020-10-01 |2 | +| contextual_hint.tracking_protection.inside_tap |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user tapped inside of the etp contextual hint (which brings up the etp panel for this site). |[1](https://github.com/mozilla-mobile/fenix/pull/11923)||2020-10-01 |2 | +| contextual_hint.tracking_protection.outside_tap |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user tapped outside of the etp contextual hint (which has no effect). |[1](https://github.com/mozilla-mobile/fenix/pull/11923)||2020-10-01 |2 | +| crash_reporter.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The crash reporter was closed |[1](https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708)|
  • crash_submitted: A boolean that tells us whether or not the user submitted a crash report
|2020-10-01 |2 | +| crash_reporter.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The crash reporter was displayed |[1](https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708)||2020-10-01 |2 | +| custom_tab.action_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the action button provided by the launching app |[1](https://github.com/mozilla-mobile/fenix/pull/1697)||2020-10-01 |2 | +| custom_tab.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed the custom tab |[1](https://github.com/mozilla-mobile/fenix/pull/1697)||2020-10-01 |2 | +| custom_tab.menu |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the custom tabs menu |[1](https://github.com/mozilla-mobile/fenix/pull/1697)||2020-10-01 |2 | +| download_notification.cancel |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user cancelled a download in the download notification |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 |2 | +| download_notification.in_app_open |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a downloaded file in the in-app notification link |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 |2 | +| download_notification.in_app_try_again |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on try again when a download fails in the in-app notification link |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 |2 | +| download_notification.open |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a downloaded file in the download notification |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 |2 | +| download_notification.pause |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user paused a download in the download notification |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 |2 | +| download_notification.resume |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user resumed a download in the download notification |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 |2 | +| download_notification.try_again |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped on try again when a download fails in the download notification |[1](https://github.com/mozilla-mobile/fenix/pull/6554)||2020-10-01 |2 | +| error_page.visited_error |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user encountered an error page |[1](https://github.com/mozilla-mobile/fenix/pull/2491#issuecomment-492414486)|
  • error_type: The error type of the error page encountered
|2020-10-01 |2 | +| events.app_opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the app (from cold start, to the homescreen or browser) |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673)|
  • source: The method used to open Fenix. Possible values are: `app_icon`, `custom_tab` or `link`
|2020-10-01 |2 | +| events.app_opened_all_startup |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the app to the HomeActivity. The HomeActivity encompasses the home screen, browser screen, settings screen, collections and other screens in the nav_graph. This differs from the app_opened probe because it measures all startups, not just cold startup. Note: There is a short gap between the time application goes into background and the time android reports the application going into the background. Note: This metric does not cover the following cases: Case # 1 -> a). open a link(for example, gmail) with in-app Browser (metric report custom_tab startup) b). press home button c). open gmail again (which brings us back to in app browser). Step c will not report startup metric. Case # 2 -> a). open fenix b). press home button c). launch fenix through app switcher/recent apps. step c will not report startup type. |[1](https://github.com/mozilla-mobile/fenix/pull/12114#pullrequestreview-445245341)|
  • source: The method used to open Fenix. Possible values are `app_icon`, `custom_tab`, `link` or `unknown`
|2020-12-01 |2 | | events.app_received_intent |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The system received an Intent for the HomeActivity. An intent is received an external entity wants to the app to display content. Intents can be received when the app is closed – at which point the app will be opened – or when the app is already opened – at which point the already open app will make changes such as loading a url. This can be used loosely as a heuristic for when the user requested to open the app. The HomeActivity encompasses the home screen and browser screen but may include other screens. This differs from the app_opened probe because it measures all startups, not just cold startup. |[1](https://github.com/mozilla-mobile/fenix/pull/11940/)|
  • source: The method used to open Fenix. Possible values are `app_icon`, `custom_tab`, `link` or `unknown`
|2020-12-01 | | -| events.browser_menu_action |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A browser menu item was tapped |[1](https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708), [2](https://github.com/mozilla-mobile/fenix/pull/5098#issuecomment-529658996), [3](https://github.com/mozilla-mobile/fenix/pull/6310)|
  • item: A string containing the name of the item the user tapped. These items include: Settings, Help, Desktop Site toggle on/off, Find in Page, New Tab, Private Tab, Share, Report Site Issue, Back/Forward button, Reload Button, Quit, Reader Mode On, Reader Mode Off, Open In app, Add To Top Sites, Add-ons Manager, Bookmarks, History
|2020-10-01 | | -| events.entered_url |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user entered a url |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673)|
  • autocomplete: A boolean that tells us whether the URL was autofilled by an Autocomplete suggestion
|2020-10-01 | | -| events.opened_link |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a link with Fenix |[1](https://github.com/mozilla-mobile/fenix/pull/5975)|
  • mode: The mode the link was opened in. Either 'PRIVATE' or 'NORMAL'.
|2020-10-01 | | -| events.performed_search |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user performed a search |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673), [2](https://github.com/mozilla-mobile/fenix/pull/1677)|
  • source: A string that tells us how the user performed the search. Possible values are: * default.action * default.suggestion * shortcut.action * shortcut.suggestion
|2020-10-01 | | -| events.preference_toggled |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user toggled a boolean preference in settings |[1](https://github.com/mozilla-mobile/fenix/pull/1896), [2](https://github.com/mozilla-mobile/fenix/pull/5704), [3](https://github.com/mozilla-mobile/fenix/pull/5886), [4](https://github.com/mozilla-mobile/fenix/pull/5975), [5](https://github.com/mozilla-mobile/fenix/pull/6352), [6](https://github.com/mozilla-mobile/fenix/pull/6601), [7](https://github.com/mozilla-mobile/fenix/pull/6746)|
  • enabled: Whether or not the preference is *now* enabled
  • preference_key: The preference key for the boolean (true/false) preference the user toggled. We currently track: show_search_suggestions, remote_debugging, telemetry, tracking_protection, search_bookmarks, search_browsing_history, show_clipboard_suggestions, show_search_shortcuts, open_links_in_a_private_tab (bug in implementation https://github.com/mozilla-mobile/fenix/issues/7384), pref_key_sync_logins, pref_key_sync_bookmarks, pref_key_sync_history, pref_key_show_voice_search, and pref_key_show_search_suggestions_in_private.
|2020-10-01 | | -| events.search_bar_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the search bar |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673)|
  • source: The view the user was on when they initiated the search (For example: `Home` or `Browser`)
|2020-10-01 | | -| events.tab_counter_menu_action |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A tab counter menu item was tapped |[1](https://github.com/mozilla-mobile/fenix/pull/11533)|
  • item: A string containing the name of the item the user tapped. These items are: New tab, New private tab, Close tab
|2020-10-01 | | -| events.whats_new_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the "what's new" page button |[1](https://github.com/mozilla-mobile/fenix/pull/5090)||2020-10-01 | | -| find_in_page.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed the find in page UI |[1](https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010)||2020-10-01 | | -| find_in_page.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the find in page UI |[1](https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010)||2020-10-01 | | -| find_in_page.searched_page |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user searched the page |[1](https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010)||2020-10-01 | | -| history.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the history screen |[1](https://github.com/mozilla-mobile/fenix/pull/3940)||2020-10-01 | | -| history.opened_item |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a history item |[1](https://github.com/mozilla-mobile/fenix/pull/3940)||2020-10-01 | | -| history.removed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removed a history item |[1](https://github.com/mozilla-mobile/fenix/pull/3940)||2020-10-01 | | -| history.removed_all |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removed all history items |[1](https://github.com/mozilla-mobile/fenix/pull/3940)||2020-10-01 | | -| history.shared |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user shared a history item |[1](https://github.com/mozilla-mobile/fenix/pull/3940)||2020-10-01 | | -| login_dialog.cancelled |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The login dialog prompt was cancelled |[1](https://github.com/mozilla-mobile/fenix/pull/13050)||2021-02-01 | | -| login_dialog.displayed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The login dialog prompt was displayed |[1](https://github.com/mozilla-mobile/fenix/pull/13050)||2021-02-01 | | -| login_dialog.never_save |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The login dialog prompt "never save" button was pressed |[1](https://github.com/mozilla-mobile/fenix/pull/13050)||2021-02-01 | | -| login_dialog.saved |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The login dialog prompt "save" button was pressed |[1](https://github.com/mozilla-mobile/fenix/pull/13050)||2021-02-01 | | -| logins.copy_login |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user copied a piece of a login in saved logins |[1](https://github.com/mozilla-mobile/fenix/pull/6352)||2020-10-01 | | -| logins.delete_saved_login |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user confirms delete of a saved login |[1](https://github.com/mozilla-mobile/fenix/issues/11208)||2020-10-01 | | -| logins.open_individual_login |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user accessed an individual login in saved logins |[1](https://github.com/mozilla-mobile/fenix/pull/6352)||2020-10-01 | | -| logins.open_login_editor |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user entered the edit screen for an individual saved login |[1](https://github.com/mozilla-mobile/fenix/issues/11208)||2020-10-01 | | -| logins.open_logins |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user accessed Logins in Settings |[1](https://github.com/mozilla-mobile/fenix/pull/6352)||2020-10-01 | | -| logins.save_edited_login |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user saves changes made to an individual login |[1](https://github.com/mozilla-mobile/fenix/issues/11208)||2020-10-01 | | -| logins.save_logins_setting_changed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user changed their setting for asking to save logins |[1](https://github.com/mozilla-mobile/fenix/pull/7767)|
  • setting: The new setting for saving logins the user selected. Either `ask_to_save` or `never_save`
|2020-10-01 | | -| logins.view_password_login |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user viewed a password in an individual saved login |[1](https://github.com/mozilla-mobile/fenix/pull/6352)||2020-10-01 | | -| media_notification.pause |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the pause icon on the media notification |[1](https://github.com/mozilla-mobile/fenix/pull/5520)||2020-10-01 | | -| media_notification.play |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the play icon on the media notification |[1](https://github.com/mozilla-mobile/fenix/pull/5520)||2020-10-01 | | -| media_state.pause |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |Media playback was paused. |[1](https://github.com/mozilla-mobile/fenix/pull/6463)||2020-10-01 | | -| media_state.play |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |Media started playing. |[1](https://github.com/mozilla-mobile/fenix/pull/6463)||2020-10-01 | | -| media_state.stop |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |Media playback has ended. |[1](https://github.com/mozilla-mobile/fenix/pull/6463)||2020-10-01 | | -| onboarding.finish |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user taps starts browsing and ends the onboarding experience. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)||2020-10-01 | | -| onboarding.fxa_auto_signin |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The onboarding automatic sign in card was tapped. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)||2020-10-01 | | -| onboarding.fxa_manual_signin |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The onboarding manual sign in card was tapped. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)||2020-10-01 | | -| onboarding.pref_toggled_private_browsing |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The private browsing preference was selected from the onboarding card. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)||2020-10-01 | | -| onboarding.pref_toggled_theme_picker |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The device theme was chosen using the theme picker onboarding card. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)|
  • theme: A string that indicates the theme LIGHT, DARK, or FOLLOW DEVICE. Default: FOLLOW DEVICE
|2020-10-01 | | -| onboarding.pref_toggled_toolbar_position |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The toolbar position preference was chosen from the onboarding card. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)|
  • position: A string that indicates the position of the toolbar TOP or BOTTOM. Default: BOTTOM
|2020-10-01 | | -| onboarding.pref_toggled_tracking_prot |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The tracking protection preference was chosen from the onboarding card. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)|
  • setting: A string that indicates the Tracking Protection policy STANDARD or STRICT. Default: Toggle ON, STANDARD
|2020-10-01 | | -| onboarding.privacy_notice |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The onboarding privacy notice card was tapped. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)||2020-10-01 | | -| onboarding.whats_new |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The onboarding What\'s New card was tapped. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)||2020-10-01 | | -| pocket.pocket_top_site_clicked |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user clicked on the trending Pocket top site |[1](https://github.com/mozilla-mobile/fenix/pull/8098)||2020-10-01 | | -| pocket.pocket_top_site_removed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removed the trending Pocket top site |[1](https://github.com/mozilla-mobile/fenix/pull/8098)||2020-10-01 | | -| private_browsing_mode.garbage_icon |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the garbage can icon on the private browsing home page, deleting all private tabs. |[1](https://github.com/mozilla-mobile/fenix/pull/4968)||2020-10-01 | | -| private_browsing_mode.notification_delete |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the private browsing mode notification's "Delete and Open" button. |[1](https://github.com/mozilla-mobile/fenix/pull/4968)||2020-10-01 | | -| private_browsing_mode.notification_open |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the private browsing mode notification's "Open" button. |[1](https://github.com/mozilla-mobile/fenix/pull/4968)||2020-10-01 | | -| private_browsing_mode.notification_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the private browsing mode notification itself. |[1](https://github.com/mozilla-mobile/fenix/pull/4968)||2020-10-01 | | -| private_browsing_mode.snackbar_undo |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "undo" button in the snackbar that is shown when the garbage icon is tapped. |[1](https://github.com/mozilla-mobile/fenix/pull/4968)||2020-10-01 | | -| private_browsing_shortcut.cfr_add_shortcut |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "Add shortcut" button when the contextual feature recommender appeared. |[1](https://github.com/mozilla-mobile/fenix/pull/5194)||2020-10-01 | | -| private_browsing_shortcut.cfr_cancel |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "No thanks" button when the contextual feature recommender appeared. |[1](https://github.com/mozilla-mobile/fenix/pull/5194)||2020-10-01 | | -| private_browsing_shortcut.create_shortcut |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "Add private browsing shortcut" button in settings. |[1](https://github.com/mozilla-mobile/fenix/pull/5194)||2020-10-01 | | -| private_browsing_shortcut.pinned_shortcut_priv |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the pinned private shortcut in Android home screen, opening up a new private search. |[1](https://github.com/mozilla-mobile/fenix/pull/5194)||2020-10-01 | | -| private_browsing_shortcut.static_shortcut_priv |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the long-press shortcut "Open new private tab", opening up a new private search. |[1](https://github.com/mozilla-mobile/fenix/pull/5194)||2020-10-01 | | -| private_browsing_shortcut.static_shortcut_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the long-press shortcut "Open new tab", opening up a new search. |[1](https://github.com/mozilla-mobile/fenix/pull/5194)||2020-10-01 | | -| progressive_web_app.background |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user puts the PWA into the background. |[1](https://github.com/mozilla-mobile/fenix/pull/11859)|
  • time_ms: The current time in ms when the PWA was backgrounded.
|2021-03-01 | | -| progressive_web_app.foreground |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user brings the PWA into the foreground. |[1](https://github.com/mozilla-mobile/fenix/pull/11859)|
  • time_ms: The current time in ms when the PWA was brought to the foreground.
|2021-03-01 | | -| progressive_web_app.homescreen_tap |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user taps on PWA homescreen icon |[1](https://github.com/mozilla-mobile/fenix/pull/11859)||2021-03-01 | | -| progressive_web_app.install_tap |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user installs a PWA. Could be a shortcut or added to homescreen. |[1](https://github.com/mozilla-mobile/fenix/pull/11859)||2021-03-01 | | -| qr_scanner.navigation_allowed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped "allow" on the prompt, directing the user to the website scanned |[1](https://github.com/mozilla-mobile/fenix/pull/2524#issuecomment-492739967)||2020-10-01 | | -| qr_scanner.navigation_denied |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped "deny" on the prompt, putting the user back to the scanning view |[1](https://github.com/mozilla-mobile/fenix/pull/2524#issuecomment-492739967)||2020-10-01 | | -| qr_scanner.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the QR scanner |[1](https://github.com/mozilla-mobile/fenix/pull/2524#issuecomment-492739967)||2020-10-01 | | -| qr_scanner.prompt_displayed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user scanned a QR code, causing a confirmation prompt to display asking if they want to navigate to the page |[1](https://github.com/mozilla-mobile/fenix/pull/2524#issuecomment-492739967)||2020-10-01 | | -| reader_mode.appearance |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the appearance button |[1](https://github.com/mozilla-mobile/fenix/pull/3941)||2020-10-01 | | -| reader_mode.available |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |Reader mode is available for the current page |[1](https://github.com/mozilla-mobile/fenix/pull/3941)||2020-10-01 | | -| reader_mode.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed reader mode |[1](https://github.com/mozilla-mobile/fenix/pull/4328)||2020-10-01 | | -| reader_mode.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened reader mode |[1](https://github.com/mozilla-mobile/fenix/pull/3941)||2020-10-01 | | +| events.browser_menu_action |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A browser menu item was tapped |[1](https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708), [2](https://github.com/mozilla-mobile/fenix/pull/5098#issuecomment-529658996), [3](https://github.com/mozilla-mobile/fenix/pull/6310)|
  • item: A string containing the name of the item the user tapped. These items include: Settings, Help, Desktop Site toggle on/off, Find in Page, New Tab, Private Tab, Share, Report Site Issue, Back/Forward button, Reload Button, Quit, Reader Mode On, Reader Mode Off, Open In app, Add To Top Sites, Add-ons Manager, Bookmarks, History
|2020-10-01 |2 | +| events.entered_url |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user entered a url |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673)|
  • autocomplete: A boolean that tells us whether the URL was autofilled by an Autocomplete suggestion
|2020-10-01 |2 | +| events.opened_link |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a link with Fenix |[1](https://github.com/mozilla-mobile/fenix/pull/5975)|
  • mode: The mode the link was opened in. Either 'PRIVATE' or 'NORMAL'.
|2020-10-01 |2 | +| events.performed_search |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user performed a search |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673), [2](https://github.com/mozilla-mobile/fenix/pull/1677)|
  • source: A string that tells us how the user performed the search. Possible values are: * default.action * default.suggestion * shortcut.action * shortcut.suggestion
|2020-10-01 |2 | +| events.preference_toggled |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user toggled a boolean preference in settings |[1](https://github.com/mozilla-mobile/fenix/pull/1896), [2](https://github.com/mozilla-mobile/fenix/pull/5704), [3](https://github.com/mozilla-mobile/fenix/pull/5886), [4](https://github.com/mozilla-mobile/fenix/pull/5975), [5](https://github.com/mozilla-mobile/fenix/pull/6352), [6](https://github.com/mozilla-mobile/fenix/pull/6601), [7](https://github.com/mozilla-mobile/fenix/pull/6746)|
  • enabled: Whether or not the preference is *now* enabled
  • preference_key: The preference key for the boolean (true/false) preference the user toggled. We currently track: show_search_suggestions, remote_debugging, telemetry, tracking_protection, search_bookmarks, search_browsing_history, show_clipboard_suggestions, show_search_shortcuts, open_links_in_a_private_tab (bug in implementation https://github.com/mozilla-mobile/fenix/issues/7384), pref_key_sync_logins, pref_key_sync_bookmarks, pref_key_sync_history, pref_key_show_voice_search, and pref_key_show_search_suggestions_in_private.
|2020-10-01 |1, 2 | +| events.search_bar_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the search bar |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673)|
  • source: The view the user was on when they initiated the search (For example: `Home` or `Browser`)
|2020-10-01 |2 | +| events.tab_counter_menu_action |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A tab counter menu item was tapped |[1](https://github.com/mozilla-mobile/fenix/pull/11533)|
  • item: A string containing the name of the item the user tapped. These items are: New tab, New private tab, Close tab
|2020-10-01 |2 | +| events.whats_new_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the "what's new" page button |[1](https://github.com/mozilla-mobile/fenix/pull/5090)||2020-10-01 |2 | +| find_in_page.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed the find in page UI |[1](https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010)||2020-10-01 |2 | +| find_in_page.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the find in page UI |[1](https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010)||2020-10-01 |2 | +| find_in_page.searched_page |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user searched the page |[1](https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010)||2020-10-01 |2 | +| history.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the history screen |[1](https://github.com/mozilla-mobile/fenix/pull/3940)||2020-10-01 |2 | +| history.opened_item |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a history item |[1](https://github.com/mozilla-mobile/fenix/pull/3940)||2020-10-01 |2 | +| history.removed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removed a history item |[1](https://github.com/mozilla-mobile/fenix/pull/3940)||2020-10-01 |2 | +| history.removed_all |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removed all history items |[1](https://github.com/mozilla-mobile/fenix/pull/3940)||2020-10-01 |2 | +| history.shared |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user shared a history item |[1](https://github.com/mozilla-mobile/fenix/pull/3940)||2020-10-01 |2 | +| login_dialog.cancelled |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The login dialog prompt was cancelled |[1](https://github.com/mozilla-mobile/fenix/pull/13050)||2021-02-01 |2 | +| login_dialog.displayed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The login dialog prompt was displayed |[1](https://github.com/mozilla-mobile/fenix/pull/13050)||2021-02-01 |2 | +| login_dialog.never_save |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The login dialog prompt "never save" button was pressed |[1](https://github.com/mozilla-mobile/fenix/pull/13050)||2021-02-01 |2 | +| login_dialog.saved |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The login dialog prompt "save" button was pressed |[1](https://github.com/mozilla-mobile/fenix/pull/13050)||2021-02-01 |2 | +| logins.copy_login |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user copied a piece of a login in saved logins |[1](https://github.com/mozilla-mobile/fenix/pull/6352)||2020-10-01 |2 | +| logins.delete_saved_login |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user confirms delete of a saved login |[1](https://github.com/mozilla-mobile/fenix/issues/11208)||2020-10-01 |2 | +| logins.open_individual_login |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user accessed an individual login in saved logins |[1](https://github.com/mozilla-mobile/fenix/pull/6352)||2020-10-01 |2 | +| logins.open_login_editor |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user entered the edit screen for an individual saved login |[1](https://github.com/mozilla-mobile/fenix/issues/11208)||2020-10-01 |2 | +| logins.open_logins |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user accessed Logins in Settings |[1](https://github.com/mozilla-mobile/fenix/pull/6352)||2020-10-01 |2 | +| logins.save_edited_login |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user saves changes made to an individual login |[1](https://github.com/mozilla-mobile/fenix/issues/11208)||2020-10-01 |2 | +| logins.save_logins_setting_changed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user changed their setting for asking to save logins |[1](https://github.com/mozilla-mobile/fenix/pull/7767)|
  • setting: The new setting for saving logins the user selected. Either `ask_to_save` or `never_save`
|2020-10-01 |2 | +| logins.view_password_login |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user viewed a password in an individual saved login |[1](https://github.com/mozilla-mobile/fenix/pull/6352)||2020-10-01 |2 | +| media_notification.pause |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the pause icon on the media notification |[1](https://github.com/mozilla-mobile/fenix/pull/5520)||2020-10-01 |2 | +| media_notification.play |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the play icon on the media notification |[1](https://github.com/mozilla-mobile/fenix/pull/5520)||2020-10-01 |2 | +| media_state.pause |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |Media playback was paused. |[1](https://github.com/mozilla-mobile/fenix/pull/6463)||2020-10-01 |2 | +| media_state.play |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |Media started playing. |[1](https://github.com/mozilla-mobile/fenix/pull/6463)||2020-10-01 |2 | +| media_state.stop |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |Media playback has ended. |[1](https://github.com/mozilla-mobile/fenix/pull/6463)||2020-10-01 |2 | +| onboarding.finish |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user taps starts browsing and ends the onboarding experience. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)||2020-10-01 |2 | +| onboarding.fxa_auto_signin |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The onboarding automatic sign in card was tapped. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)||2020-10-01 |2 | +| onboarding.fxa_manual_signin |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The onboarding manual sign in card was tapped. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)||2020-10-01 |2 | +| onboarding.pref_toggled_private_browsing |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The private browsing preference was selected from the onboarding card. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)||2020-10-01 |2 | +| onboarding.pref_toggled_theme_picker |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The device theme was chosen using the theme picker onboarding card. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)|
  • theme: A string that indicates the theme LIGHT, DARK, or FOLLOW DEVICE. Default: FOLLOW DEVICE
|2020-10-01 |2 | +| onboarding.pref_toggled_toolbar_position |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The toolbar position preference was chosen from the onboarding card. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)|
  • position: A string that indicates the position of the toolbar TOP or BOTTOM. Default: BOTTOM
|2020-10-01 |2 | +| onboarding.pref_toggled_tracking_prot |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The tracking protection preference was chosen from the onboarding card. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)|
  • setting: A string that indicates the Tracking Protection policy STANDARD or STRICT. Default: Toggle ON, STANDARD
|2020-10-01 |2 | +| onboarding.privacy_notice |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The onboarding privacy notice card was tapped. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)||2020-10-01 |2 | +| onboarding.whats_new |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The onboarding What\'s New card was tapped. |[1](https://github.com/mozilla-mobile/fenix/pull/11867)||2020-10-01 |2 | +| pocket.pocket_top_site_clicked |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user clicked on the trending Pocket top site |[1](https://github.com/mozilla-mobile/fenix/pull/8098)||2020-10-01 |2 | +| pocket.pocket_top_site_removed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removed the trending Pocket top site |[1](https://github.com/mozilla-mobile/fenix/pull/8098)||2020-10-01 |2 | +| private_browsing_mode.garbage_icon |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the garbage can icon on the private browsing home page, deleting all private tabs. |[1](https://github.com/mozilla-mobile/fenix/pull/4968)||2020-10-01 |2 | +| private_browsing_mode.notification_delete |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the private browsing mode notification's "Delete and Open" button. |[1](https://github.com/mozilla-mobile/fenix/pull/4968)||2020-10-01 |2 | +| private_browsing_mode.notification_open |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the private browsing mode notification's "Open" button. |[1](https://github.com/mozilla-mobile/fenix/pull/4968)||2020-10-01 |2 | +| private_browsing_mode.notification_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the private browsing mode notification itself. |[1](https://github.com/mozilla-mobile/fenix/pull/4968)||2020-10-01 |2 | +| private_browsing_mode.snackbar_undo |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "undo" button in the snackbar that is shown when the garbage icon is tapped. |[1](https://github.com/mozilla-mobile/fenix/pull/4968)||2020-10-01 |2 | +| private_browsing_shortcut.cfr_add_shortcut |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "Add shortcut" button when the contextual feature recommender appeared. |[1](https://github.com/mozilla-mobile/fenix/pull/5194)||2020-10-01 |2 | +| private_browsing_shortcut.cfr_cancel |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "No thanks" button when the contextual feature recommender appeared. |[1](https://github.com/mozilla-mobile/fenix/pull/5194)||2020-10-01 |2 | +| private_browsing_shortcut.create_shortcut |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "Add private browsing shortcut" button in settings. |[1](https://github.com/mozilla-mobile/fenix/pull/5194)||2020-10-01 |2 | +| private_browsing_shortcut.pinned_shortcut_priv |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the pinned private shortcut in Android home screen, opening up a new private search. |[1](https://github.com/mozilla-mobile/fenix/pull/5194)||2020-10-01 |2 | +| private_browsing_shortcut.static_shortcut_priv |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the long-press shortcut "Open new private tab", opening up a new private search. |[1](https://github.com/mozilla-mobile/fenix/pull/5194)||2020-10-01 |2 | +| private_browsing_shortcut.static_shortcut_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the long-press shortcut "Open new tab", opening up a new search. |[1](https://github.com/mozilla-mobile/fenix/pull/5194)||2020-10-01 |2 | +| progressive_web_app.background |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user puts the PWA into the background. |[1](https://github.com/mozilla-mobile/fenix/pull/11859)|
  • time_ms: The current time in ms when the PWA was backgrounded.
|2021-03-01 |2 | +| progressive_web_app.foreground |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user brings the PWA into the foreground. |[1](https://github.com/mozilla-mobile/fenix/pull/11859)|
  • time_ms: The current time in ms when the PWA was brought to the foreground.
|2021-03-01 |2 | +| progressive_web_app.homescreen_tap |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user taps on PWA homescreen icon |[1](https://github.com/mozilla-mobile/fenix/pull/11859)||2021-03-01 |2 | +| progressive_web_app.install_tap |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user installs a PWA. Could be a shortcut or added to homescreen. |[1](https://github.com/mozilla-mobile/fenix/pull/11859)||2021-03-01 |2 | +| qr_scanner.navigation_allowed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped "allow" on the prompt, directing the user to the website scanned |[1](https://github.com/mozilla-mobile/fenix/pull/2524#issuecomment-492739967)||2020-10-01 |2 | +| qr_scanner.navigation_denied |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped "deny" on the prompt, putting the user back to the scanning view |[1](https://github.com/mozilla-mobile/fenix/pull/2524#issuecomment-492739967)||2020-10-01 |2 | +| qr_scanner.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the QR scanner |[1](https://github.com/mozilla-mobile/fenix/pull/2524#issuecomment-492739967)||2020-10-01 |2 | +| qr_scanner.prompt_displayed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user scanned a QR code, causing a confirmation prompt to display asking if they want to navigate to the page |[1](https://github.com/mozilla-mobile/fenix/pull/2524#issuecomment-492739967)||2020-10-01 |2 | +| reader_mode.appearance |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the appearance button |[1](https://github.com/mozilla-mobile/fenix/pull/3941)||2020-10-01 |2 | +| reader_mode.available |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |Reader mode is available for the current page |[1](https://github.com/mozilla-mobile/fenix/pull/3941)||2020-10-01 |2 | +| reader_mode.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed reader mode |[1](https://github.com/mozilla-mobile/fenix/pull/4328)||2020-10-01 |2 | +| reader_mode.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened reader mode |[1](https://github.com/mozilla-mobile/fenix/pull/3941)||2020-10-01 |2 | | search_shortcuts.selected |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user selected a search shortcut engine to use |[1](https://github.com/mozilla-mobile/fenix/pull/1202#issuecomment-476870449)|
  • engine: The name of the built-in search engine the user selected as a string
|2020-10-01 | | -| search_suggestions.enable_in_private |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user enabled receiving search suggestions in private sessions |[1](https://github.com/mozilla-mobile/fenix/pull/6746)||2020-10-01 | | -| search_widget.new_tab_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed anywhere from the Firefox logo until the start of the microphone icon, opening a new tab search screen. |[1](https://github.com/mozilla-mobile/fenix/pull/4714)||2020-10-01 | | -| search_widget.voice_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the microphone icon, opening a new voice search screen. |[1](https://github.com/mozilla-mobile/fenix/pull/4714)||2020-10-01 | | -| search_widget_cfr.add_widget_pressed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user pressed the "add widget" button. |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-10-01 | | -| search_widget_cfr.canceled |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user dismissed the search widget cfr by tapping outside of the prompt |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-10-01 | | -| search_widget_cfr.displayed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The search widget cfr was displayed. |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-10-01 | | -| search_widget_cfr.not_now_pressed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user pressed the "not now" button. |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-10-01 | | -| sync_account.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed the sync account page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 | | -| sync_account.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the sync account page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 | | -| sync_account.send_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user sent the current tab to another FxA device |[1](https://github.com/mozilla-mobile/fenix/pull/5106)||2020-10-01 | | -| sync_account.sign_in_to_send_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "sign in to send tab" button inside the share tab menu |[1](https://github.com/mozilla-mobile/fenix/pull/5106)||2020-10-01 | | -| sync_account.sync_now |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the sync now button on the sync account page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 | | -| sync_auth.auto_login |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |User signed into FxA via an account shared from another locally installed Mozilla application (e.g. Fennec) |[1](https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300)||2020-10-01 | | -| sync_auth.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed the sync page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 | | -| sync_auth.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the sync authentication page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 | | -| sync_auth.other_external |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |User authenticated via FxA using an unknown mechanism. "Known" mechanisms are currently sign-in, sign-up and pairing |[1](https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300)||2020-10-01 | | -| sync_auth.paired |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |User signed into FxA by pairing with a different Firefox browser, using a QR code |[1](https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300)||2020-10-01 | | -| sync_auth.recovered |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |Account manager automatically recovered FxA authentication state without direct user involvement |[1](https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300)||2020-10-01 | | -| sync_auth.scan_pairing |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the scan pairing button on the sync authentication page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 | | -| sync_auth.sign_in |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the sign in button on the sync authentication page and was successfully signed in to FxA |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 | | -| sync_auth.sign_out |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the sign out button on the sync account page and was successfully signed out of FxA |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 | | -| sync_auth.sign_up |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |User registered a new Firefox Account, and was signed into it |[1](https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300)||2020-10-01 | | -| sync_auth.use_email |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user chose to use their email to sign in instead of scanning a QR code, counterpart to "scan_pairing" |[1](https://github.com/mozilla-mobile/fenix/pull/9835#pullrequestreview-398641844)||2020-10-01 | | -| sync_auth.use_email_problem |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user chose to use their email to sign in after an account problem |[1](https://github.com/mozilla-mobile/fenix/pull/9835#pullrequestreview-398641844)||2020-10-01 | | -| tab.media_pause |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the pause icon on a tab from the home screen |[1](https://github.com/mozilla-mobile/fenix/pull/5266)||2020-10-01 | | -| tab.media_play |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the play icon on a tab from the home screen |[1](https://github.com/mozilla-mobile/fenix/pull/5266)||2020-10-01 | | -| tabs_tray.close_all_tabs |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the close all tabs button in the three dot menu within the tabs tray |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 | | -| tabs_tray.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed the tabs tray |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 | | -| tabs_tray.closed_existing_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed an existing tab |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 | | -| tabs_tray.menu_opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened three three dot menu in the tabs tray |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 | | -| tabs_tray.new_private_tab_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a new private tab |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 | | -| tabs_tray.new_tab_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a new tab |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 | | -| tabs_tray.normal_mode_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user switched to normal mode |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 | | -| tabs_tray.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the tabs tray |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 | | -| tabs_tray.opened_existing_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened an existing tab |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 | | -| tabs_tray.private_mode_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user switched to private mode |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 | | -| tabs_tray.save_to_collection |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the save to collection button in the three dot menu within the tabs tray |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 | | -| tabs_tray.share_all_tabs |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the share all tabs button in the three dot menu within the tabs tray |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 | | -| tip.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The tip was closed |[1](https://github.com/mozilla-mobile/fenix/pull/9836)|
  • identifier: The identifier of the tip closed
|2020-10-01 | | -| tip.displayed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The tip was displayed |[1](https://github.com/mozilla-mobile/fenix/pull/9836)|
  • identifier: The identifier of the tip displayed
|2020-10-01 | | -| tip.pressed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The tip's button was pressed |[1](https://github.com/mozilla-mobile/fenix/pull/9836)|
  • identifier: The identifier of the tip the action was taken on
|2020-10-01 | | -| toolbar_settings.changed_position |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user selected a new position for the toolbar |[1](https://github.com/mozilla-mobile/fenix/pull/6608)|
  • position: A string that indicates the new position of the toolbar TOP or BOTTOM
|2020-10-01 | | -| top_sites.open_default |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a default top site |[1](https://github.com/mozilla-mobile/fenix/pull/10752)||2020-10-01 | | -| top_sites.open_in_new_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opens a new tab based on a top site item |[1](https://github.com/mozilla-mobile/fenix/pull/7523)||2020-10-01 | | -| top_sites.open_in_private_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opens a new private tab based on a top site item |[1](https://github.com/mozilla-mobile/fenix/pull/7523)||2020-10-01 | | -| top_sites.remove |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removes a top site item |[1](https://github.com/mozilla-mobile/fenix/pull/7523)||2020-10-01 | | -| tracking_protection.etp_setting_changed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user changed their tracking protection level setting to either strict, standard, or custom. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188), [2](https://github.com/mozilla-mobile/fenix/pull/11383)|
  • etp_setting: The new setting for ETP: strict, standard, custom
|2020-10-01 | | -| tracking_protection.etp_settings |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened tracking protection settings through settings. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188)||2020-10-01 | | -| tracking_protection.etp_shield |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the tracking protection shield icon in toolbar. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188)||2020-10-01 | | -| tracking_protection.etp_tracker_list |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed into a list of categorized trackers in tracking protection panel. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188)||2020-10-01 | | -| tracking_protection.exception_added |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user added a tracking protection exception through the TP toggle in the panel. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188)||2020-10-01 | | -| tracking_protection.panel_settings |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened tracking protection settings from the panel. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188)||2020-10-01 | | -| user_specified_search_engines.custom_engine_added |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user added a new custom search engine |[1](https://github.com/mozilla-mobile/fenix/pull/6918)||2020-10-01 | | -| user_specified_search_engines.custom_engine_deleted |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user deleted a custom search engine |[1](https://github.com/mozilla-mobile/fenix/pull/6918)||2020-10-01 | | -| voice_search.tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user selected the voice search button on the search screen. |[1](https://github.com/mozilla-mobile/fenix/pull/10785)||2020-10-01 | | +| search_suggestions.enable_in_private |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user enabled receiving search suggestions in private sessions |[1](https://github.com/mozilla-mobile/fenix/pull/6746)||2020-10-01 |1, 2 | +| search_widget.new_tab_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed anywhere from the Firefox logo until the start of the microphone icon, opening a new tab search screen. |[1](https://github.com/mozilla-mobile/fenix/pull/4714)||2020-10-01 |2 | +| search_widget.voice_button |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the microphone icon, opening a new voice search screen. |[1](https://github.com/mozilla-mobile/fenix/pull/4714)||2020-10-01 |2 | +| search_widget_cfr.add_widget_pressed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user pressed the "add widget" button. |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-10-01 |2 | +| search_widget_cfr.canceled |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user dismissed the search widget cfr by tapping outside of the prompt |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-10-01 |2 | +| search_widget_cfr.displayed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The search widget cfr was displayed. |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-10-01 |2 | +| search_widget_cfr.not_now_pressed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user pressed the "not now" button. |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-10-01 |2 | +| sync_account.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed the sync account page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 |2 | +| sync_account.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the sync account page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 |2 | +| sync_account.send_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user sent the current tab to another FxA device |[1](https://github.com/mozilla-mobile/fenix/pull/5106)||2020-10-01 |2 | +| sync_account.sign_in_to_send_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the "sign in to send tab" button inside the share tab menu |[1](https://github.com/mozilla-mobile/fenix/pull/5106)||2020-10-01 |2 | +| sync_account.sync_now |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the sync now button on the sync account page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 |2 | +| sync_auth.auto_login |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |User signed into FxA via an account shared from another locally installed Mozilla application (e.g. Fennec) |[1](https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300)||2020-10-01 |1, 2 | +| sync_auth.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed the sync page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 |2 | +| sync_auth.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the sync authentication page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 |2 | +| sync_auth.other_external |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |User authenticated via FxA using an unknown mechanism. "Known" mechanisms are currently sign-in, sign-up and pairing |[1](https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300)||2020-10-01 |1, 2 | +| sync_auth.paired |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |User signed into FxA by pairing with a different Firefox browser, using a QR code |[1](https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300)||2020-10-01 |1, 2 | +| sync_auth.recovered |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |Account manager automatically recovered FxA authentication state without direct user involvement |[1](https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300)||2020-10-01 |1, 2 | +| sync_auth.scan_pairing |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the scan pairing button on the sync authentication page |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 |2 | +| sync_auth.sign_in |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the sign in button on the sync authentication page and was successfully signed in to FxA |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 |2 | +| sync_auth.sign_out |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the sign out button on the sync account page and was successfully signed out of FxA |[1](https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532)||2020-10-01 |2 | +| sync_auth.sign_up |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |User registered a new Firefox Account, and was signed into it |[1](https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300)||2020-10-01 |1, 2 | +| sync_auth.use_email |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user chose to use their email to sign in instead of scanning a QR code, counterpart to "scan_pairing" |[1](https://github.com/mozilla-mobile/fenix/pull/9835#pullrequestreview-398641844)||2020-10-01 |2 | +| sync_auth.use_email_problem |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user chose to use their email to sign in after an account problem |[1](https://github.com/mozilla-mobile/fenix/pull/9835#pullrequestreview-398641844)||2020-10-01 |2 | +| tab.media_pause |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the pause icon on a tab from the home screen |[1](https://github.com/mozilla-mobile/fenix/pull/5266)||2020-10-01 |2 | +| tab.media_play |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the play icon on a tab from the home screen |[1](https://github.com/mozilla-mobile/fenix/pull/5266)||2020-10-01 |2 | +| tabs_tray.close_all_tabs |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the close all tabs button in the three dot menu within the tabs tray |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 |2 | +| tabs_tray.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed the tabs tray |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 |2 | +| tabs_tray.closed_existing_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed an existing tab |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 |2 | +| tabs_tray.menu_opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened three three dot menu in the tabs tray |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 |2 | +| tabs_tray.new_private_tab_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a new private tab |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 |2 | +| tabs_tray.new_tab_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a new tab |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 |2 | +| tabs_tray.normal_mode_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user switched to normal mode |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 |2 | +| tabs_tray.opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the tabs tray |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 |2 | +| tabs_tray.opened_existing_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened an existing tab |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 |2 | +| tabs_tray.private_mode_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user switched to private mode |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 |2 | +| tabs_tray.save_to_collection |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the save to collection button in the three dot menu within the tabs tray |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 |2 | +| tabs_tray.share_all_tabs |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the share all tabs button in the three dot menu within the tabs tray |[1](https://github.com/mozilla-mobile/fenix/pull/12036)||2020-10-01 |2 | +| tip.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The tip was closed |[1](https://github.com/mozilla-mobile/fenix/pull/9836)|
  • identifier: The identifier of the tip closed
|2020-10-01 |2 | +| tip.displayed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The tip was displayed |[1](https://github.com/mozilla-mobile/fenix/pull/9836)|
  • identifier: The identifier of the tip displayed
|2020-10-01 |2 | +| tip.pressed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The tip's button was pressed |[1](https://github.com/mozilla-mobile/fenix/pull/9836)|
  • identifier: The identifier of the tip the action was taken on
|2020-10-01 |2 | +| toolbar_settings.changed_position |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |The user selected a new position for the toolbar |[1](https://github.com/mozilla-mobile/fenix/pull/6608)|
  • position: A string that indicates the new position of the toolbar TOP or BOTTOM
|2020-10-01 |2 | +| top_sites.open_default |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a default top site |[1](https://github.com/mozilla-mobile/fenix/pull/10752)||2020-10-01 |2 | +| top_sites.open_in_new_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opens a new tab based on a top site item |[1](https://github.com/mozilla-mobile/fenix/pull/7523)||2020-10-01 |2 | +| top_sites.open_in_private_tab |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opens a new private tab based on a top site item |[1](https://github.com/mozilla-mobile/fenix/pull/7523)||2020-10-01 |2 | +| top_sites.remove |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user removes a top site item |[1](https://github.com/mozilla-mobile/fenix/pull/7523)||2020-10-01 |2 | +| tracking_protection.etp_setting_changed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user changed their tracking protection level setting to either strict, standard, or custom. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188), [2](https://github.com/mozilla-mobile/fenix/pull/11383)|
  • etp_setting: The new setting for ETP: strict, standard, custom
|2020-10-01 |2 | +| tracking_protection.etp_settings |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened tracking protection settings through settings. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188)||2020-10-01 |2 | +| tracking_protection.etp_shield |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed the tracking protection shield icon in toolbar. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188)||2020-10-01 |2 | +| tracking_protection.etp_tracker_list |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user pressed into a list of categorized trackers in tracking protection panel. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188)||2020-10-01 |2 | +| tracking_protection.exception_added |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user added a tracking protection exception through the TP toggle in the panel. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188)||2020-10-01 |2 | +| tracking_protection.panel_settings |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened tracking protection settings from the panel. |[1](https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188)||2020-10-01 |2 | +| user_specified_search_engines.custom_engine_added |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user added a new custom search engine |[1](https://github.com/mozilla-mobile/fenix/pull/6918)||2020-10-01 |2 | +| user_specified_search_engines.custom_engine_deleted |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user deleted a custom search engine |[1](https://github.com/mozilla-mobile/fenix/pull/6918)||2020-10-01 |2 | +| voice_search.tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user selected the voice search button on the search screen. |[1](https://github.com/mozilla-mobile/fenix/pull/10785)||2020-10-01 |2 | ## first-session @@ -248,11 +248,11 @@ The following metrics are added to the ping: | Name | Type | Description | Data reviews | Extras | Expiration | [Data Sensitivity](https://wiki.mozilla.org/Firefox/Data_Collection) | | --- | --- | --- | --- | --- | --- | --- | -| first_session.adgroup |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |The name of the AdGroup that was used to source this installation. |[1](https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586480836)||2020-10-01 | | -| first_session.campaign |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |The name of the campaign that is responsible for this installation. |[1](https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202)||2020-10-01 | | -| first_session.creative |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |The identifier of the creative material that the user interacted with. |[1](https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202)||2020-10-01 | | -| first_session.network |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |The name of the Network that sourced this installation. |[1](https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202)||2020-10-01 | | -| first_session.timestamp |[datetime](https://mozilla.github.io/glean/book/user/metrics/datetime.html) |The Glean generated date and time of the installation. This is unique per app install, though the rest of the data in this ping is from Adjust and will remain static across installs. |[1](https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202)||2020-10-01 | | +| first_session.adgroup |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |The name of the AdGroup that was used to source this installation. |[1](https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586480836)||2020-10-01 |1, 2 | +| first_session.campaign |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |The name of the campaign that is responsible for this installation. |[1](https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202)||2020-10-01 |1, 2 | +| first_session.creative |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |The identifier of the creative material that the user interacted with. |[1](https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202)||2020-10-01 |1, 2 | +| first_session.network |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |The name of the Network that sourced this installation. |[1](https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202)||2020-10-01 |1, 2 | +| first_session.timestamp |[datetime](https://mozilla.github.io/glean/book/user/metrics/datetime.html) |The Glean generated date and time of the installation. This is unique per app install, though the rest of the data in this ping is from Adjust and will remain static across installs. |[1](https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202)||2020-10-01 |1, 2 | ## metrics @@ -264,61 +264,61 @@ The following metrics are added to the ping: | Name | Type | Description | Data reviews | Extras | Expiration | [Data Sensitivity](https://wiki.mozilla.org/Firefox/Data_Collection) | | --- | --- | --- | --- | --- | --- | --- | -| addons.enabled_addons |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |A list of all enabled add-ons on the device. |[1](https://github.com/mozilla-mobile/fenix/pull/11080)||2020-10-01 | | -| addons.has_enabled_addons |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has enabled add-ons on the device. |[1](https://github.com/mozilla-mobile/fenix/pull/8318)||2020-10-01 | | -| addons.has_installed_addons |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has installed add-ons on the device. |[1](https://github.com/mozilla-mobile/fenix/pull/8318)||2020-10-01 | | -| addons.installed_addons |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |A list of all installed add-ons on the device. |[1](https://github.com/mozilla-mobile/fenix/pull/11080)||2020-10-01 | | -| browser.search.ad_clicks |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |Records clicks of adverts on SERP pages. The key format is ‘’. |[1](https://github.com/mozilla-mobile/fenix/pull/10112)||2020-10-01 | | -| browser.search.in_content |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |Records the type of interaction a user has on SERP pages. |[1](https://github.com/mozilla-mobile/fenix/pull/10167)||2020-10-01 | | -| browser.search.with_ads |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |Records counts of SERP pages with adverts displayed. The key format is ‘’. |[1](https://github.com/mozilla-mobile/fenix/pull/10112)||2020-10-01 | | -| events.total_uri_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter of URIs visited by the user in the current session, including page reloads. This does not include background page requests and URIs from embedded pages or private browsing but may be incremented without user interaction by website scripts that programmatically redirect to a new location. |[1](https://github.com/mozilla-mobile/fenix/pull/1785), [2](https://github.com/mozilla-mobile/fenix/pull/8314)||2020-10-01 | | -| metrics.adjust_ad_group |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string containing the Adjust ad group ID from which the user installed Fenix. This will not send on the first session the user runs. If the install is organic, this will be empty. |[1](https://github.com/mozilla-mobile/fenix/pull/9253)||2020-10-01 | | -| metrics.adjust_campaign |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string containing the Adjust campaign ID from which the user installed Fenix. This will not send on the first session the user runs. If the install is organic, this will be empty. |[1](https://github.com/mozilla-mobile/fenix/pull/5579)||2020-10-01 | | -| metrics.adjust_creative |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string containing the Adjust creative ID from which the user installed Fenix. This will not send on the first session the user runs. If the install is organic, this will be empty. |[1](https://github.com/mozilla-mobile/fenix/pull/9253)||2020-10-01 | | -| metrics.adjust_network |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string containing the Adjust network ID from which the user installed Fenix. This will not send on the first session the user runs. If the install is organic, this will be empty. |[1](https://github.com/mozilla-mobile/fenix/pull/9253)||2020-10-01 | | -| metrics.default_browser |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Is Fenix the default browser? |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673)||2020-10-01 | | -| metrics.default_moz_browser |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |The name of the default browser on device if and only if it's a Mozilla owned product |[1](https://github.com/mozilla-mobile/fenix/pull/1953/), [2](https://github.com/mozilla-mobile/fenix/pull/5216)||2020-10-01 | | -| metrics.has_open_tabs |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |A boolean that indicates if the user has any open NORMAL tabs. |[1](https://github.com/mozilla-mobile/fenix/pull/12024)||2020-10-01 | | -| metrics.has_recent_pwas |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |A boolean that indicates if the user has recently used PWAs. See recently_used_pwa_count for the actual count. |[1](https://github.com/mozilla-mobile/fenix/pull/11982#pullrequestreview-437963817)||2020-12-01 | | -| metrics.has_top_sites |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |A boolean that indicates if the user has top sites |[1](https://github.com/mozilla-mobile/fenix/pull/9556)||2020-10-01 | | -| metrics.mozilla_products |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |A list of all the Mozilla products installed on device. We currently scan for: Firefox, Firefox Beta, Firefox Aurora, Firefox Nightly, Firefox Fdroid, Firefox Lite, Reference Browser, Reference Browser Debug, Fenix, Focus, and Lockwise. |[1](https://github.com/mozilla-mobile/fenix/pull/1953/), [2](https://github.com/mozilla-mobile/fenix/pull/5216)||2020-10-01 | | -| metrics.recently_used_pwa_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter that indicates how many PWAs a user has recently used. Threshold for "recency" set in HomeActivity#PWA_RECENTLY_USED_THRESHOLD. Currently we are not told by the OS when a PWA is removed by the user, so we use the "recently used" heuristic to judge how many PWAs are still active, as a proxy for "installed". This value will only be set if the user has at least *one* recently used PWA. If they have 0, this metric will not be sent, resulting in a null value during analysis on the server-side. To disambiguate between a failed `recently_used_pwa_count` metric and 0 recent PWAs, please see `has_recent_pwas`. |[1](https://github.com/mozilla-mobile/fenix/pull/11982#pullrequestreview-437963817)||2020-12-01 | | -| metrics.search_count |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |The labels for this counter are `.`. If the search engine is bundled with Fenix `search-engine-name` will be the name of the search engine. If it's a custom search engine (defined: https://github.com/mozilla-mobile/fenix/issues/1607) the value will be `custom`. `source` will be: `action`, `suggestion`, `widget` or `shortcut` (depending on the source from which the search started). Also added the `other` option for the source but it should never enter on this case. |[1](https://github.com/mozilla-mobile/fenix/pull/1677), [2](https://github.com/mozilla-mobile/fenix/pull/5216), [3](https://github.com/mozilla-mobile/fenix/pull/7310)||2020-10-01 | | -| metrics.search_widget_installed |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the search widget is installed |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-10-01 | | -| metrics.tabs_open_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter that indicates how many NORMAL tabs a user has open. This value will only be set if the user has at least *one* open tab. If they have 0, this ping will not get sent, resulting in a null value. To disambiguate between a failed `tabs_open_count` ping and 0 open tabs, please see `has_open_tabs`. |[1](https://github.com/mozilla-mobile/fenix/pull/12024)||2020-10-01 | | -| metrics.toolbar_position |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string that indicates the new position of the toolbar TOP or BOTTOM |[1](https://github.com/mozilla-mobile/fenix/pull/6608)||2020-10-01 | | -| metrics.top_sites_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter that indicates how many top sites a user has. This value will only be set if the user has at least *one* top site. If they have 0, this ping will not get sent, resulting in a null value. To disambiguate between a failed `top_sites_count` ping and 0 top sites, please see `has_top_sites`. |[1](https://github.com/mozilla-mobile/fenix/pull/9556)||2020-10-01 | | -| perf.awesomebar.bookmark_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a bookmarks awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 | | -| perf.awesomebar.clipboard_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a clipboard awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 | | -| perf.awesomebar.history_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a history awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 | | -| perf.awesomebar.search_engine_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a search engine awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 | | -| perf.awesomebar.session_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a session awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 | | -| perf.awesomebar.shortcuts_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a shortcuts awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 | | -| perf.awesomebar.synced_tabs_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a synced tabs awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 | | -| 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: "" |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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 |[1](https://github.com/mozilla-mobile/fenix/pull/11446)||2020-10-01 | | -| 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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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) |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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] |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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" |[1](https://github.com/mozilla-mobile/fenix/pull/11446)||2020-10-01 | | -| 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) |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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" |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-01 | | -| 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" |[1](https://github.com/mozilla-mobile/fenix/pull/1606), [2](https://github.com/mozilla-mobile/fenix/pull/5216)||2020-10-01 | | -| 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" |[1](https://github.com/mozilla-mobile/fenix/pull/1606), [2](https://github.com/mozilla-mobile/fenix/pull/5216)||2020-10-01 | | -| 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" |[1](https://github.com/mozilla-mobile/fenix/pull/1606), [2](https://github.com/mozilla-mobile/fenix/pull/5216)||2020-10-01 | | -| storage.stats.app_bytes |[memory_distribution](https://mozilla.github.io/glean/book/user/metrics/memory_distribution.html) |The size of the app's APK and related files as installed: this is expected to be larger than download size. This is the output of [StorageStats.getAppBytes](https://developer.android.com/reference/android/app/usage/StorageStats#getAppBytes()) so see that for details. This value is only available on Android 8+. A similar value may be available on the Google Play dashboard: we can use this value to see if that value is reliable enough. |[1](https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732)||2021-02-01 | | -| storage.stats.cache_bytes |[memory_distribution](https://mozilla.github.io/glean/book/user/metrics/memory_distribution.html) |The size of all cached data in the app. This is the output of [StorageStats.getCacheBytes](https://developer.android.com/reference/android/app/usage/StorageStats#getCacheBytes()) so see that for details. This value is only available on Android 8+. |[1](https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732)||2021-02-01 | | -| storage.stats.data_dir_bytes |[memory_distribution](https://mozilla.github.io/glean/book/user/metrics/memory_distribution.html) |The size of all data minus `cache_bytes`. This is the output of [StorageStats.getDataBytes](https://developer.android.com/reference/android/app/usage/StorageStats#getDataBytes()) except we subtract the value of `cache_bytes` so the cache is not measured redundantly; see that method for details. This value is only available on Android 8+. |[1](https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732)||2021-02-01 | | -| storage.stats.query_stats_duration |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |How long it took to query the device for the StorageStats that contain the file size information. The docs say it may be expensive so we want to ensure it's not too expensive. This value is only available on Android 8+. |[1](https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732)||2021-02-01 | | +| addons.enabled_addons |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |A list of all enabled add-ons on the device. |[1](https://github.com/mozilla-mobile/fenix/pull/11080)||2020-10-01 |2 | +| addons.has_enabled_addons |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has enabled add-ons on the device. |[1](https://github.com/mozilla-mobile/fenix/pull/8318)||2020-10-01 |2 | +| addons.has_installed_addons |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the user has installed add-ons on the device. |[1](https://github.com/mozilla-mobile/fenix/pull/8318)||2020-10-01 |2 | +| addons.installed_addons |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |A list of all installed add-ons on the device. |[1](https://github.com/mozilla-mobile/fenix/pull/11080)||2020-10-01 |2 | +| browser.search.ad_clicks |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |Records clicks of adverts on SERP pages. The key format is ‘’. |[1](https://github.com/mozilla-mobile/fenix/pull/10112)||2020-10-01 |2 | +| browser.search.in_content |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |Records the type of interaction a user has on SERP pages. |[1](https://github.com/mozilla-mobile/fenix/pull/10167)||2020-10-01 |2 | +| browser.search.with_ads |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |Records counts of SERP pages with adverts displayed. The key format is ‘’. |[1](https://github.com/mozilla-mobile/fenix/pull/10112)||2020-10-01 |2 | +| events.total_uri_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter of URIs visited by the user in the current session, including page reloads. This does not include background page requests and URIs from embedded pages or private browsing but may be incremented without user interaction by website scripts that programmatically redirect to a new location. |[1](https://github.com/mozilla-mobile/fenix/pull/1785), [2](https://github.com/mozilla-mobile/fenix/pull/8314)||2020-10-01 |2 | +| metrics.adjust_ad_group |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string containing the Adjust ad group ID from which the user installed Fenix. This will not send on the first session the user runs. If the install is organic, this will be empty. |[1](https://github.com/mozilla-mobile/fenix/pull/9253)||2020-10-01 |2 | +| metrics.adjust_campaign |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string containing the Adjust campaign ID from which the user installed Fenix. This will not send on the first session the user runs. If the install is organic, this will be empty. |[1](https://github.com/mozilla-mobile/fenix/pull/5579)||2020-10-01 |1 | +| metrics.adjust_creative |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string containing the Adjust creative ID from which the user installed Fenix. This will not send on the first session the user runs. If the install is organic, this will be empty. |[1](https://github.com/mozilla-mobile/fenix/pull/9253)||2020-10-01 |2 | +| metrics.adjust_network |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string containing the Adjust network ID from which the user installed Fenix. This will not send on the first session the user runs. If the install is organic, this will be empty. |[1](https://github.com/mozilla-mobile/fenix/pull/9253)||2020-10-01 |2 | +| metrics.default_browser |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Is Fenix the default browser? |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673)||2020-10-01 |2 | +| metrics.default_moz_browser |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |The name of the default browser on device if and only if it's a Mozilla owned product |[1](https://github.com/mozilla-mobile/fenix/pull/1953/), [2](https://github.com/mozilla-mobile/fenix/pull/5216)||2020-10-01 |1, 2 | +| metrics.has_open_tabs |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |A boolean that indicates if the user has any open NORMAL tabs. |[1](https://github.com/mozilla-mobile/fenix/pull/12024)||2020-10-01 |2 | +| metrics.has_recent_pwas |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |A boolean that indicates if the user has recently used PWAs. See recently_used_pwa_count for the actual count. |[1](https://github.com/mozilla-mobile/fenix/pull/11982#pullrequestreview-437963817)||2020-12-01 |2 | +| metrics.has_top_sites |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |A boolean that indicates if the user has top sites |[1](https://github.com/mozilla-mobile/fenix/pull/9556)||2020-10-01 |2 | +| metrics.mozilla_products |[string_list](https://mozilla.github.io/glean/book/user/metrics/string_list.html) |A list of all the Mozilla products installed on device. We currently scan for: Firefox, Firefox Beta, Firefox Aurora, Firefox Nightly, Firefox Fdroid, Firefox Lite, Reference Browser, Reference Browser Debug, Fenix, Focus, and Lockwise. |[1](https://github.com/mozilla-mobile/fenix/pull/1953/), [2](https://github.com/mozilla-mobile/fenix/pull/5216)||2020-10-01 |1, 2 | +| metrics.recently_used_pwa_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter that indicates how many PWAs a user has recently used. Threshold for "recency" set in HomeActivity#PWA_RECENTLY_USED_THRESHOLD. Currently we are not told by the OS when a PWA is removed by the user, so we use the "recently used" heuristic to judge how many PWAs are still active, as a proxy for "installed". This value will only be set if the user has at least *one* recently used PWA. If they have 0, this metric will not be sent, resulting in a null value during analysis on the server-side. To disambiguate between a failed `recently_used_pwa_count` metric and 0 recent PWAs, please see `has_recent_pwas`. |[1](https://github.com/mozilla-mobile/fenix/pull/11982#pullrequestreview-437963817)||2020-12-01 |2 | +| metrics.search_count |[labeled_counter](https://mozilla.github.io/glean/book/user/metrics/labeled_counters.html) |The labels for this counter are `.`. If the search engine is bundled with Fenix `search-engine-name` will be the name of the search engine. If it's a custom search engine (defined: https://github.com/mozilla-mobile/fenix/issues/1607) the value will be `custom`. `source` will be: `action`, `suggestion`, `widget` or `shortcut` (depending on the source from which the search started). Also added the `other` option for the source but it should never enter on this case. |[1](https://github.com/mozilla-mobile/fenix/pull/1677), [2](https://github.com/mozilla-mobile/fenix/pull/5216), [3](https://github.com/mozilla-mobile/fenix/pull/7310)||2020-10-01 |1, 2 | +| metrics.search_widget_installed |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |Whether or not the search widget is installed |[1](https://github.com/mozilla-mobile/fenix/pull/10958)||2020-10-01 |2 | +| metrics.tabs_open_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter that indicates how many NORMAL tabs a user has open. This value will only be set if the user has at least *one* open tab. If they have 0, this ping will not get sent, resulting in a null value. To disambiguate between a failed `tabs_open_count` ping and 0 open tabs, please see `has_open_tabs`. |[1](https://github.com/mozilla-mobile/fenix/pull/12024)||2020-10-01 |2 | +| metrics.toolbar_position |[string](https://mozilla.github.io/glean/book/user/metrics/string.html) |A string that indicates the new position of the toolbar TOP or BOTTOM |[1](https://github.com/mozilla-mobile/fenix/pull/6608)||2020-10-01 |2 | +| metrics.top_sites_count |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |A counter that indicates how many top sites a user has. This value will only be set if the user has at least *one* top site. If they have 0, this ping will not get sent, resulting in a null value. To disambiguate between a failed `top_sites_count` ping and 0 top sites, please see `has_top_sites`. |[1](https://github.com/mozilla-mobile/fenix/pull/9556)||2020-10-01 |2 | +| perf.awesomebar.bookmark_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a bookmarks awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 |1, 2 | +| perf.awesomebar.clipboard_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a clipboard awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 |1, 2 | +| perf.awesomebar.history_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a history awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 |1, 2 | +| perf.awesomebar.search_engine_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a search engine awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 |1, 2 | +| perf.awesomebar.session_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a session awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 |1, 2 | +| perf.awesomebar.shortcuts_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a shortcuts awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 |1, 2 | +| perf.awesomebar.synced_tabs_suggestions |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |Duration of a synced tabs awesomebar suggestion query. |[1](https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979)||2020-10-01 |1, 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: "" |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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 |[1](https://github.com/mozilla-mobile/fenix/pull/11446)||2020-10-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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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) |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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] |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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 |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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" |[1](https://github.com/mozilla-mobile/fenix/pull/11446)||2020-10-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) |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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" |[1](https://github.com/mozilla-mobile/fenix/pull/11211)||2020-10-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" |[1](https://github.com/mozilla-mobile/fenix/pull/1606), [2](https://github.com/mozilla-mobile/fenix/pull/5216)||2020-10-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" |[1](https://github.com/mozilla-mobile/fenix/pull/1606), [2](https://github.com/mozilla-mobile/fenix/pull/5216)||2020-10-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" |[1](https://github.com/mozilla-mobile/fenix/pull/1606), [2](https://github.com/mozilla-mobile/fenix/pull/5216)||2020-10-01 |1, 2 | +| storage.stats.app_bytes |[memory_distribution](https://mozilla.github.io/glean/book/user/metrics/memory_distribution.html) |The size of the app's APK and related files as installed: this is expected to be larger than download size. This is the output of [StorageStats.getAppBytes](https://developer.android.com/reference/android/app/usage/StorageStats#getAppBytes()) so see that for details. This value is only available on Android 8+. A similar value may be available on the Google Play dashboard: we can use this value to see if that value is reliable enough. |[1](https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732)||2021-02-01 |1, 2 | +| storage.stats.cache_bytes |[memory_distribution](https://mozilla.github.io/glean/book/user/metrics/memory_distribution.html) |The size of all cached data in the app. This is the output of [StorageStats.getCacheBytes](https://developer.android.com/reference/android/app/usage/StorageStats#getCacheBytes()) so see that for details. This value is only available on Android 8+. |[1](https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732)||2021-02-01 |1, 2 | +| storage.stats.data_dir_bytes |[memory_distribution](https://mozilla.github.io/glean/book/user/metrics/memory_distribution.html) |The size of all data minus `cache_bytes`. This is the output of [StorageStats.getDataBytes](https://developer.android.com/reference/android/app/usage/StorageStats#getDataBytes()) except we subtract the value of `cache_bytes` so the cache is not measured redundantly; see that method for details. This value is only available on Android 8+. |[1](https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732)||2021-02-01 |1, 2 | +| storage.stats.query_stats_duration |[timing_distribution](https://mozilla.github.io/glean/book/user/metrics/timing_distribution.html) |How long it took to query the device for the StorageStats that contain the file size information. The docs say it may be expensive so we want to ensure it's not too expensive. This value is only available on Android 8+. |[1](https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732)||2021-02-01 |1, 2 | ## startup-timeline @@ -341,10 +341,10 @@ The following metrics are added to the ping: | Name | Type | Description | Data reviews | Extras | Expiration | [Data Sensitivity](https://wiki.mozilla.org/Firefox/Data_Collection) | | --- | --- | --- | --- | --- | --- | --- | -| startup.timeline.clock_ticks_per_second |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |The number of clock tick time units that occur in one second on this particular device. This value is expected to be used in conjunction with the `framework_start` metric. |[1](https://github.com/mozilla-mobile/fenix/pull/9788#pullrequestreview-394228626)||2020-10-01 | | -| startup.timeline.framework_start |[timespan](https://mozilla.github.io/glean/book/user/metrics/timespan.html) |The duration the Android framework takes to start before letting us run code in `*Application.init`. This is calculated from `appInitTimestamp - processStartTimestamp`. `processStartTimestamp` is derived from the clock tick time unit, which is expected to be less granular than nanoseconds. Therefore, we convert and round our timestamps to clock ticks before computing the difference and convert back to nanoseconds to report. For debugging purposes, `clock_ticks_per_second`, which may vary between devices, is also reported as a metric |[1](https://github.com/mozilla-mobile/fenix/pull/9788#pullrequestreview-394228626)||2020-10-01 | | -| startup.timeline.framework_start_error |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |An error when attempting to record `framework_start` - the application init timestamp returned a negative value - which is likely indicative of a bug in the implementation. |[1](https://github.com/mozilla-mobile/fenix/pull/9788#pullrequestreview-394228626)||2020-10-01 | | -| startup.timeline.framework_start_read_error |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |An error when attempting to read stats from /proc pseudo-filesystem - privacy managers can block access to reading these files - the application will catch a file reading exception. |[1](https://github.com/mozilla-mobile/fenix/pull/10481)||2020-10-01 | | +| startup.timeline.clock_ticks_per_second |[counter](https://mozilla.github.io/glean/book/user/metrics/counter.html) |The number of clock tick time units that occur in one second on this particular device. This value is expected to be used in conjunction with the `framework_start` metric. |[1](https://github.com/mozilla-mobile/fenix/pull/9788#pullrequestreview-394228626)||2020-10-01 |1 | +| startup.timeline.framework_start |[timespan](https://mozilla.github.io/glean/book/user/metrics/timespan.html) |The duration the Android framework takes to start before letting us run code in `*Application.init`. This is calculated from `appInitTimestamp - processStartTimestamp`. `processStartTimestamp` is derived from the clock tick time unit, which is expected to be less granular than nanoseconds. Therefore, we convert and round our timestamps to clock ticks before computing the difference and convert back to nanoseconds to report. For debugging purposes, `clock_ticks_per_second`, which may vary between devices, is also reported as a metric |[1](https://github.com/mozilla-mobile/fenix/pull/9788#pullrequestreview-394228626)||2020-10-01 |1 | +| startup.timeline.framework_start_error |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |An error when attempting to record `framework_start` - the application init timestamp returned a negative value - which is likely indicative of a bug in the implementation. |[1](https://github.com/mozilla-mobile/fenix/pull/9788#pullrequestreview-394228626)||2020-10-01 |1 | +| startup.timeline.framework_start_read_error |[boolean](https://mozilla.github.io/glean/book/user/metrics/boolean.html) |An error when attempting to read stats from /proc pseudo-filesystem - privacy managers can block access to reading these files - the application will catch a file reading exception. |[1](https://github.com/mozilla-mobile/fenix/pull/10481)||2020-10-01 |1 | Data categories are [defined here](https://wiki.mozilla.org/Firefox/Data_Collection).