For #21009 - New Recently closed tabs telemetry

This adds a new `recently_closed_tabs` category with then events for all user
interactions on the screen.

The already existent `events.recently_closed_tabs_opened` is still kept for a
bit more time to still have this data available while the new telemetry ride
the trains but can later be removed in favor of this newly added events.
upstream-sync
Mugurell 3 years ago committed by mergify[bot]
parent e73deb23ac
commit 0be470a104

@ -358,6 +358,7 @@ events:
description: |
An event that indicates that the user
has accessed recently closed tabs list.
Deprecated in favor of "recently_closed_tabs.opened"
bugs:
- https://github.com/mozilla-mobile/fenix/issues/15366
- https://github.com/mozilla-mobile/fenix/issues/19923
@ -3124,6 +3125,165 @@ history:
- android-probes@mozilla.com
expires: "2022-11-01"
recently_closed_tabs:
opened:
type: event
description: |
User opened the "Recently closed tabs" screen.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21009
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22588#issuecomment-1024352995
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-01-31"
closed:
type: event
description: |
User closed the "Recently closed tabs" screen.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21009
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22588#issuecomment-1024352995
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-01-31"
show_full_history:
type: event
description: |
User tapped "Show full history" to see all history.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21009
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22588#issuecomment-1024352995
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-01-31"
open_tab:
type: event
description: |
User tapped on a tab item to be opened.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21009
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22588#issuecomment-1024352995
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-01-31"
delete_tab:
type: event
description: |
User tapped the delete button of a tab item.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21009
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22588#issuecomment-1024352995
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-01-31"
menu_close:
type: event
description: |
User tapped the close button - "X" to return to the previous screen.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21009
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22588#issuecomment-1024352995
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-01-31"
menu_share:
type: event
description: |
User tapped the share menu option for multi selected tabs.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21009
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22588#issuecomment-1024352995
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-01-31"
menu_delete:
type: event
description: |
User tapped the delete menu option for multi selected tabs.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21009
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22588#issuecomment-1024352995
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-01-31"
menu_open_in_normal_tab:
type: event
description: |
User tapped the "Open in new tab" menu option for multi selected tabs.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21009
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22588#issuecomment-1024352995
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-01-31"
menu_open_in_private_tab:
type: event
description: |
User tapped the "Open in private tab" menu option for multi selected tabs.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21009
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22588#issuecomment-1024352995
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-01-31"
enter_multiselect:
type: event
description: |
User tapped on a tab item to enter multi select mode.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21009
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22588#issuecomment-1024352995
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-01-31"
exit_multiselect:
type: event
description: |
User pressed back or tapped the last selected tab item to exit
multiselect.
bugs:
- https://github.com/mozilla-mobile/fenix/issues/21009
data_reviews:
- https://github.com/mozilla-mobile/fenix/pull/22588#issuecomment-1024352995
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: "2023-01-31"
reader_mode:
available:
type: event

@ -90,6 +90,18 @@ sealed class Event {
object HistorySearchTermGroupOpenTab : Event()
object HistorySearchTermGroupRemoveTab : Event()
object HistorySearchTermGroupRemoveAll : Event()
object RecentlyClosedTabsOpened : Event()
object RecentlyClosedTabsClosed : Event()
object RecentlyClosedTabsShowFullHistory : Event()
object RecentlyClosedTabsOpenTab : Event()
object RecentlyClosedTabsDeleteTab : Event()
object RecentlyClosedTabsMenuClose : Event()
object RecentlyClosedTabsMenuShare : Event()
object RecentlyClosedTabsMenuDelete : Event()
object RecentlyClosedTabsMenuOpenInNormalTab : Event()
object RecentlyClosedTabsMenuOpenInPrivateTab : Event()
object RecentlyClosedTabsEnterMultiselect : Event()
object RecentlyClosedTabsExitMultiselect : Event()
object ReaderModeAvailable : Event()
object ReaderModeOpened : Event()
object ReaderModeClosed : Event()
@ -235,7 +247,7 @@ sealed class Event {
object SyncedTabOpened : Event()
object RecentlyClosedTabsOpened : Event()
object RecentlyClosedTabsOpenedOld : Event()
object HaveOpenTabs : Event()
object HaveNoOpenTabs : Event()

@ -42,6 +42,7 @@ import org.mozilla.fenix.GleanMetrics.ReaderMode
import org.mozilla.fenix.GleanMetrics.RecentBookmarks
import org.mozilla.fenix.GleanMetrics.RecentSearches
import org.mozilla.fenix.GleanMetrics.RecentTabs
import org.mozilla.fenix.GleanMetrics.RecentlyClosedTabs
import org.mozilla.fenix.GleanMetrics.SearchShortcuts
import org.mozilla.fenix.GleanMetrics.SearchTerms
import org.mozilla.fenix.GleanMetrics.SearchWidget
@ -325,6 +326,42 @@ private val Event.wrapper: EventWrapper<*>?
is Event.HistorySearchTermGroupRemoveAll -> EventWrapper<NoExtraKeys>(
{ History.searchTermGroupRemoveAll.record(it) }
)
is Event.RecentlyClosedTabsOpened -> EventWrapper<NoExtraKeys>(
{ RecentlyClosedTabs.opened.record(it) }
)
is Event.RecentlyClosedTabsClosed -> EventWrapper<NoExtraKeys>(
{ RecentlyClosedTabs.closed.record(it) }
)
is Event.RecentlyClosedTabsShowFullHistory -> EventWrapper<NoExtraKeys>(
{ RecentlyClosedTabs.showFullHistory.record(it) }
)
is Event.RecentlyClosedTabsOpenTab -> EventWrapper<NoExtraKeys>(
{ RecentlyClosedTabs.openTab.record(it) }
)
is Event.RecentlyClosedTabsDeleteTab -> EventWrapper<NoExtraKeys>(
{ RecentlyClosedTabs.deleteTab.record(it) }
)
is Event.RecentlyClosedTabsMenuClose -> EventWrapper<NoExtraKeys>(
{ RecentlyClosedTabs.menuClose.record(it) }
)
is Event.RecentlyClosedTabsMenuShare -> EventWrapper<NoExtraKeys>(
{ RecentlyClosedTabs.menuShare.record(it) }
)
is Event.RecentlyClosedTabsMenuDelete -> EventWrapper<NoExtraKeys>(
{ RecentlyClosedTabs.menuDelete.record(it) }
)
is Event.RecentlyClosedTabsMenuOpenInNormalTab -> EventWrapper<NoExtraKeys>(
{ RecentlyClosedTabs.menuOpenInNormalTab.record(it) }
)
is Event.RecentlyClosedTabsMenuOpenInPrivateTab -> EventWrapper<NoExtraKeys>(
{ RecentlyClosedTabs.menuOpenInPrivateTab.record(it) }
)
is Event.RecentlyClosedTabsEnterMultiselect -> EventWrapper<NoExtraKeys>(
{ RecentlyClosedTabs.enterMultiselect.record(it) }
)
is Event.RecentlyClosedTabsExitMultiselect -> EventWrapper<NoExtraKeys>(
{ RecentlyClosedTabs.exitMultiselect.record(it) }
)
is Event.CollectionRenamed -> EventWrapper<NoExtraKeys>(
{ Collections.renamed.record(it) }
)
@ -691,7 +728,7 @@ private val Event.wrapper: EventWrapper<*>?
{ Events.syncedTabOpened.record(it) }
)
is Event.RecentlyClosedTabsOpened -> EventWrapper<NoExtraKeys>(
is Event.RecentlyClosedTabsOpenedOld -> EventWrapper<NoExtraKeys>(
{ Events.recentlyClosedTabsOpened.record(it) }
)

@ -101,6 +101,6 @@ class DefaultHistoryController(
HistoryFragmentDirections.actionGlobalRecentlyClosed(),
NavOptions.Builder().setPopUpTo(R.id.recentlyClosedFragment, true).build()
)
metrics.track(Event.RecentlyClosedTabsOpened)
metrics.track(Event.RecentlyClosedTabsOpenedOld)
}
}

@ -15,6 +15,8 @@ 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.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController
@Suppress("TooManyFunctions")
interface RecentlyClosedController {
@ -37,6 +39,7 @@ class DefaultRecentlyClosedController(
private val recentlyClosedStore: RecentlyClosedFragmentStore,
private val tabsUseCases: TabsUseCases,
private val activity: HomeActivity,
private val metrics: MetricController,
private val openToBrowser: (item: RecoverableTab, mode: BrowsingMode?) -> Unit
) : RecentlyClosedController {
override fun handleOpen(tab: RecoverableTab, mode: BrowsingMode?) {
@ -44,28 +47,44 @@ class DefaultRecentlyClosedController(
}
override fun handleOpen(tabs: Set<RecoverableTab>, mode: BrowsingMode?) {
if (mode == BrowsingMode.Normal) {
metrics.track(Event.RecentlyClosedTabsMenuOpenInNormalTab)
} else if (mode == BrowsingMode.Private) {
metrics.track(Event.RecentlyClosedTabsMenuOpenInPrivateTab)
}
recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.DeselectAll)
tabs.forEach { tab -> handleOpen(tab, mode) }
}
override fun handleSelect(tab: RecoverableTab) {
if (recentlyClosedStore.state.selectedTabs.isEmpty()) {
metrics.track(Event.RecentlyClosedTabsEnterMultiselect)
}
recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.Select(tab))
}
override fun handleDeselect(tab: RecoverableTab) {
if (recentlyClosedStore.state.selectedTabs.size == 1) {
metrics.track(Event.RecentlyClosedTabsExitMultiselect)
}
recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.Deselect(tab))
}
override fun handleDelete(tab: RecoverableTab) {
metrics.track(Event.RecentlyClosedTabsDeleteTab)
browserStore.dispatch(RecentlyClosedAction.RemoveClosedTabAction(tab))
}
override fun handleDelete(tabs: Set<RecoverableTab>) {
metrics.track(Event.RecentlyClosedTabsMenuDelete)
recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.DeselectAll)
tabs.forEach { tab -> handleDelete(tab) }
tabs.forEach { tab ->
browserStore.dispatch(RecentlyClosedAction.RemoveClosedTabAction(tab))
}
}
override fun handleNavigateToHistory() {
metrics.track(Event.RecentlyClosedTabsShowFullHistory)
navController.navigate(
RecentlyClosedFragmentDirections.actionGlobalHistoryFragment(),
NavOptions.Builder().setPopUpTo(R.id.historyFragment, true).build()
@ -73,6 +92,7 @@ class DefaultRecentlyClosedController(
}
override fun handleShare(tabs: Set<RecoverableTab>) {
metrics.track(Event.RecentlyClosedTabsMenuShare)
val shareData = tabs.map { ShareData(url = it.url, title = it.title) }
navController.navigate(
RecentlyClosedFragmentDirections.actionGlobalShareFragment(
@ -82,6 +102,8 @@ class DefaultRecentlyClosedController(
}
override fun handleRestore(item: RecoverableTab) {
metrics.track(Event.RecentlyClosedTabsOpenTab)
tabsUseCases.restore(item)
browserStore.dispatch(
@ -95,9 +117,11 @@ class DefaultRecentlyClosedController(
override fun handleBackPressed(): Boolean {
return if (recentlyClosedStore.state.selectedTabs.isNotEmpty()) {
metrics.track(Event.RecentlyClosedTabsExitMultiselect)
recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.DeselectAll)
true
} else {
metrics.track(Event.RecentlyClosedTabsClosed)
false
}
}

@ -25,6 +25,8 @@ 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.components.metrics.MetricController
import org.mozilla.fenix.databinding.FragmentRecentlyClosedTabsBinding
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.setTextColor
@ -41,6 +43,8 @@ class RecentlyClosedFragment : LibraryPageFragment<RecoverableTab>(), UserIntera
private lateinit var recentlyClosedInteractor: RecentlyClosedFragmentInteractor
private lateinit var recentlyClosedController: RecentlyClosedController
private lateinit var metrics: MetricController
override fun onResume() {
super.onResume()
showToolbar(getString(R.string.library_recently_closed_tabs))
@ -64,6 +68,7 @@ class RecentlyClosedFragment : LibraryPageFragment<RecoverableTab>(), UserIntera
return when (item.itemId) {
R.id.close_history -> {
close()
metrics.track(Event.RecentlyClosedTabsMenuClose)
true
}
R.id.share_history_multi_select -> {
@ -89,6 +94,9 @@ class RecentlyClosedFragment : LibraryPageFragment<RecoverableTab>(), UserIntera
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
metrics = requireComponents.analytics.metrics.also {
it.track(Event.RecentlyClosedTabsOpened)
}
}
override fun onCreateView(
@ -111,6 +119,7 @@ class RecentlyClosedFragment : LibraryPageFragment<RecoverableTab>(), UserIntera
recentlyClosedStore = recentlyClosedFragmentStore,
activity = activity as HomeActivity,
tabsUseCases = requireComponents.useCases.tabsUseCases,
metrics = metrics,
openToBrowser = ::openItem
)
recentlyClosedInteractor = RecentlyClosedFragmentInteractor(recentlyClosedController)

@ -142,7 +142,7 @@ class DefaultNavigationInteractor(
navController.navigate(
TabsTrayFragmentDirections.actionGlobalRecentlyClosed()
)
metrics.track(Event.RecentlyClosedTabsOpened)
metrics.track(Event.RecentlyClosedTabsOpenedOld)
}
override fun onShareTabs(tabs: Collection<TabSessionState>) {

@ -7,10 +7,12 @@ package org.mozilla.fenix.library.recentlyclosed
import androidx.navigation.NavController
import androidx.navigation.NavOptions
import io.mockk.Runs
import io.mockk.clearMocks
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.verify
import io.mockk.verifyAll
import kotlinx.coroutines.test.TestCoroutineDispatcher
import mozilla.components.browser.state.action.RecentlyClosedAction
import mozilla.components.browser.state.state.recover.RecoverableTab
@ -25,6 +27,8 @@ import org.junit.runner.RunWith
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.ext.directionsEq
import org.mozilla.fenix.ext.optionsEq
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@ -37,6 +41,7 @@ class DefaultRecentlyClosedControllerTest {
private val browserStore: BrowserStore = mockk(relaxed = true)
private val recentlyClosedStore: RecentlyClosedFragmentStore = mockk(relaxed = true)
private val tabsUseCases: TabsUseCases = mockk(relaxed = true)
private val metrics: MetricController = mockk(relaxed = true)
@Before
fun setUp() {
@ -97,6 +102,8 @@ class DefaultRecentlyClosedControllerTest {
assertEquals(tabs[1], actualTabs[1])
assertEquals(BrowsingMode.Normal, actualBrowsingModes[0])
assertEquals(BrowsingMode.Normal, actualBrowsingModes[1])
verifyAll { metrics.track(Event.RecentlyClosedTabsMenuOpenInNormalTab) }
clearMocks(metrics)
actualTabs.clear()
actualBrowsingModes.clear()
@ -108,24 +115,51 @@ class DefaultRecentlyClosedControllerTest {
assertEquals(tabs[1], actualTabs[1])
assertEquals(BrowsingMode.Private, actualBrowsingModes[0])
assertEquals(BrowsingMode.Private, actualBrowsingModes[1])
verifyAll { metrics.track(Event.RecentlyClosedTabsMenuOpenInPrivateTab) }
}
@Test
fun `handle select tab`() {
fun `handle selecting first tab`() {
val selectedTab = createFakeTab()
every { recentlyClosedStore.state.selectedTabs } returns emptySet()
createController().handleSelect(selectedTab)
verify { recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.Select(selectedTab)) }
verify { metrics.track(Event.RecentlyClosedTabsEnterMultiselect) }
}
@Test
fun `handle deselect tab`() {
fun `handle selecting a successive tab`() {
val selectedTab = createFakeTab()
every { recentlyClosedStore.state.selectedTabs } returns setOf(mockk())
createController().handleSelect(selectedTab)
verify { recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.Select(selectedTab)) }
verify(exactly = 0) { metrics.track(Event.RecentlyClosedTabsEnterMultiselect) }
}
@Test
fun `handle deselect last tab`() {
val deselectedTab = createFakeTab()
every { recentlyClosedStore.state.selectedTabs } returns setOf(deselectedTab)
createController().handleDeselect(deselectedTab)
verify { recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.Deselect(deselectedTab)) }
verify { metrics.track(Event.RecentlyClosedTabsExitMultiselect) }
}
@Test
fun `handle deselect a tab from others still selected`() {
val deselectedTab = createFakeTab()
every { recentlyClosedStore.state.selectedTabs } returns setOf(deselectedTab, mockk())
createController().handleDeselect(deselectedTab)
verify { recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.Deselect(deselectedTab)) }
verify(exactly = 0) { metrics.track(Event.RecentlyClosedTabsExitMultiselect) }
}
@Test
@ -137,6 +171,7 @@ class DefaultRecentlyClosedControllerTest {
verify {
browserStore.dispatch(RecentlyClosedAction.RemoveClosedTabAction(item))
}
verify { metrics.track(Event.RecentlyClosedTabsDeleteTab) }
}
@Test
@ -149,6 +184,7 @@ class DefaultRecentlyClosedControllerTest {
browserStore.dispatch(RecentlyClosedAction.RemoveClosedTabAction(tabs[0]))
browserStore.dispatch(RecentlyClosedAction.RemoveClosedTabAction(tabs[1]))
}
verify { metrics.track(Event.RecentlyClosedTabsMenuDelete) }
}
@Test
@ -163,6 +199,7 @@ class DefaultRecentlyClosedControllerTest {
optionsEq(NavOptions.Builder().setPopUpTo(R.id.historyFragment, true).build())
)
}
verify { metrics.track(Event.RecentlyClosedTabsShowFullHistory) }
}
@Test
@ -180,6 +217,7 @@ class DefaultRecentlyClosedControllerTest {
directionsEq(RecentlyClosedFragmentDirections.actionGlobalShareFragment(data))
)
}
verify { metrics.track(Event.RecentlyClosedTabsMenuShare) }
}
@Test
@ -191,6 +229,7 @@ class DefaultRecentlyClosedControllerTest {
dispatcher.advanceUntilIdle()
verify { tabsUseCases.restore.invoke(item, true) }
verify { metrics.track(Event.RecentlyClosedTabsOpenTab) }
}
@Test
@ -200,6 +239,17 @@ class DefaultRecentlyClosedControllerTest {
createController().handleBackPressed()
verify { recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.DeselectAll) }
verifyAll { metrics.track(Event.RecentlyClosedTabsExitMultiselect) }
}
@Test
fun `report closing the fragment when back is pressed`() {
every { recentlyClosedStore.state.selectedTabs } returns emptySet()
createController().handleBackPressed()
verify(exactly = 0) { recentlyClosedStore.dispatch(RecentlyClosedFragmentAction.DeselectAll) }
verifyAll { metrics.track(Event.RecentlyClosedTabsClosed) }
}
private fun createController(
@ -211,6 +261,7 @@ class DefaultRecentlyClosedControllerTest {
recentlyClosedStore,
tabsUseCases,
activity,
metrics,
openToBrowser
)
}

Loading…
Cancel
Save