Bug 1954688 - [Downloads v2] Add missing telemetry probes for downloads. r=android-reviewers,calu,rsainani

Differential Revision: https://phabricator.services.mozilla.com/D242321
This commit is contained in:
iorgamgabriel
2025-03-24 08:02:12 +00:00
parent 4f99380366
commit 6d7a353dc9
6 changed files with 164 additions and 0 deletions

View File

@@ -13422,6 +13422,48 @@ sent_from_firefox:
metadata:
tags:
- Sharing
downloads:
screen_viewed:
type: event
description: |
A user opened the downloads screen.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1954688
data_reviews:
- https://phabricator.services.mozilla.com/D242321
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
deleted:
type: event
description: |
A user deleted a downloaded file.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1954688
data_reviews:
- https://phabricator.services.mozilla.com/D242321
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
filtered:
type: string
description: |
A user chose a filter for the downloads page.
The filter can be All, Image, Video, Document or Other.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1954688
data_reviews:
- https://phabricator.services.mozilla.com/D242321
data_sensitivity:
- interaction
notification_emails:
- android-probes@mozilla.com
expires: never
snackbar_clicked:
type: event
description: |

View File

@@ -36,6 +36,7 @@ import org.mozilla.fenix.compose.ComposeFragment
import org.mozilla.fenix.compose.snackbar.Snackbar
import org.mozilla.fenix.compose.snackbar.SnackbarState
import org.mozilla.fenix.downloads.dialog.DynamicDownloadDialog
import org.mozilla.fenix.downloads.listscreen.middleware.DownloadTelemetryMiddleware
import org.mozilla.fenix.downloads.listscreen.middleware.DownloadUIMapperMiddleware
import org.mozilla.fenix.downloads.listscreen.store.DownloadUIAction
import org.mozilla.fenix.downloads.listscreen.store.DownloadUIState
@@ -65,6 +66,7 @@ class DownloadFragment : ComposeFragment(), UserInteractionHandler, MenuProvider
fileSizeFormatter = requireComponents.core.fileSizeFormatter,
scope = viewModelScope,
),
DownloadTelemetryMiddleware(),
),
)
}
@@ -229,6 +231,7 @@ class DownloadFragment : ComposeFragment(), UserInteractionHandler, MenuProvider
context.let {
for (item in items) {
it.components.useCases.downloadUseCases.removeDownload(item.id)
downloadStore.dispatch(DownloadUIAction.FileItemDeletedSuccessfully)
}
}
}

View File

@@ -0,0 +1,42 @@
/* 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.downloads.listscreen.middleware
import mozilla.components.lib.state.Middleware
import mozilla.components.lib.state.MiddlewareContext
import mozilla.telemetry.glean.private.NoExtras
import org.mozilla.fenix.GleanMetrics.Downloads
import org.mozilla.fenix.downloads.listscreen.store.DownloadUIAction
import org.mozilla.fenix.downloads.listscreen.store.DownloadUIState
/**
* A [Middleware] for recording telemetry based on [DownloadUIState]s that are dispatch to the
* [DownloadUIStore].
*/
class DownloadTelemetryMiddleware : Middleware<DownloadUIState, DownloadUIAction> {
override fun invoke(
context: MiddlewareContext<DownloadUIState, DownloadUIAction>,
next: (DownloadUIAction) -> Unit,
action: DownloadUIAction,
) {
next(action)
when (action) {
is DownloadUIAction.Init -> {
Downloads.screenViewed.record(NoExtras())
}
is DownloadUIAction.FileItemDeletedSuccessfully -> {
Downloads.deleted.record(NoExtras())
}
is DownloadUIAction.ContentTypeSelected -> {
Downloads.filtered.set(action.contentTypeFilter.name)
}
else -> {}
}
}
}

View File

@@ -45,6 +45,11 @@ sealed interface DownloadUIAction : Action {
*/
data class UndoPendingDeletionSet(val itemIds: Set<String>) : DownloadUIAction
/**
* [DownloadUIAction] when a file item is deleted successfully.
*/
data object FileItemDeletedSuccessfully : DownloadUIAction
/**
* [DownloadUIAction] to update the list of [FileItem]s.
*/

View File

@@ -69,6 +69,8 @@ private fun downloadStateReducer(
is DownloadUIAction.ContentTypeSelected -> state.copy(userSelectedContentTypeFilter = action.contentTypeFilter)
is DownloadUIAction.FileItemDeletedSuccessfully -> state
DownloadUIAction.Init -> state
}
}

View File

@@ -0,0 +1,70 @@
package org.mozilla.fenix.downloads.listscreen.middleware
import mozilla.components.support.test.robolectric.testContext
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.GleanMetrics.Downloads
import org.mozilla.fenix.downloads.listscreen.store.DownloadUIAction
import org.mozilla.fenix.downloads.listscreen.store.DownloadUIState
import org.mozilla.fenix.downloads.listscreen.store.DownloadUIStore
import org.mozilla.fenix.downloads.listscreen.store.FileItem
import org.mozilla.fenix.helpers.FenixGleanTestRule
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class DownloadTelemetryMiddlewareTest {
@get:Rule
val gleanTestRule = FenixGleanTestRule(testContext)
@Test
fun `WHEN the user enters in DownloadScreen THEN record screen viewed telemetry`() {
assertNull(Downloads.screenViewed.testGetValue())
createStore()
assertNotNull(Downloads.screenViewed.testGetValue())
val snapshot = Downloads.screenViewed.testGetValue()!!
assertEquals(1, snapshot.size)
assertEquals("screen_viewed", snapshot.single().name)
}
@Test
fun `WHEN the user successfully deletes a file item THEN record deleted telemetry`() {
val store = createStore()
assertNull(Downloads.deleted.testGetValue())
store.dispatch(DownloadUIAction.FileItemDeletedSuccessfully)
assertNotNull(Downloads.deleted.testGetValue())
val snapshot = Downloads.deleted.testGetValue()!!
assertEquals(1, snapshot.size)
assertEquals("deleted", snapshot.single().name)
}
@Test
fun `WHEN the user select a different content type THEN record filtered telemetry`() {
val store = createStore()
assertNull(Downloads.filtered.testGetValue())
store.dispatch(DownloadUIAction.ContentTypeSelected(FileItem.ContentTypeFilter.Other))
assertNotNull(Downloads.filtered.testGetValue())
val snapshot = Downloads.filtered.testGetValue()!!
assertEquals(FileItem.ContentTypeFilter.Other.name, snapshot)
}
private fun createStore(
downloadUIState: DownloadUIState = DownloadUIState.INITIAL,
) = DownloadUIStore(
initialState = downloadUIState,
middleware = listOf(
DownloadTelemetryMiddleware(),
),
)
}