diff --git a/app/src/main/java/org/mozilla/fenix/components/Core.kt b/app/src/main/java/org/mozilla/fenix/components/Core.kt index b0d482f56..8ef188e3f 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Core.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Core.kt @@ -230,7 +230,7 @@ class Core( RecentlyClosedMiddleware(recentlyClosedTabsStorage, RECENTLY_CLOSED_MAX), DownloadMiddleware(context, DownloadService::class.java), ReaderViewMiddleware(), - TelemetryMiddleware(context.settings()), + TelemetryMiddleware(context.settings(), metrics), ThumbnailsMiddleware(thumbnailStorage), UndoMiddleware(context.getUndoDelay()), RegionMiddleware(context, locationService), 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 2c9545acb..a31dfd194 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 @@ -26,5 +26,10 @@ sealed class Event { * Event recording the first time Firefox has been resumed in a 24 hour period. */ object FirstAppOpenForDay : GrowthData("41hl22") + + /** + * Event recording the first time a URI is loaded in Firefox in a 24 hour period. + */ + object FirstUriLoadForDay : GrowthData("ja86ek") } } diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricsStorage.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricsStorage.kt index 9f8e00b20..e0777df7b 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricsStorage.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricsStorage.kt @@ -46,6 +46,9 @@ internal class DefaultMetricsStorage( Event.GrowthData.FirstAppOpenForDay -> { settings.resumeGrowthLastSent.hasBeenMoreThanDaySince() } + Event.GrowthData.FirstUriLoadForDay -> { + settings.uriLoadGrowthLastSent.hasBeenMoreThanDaySince() + } } } @@ -57,6 +60,9 @@ internal class DefaultMetricsStorage( Event.GrowthData.FirstAppOpenForDay -> { settings.resumeGrowthLastSent = System.currentTimeMillis() } + Event.GrowthData.FirstUriLoadForDay -> { + settings.uriLoadGrowthLastSent = System.currentTimeMillis() + } } } diff --git a/app/src/main/java/org/mozilla/fenix/telemetry/TelemetryMiddleware.kt b/app/src/main/java/org/mozilla/fenix/telemetry/TelemetryMiddleware.kt index 6863fb233..c53ca405f 100644 --- a/app/src/main/java/org/mozilla/fenix/telemetry/TelemetryMiddleware.kt +++ b/app/src/main/java/org/mozilla/fenix/telemetry/TelemetryMiddleware.kt @@ -15,13 +15,14 @@ import mozilla.components.browser.state.selector.normalTabs import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.EngineState import mozilla.components.browser.state.state.SessionState -import mozilla.components.feature.search.telemetry.ads.AdsTelemetry import mozilla.components.lib.state.Middleware import mozilla.components.lib.state.MiddlewareContext import mozilla.components.support.base.android.Clock import mozilla.components.support.base.log.logger.Logger import org.mozilla.fenix.GleanMetrics.Events import org.mozilla.fenix.GleanMetrics.Metrics +import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.GleanMetrics.EngineTab as EngineMetrics @@ -29,10 +30,11 @@ import org.mozilla.fenix.GleanMetrics.EngineTab as EngineMetrics * [Middleware] to record telemetry in response to [BrowserAction]s. * * @property settings reference to the application [Settings]. - * @property adsTelemetry reference to [AdsTelemetry] use to record search telemetry. + * @property metrics [MetricController] to pass events that have been mapped from actions */ class TelemetryMiddleware( private val settings: Settings, + private val metrics: MetricController, ) : Middleware { private val logger = Logger("TelemetryMiddleware") @@ -58,6 +60,9 @@ class TelemetryMiddleware( val tab = context.state.findTabOrCustomTab(action.tabId) onEngineSessionKilled(context.state, tab) } + is EngineAction.LoadUrlAction -> { + metrics.track(Event.GrowthData.FirstUriLoadForDay) + } else -> { // no-op } 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 a40ac535c..fd7b0a4c4 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -1423,4 +1423,9 @@ class Settings(private val appContext: Context) : PreferencesHolder { key = appContext.getPreferenceKey(R.string.pref_key_growth_resume_last_sent), default = 0, ) + + var uriLoadGrowthLastSent by longPreference( + key = appContext.getPreferenceKey(R.string.pref_key_growth_uri_load_last_sent), + default = 0, + ) } diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index 37d6cee8a..cff61b0e5 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -311,4 +311,5 @@ pref_key_growth_set_as_default pref_key_growth_last_resumed + pref_key_growth_uri_load_last_sent diff --git a/app/src/test/java/org/mozilla/fenix/components/metrics/DefaultMetricsStorageTest.kt b/app/src/test/java/org/mozilla/fenix/components/metrics/DefaultMetricsStorageTest.kt index 82f54adce..cfcb4b678 100644 --- a/app/src/test/java/org/mozilla/fenix/components/metrics/DefaultMetricsStorageTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/metrics/DefaultMetricsStorageTest.kt @@ -116,4 +116,35 @@ class DefaultMetricsStorageTest { assertTrue(updateSlot.captured > 0) } + + @Test + fun `GIVEN that it has been less than 24 hours since uri load sent WHEN checked for sending THEN will not be sent`() = runTest(dispatcher) { + val currentTime = System.currentTimeMillis() + every { settings.uriLoadGrowthLastSent } returns currentTime + + val result = storage.shouldTrack(Event.GrowthData.FirstUriLoadForDay) + + assertFalse(result) + } + + @Test + fun `GIVEN that it has been more than 24 hours since uri load sent WHEN checked for sending THEN will be sent`() = runTest(dispatcher) { + val currentTime = System.currentTimeMillis() + every { settings.uriLoadGrowthLastSent } returns currentTime - 1000 * 60 * 60 * 24 * 2 + + val result = storage.shouldTrack(Event.GrowthData.FirstUriLoadForDay) + + assertTrue(result) + } + + @Test + fun `WHEN uri load updated THEN settings updated accordingly`() = runTest(dispatcher) { + val updateSlot = slot() + every { settings.uriLoadGrowthLastSent } returns 0 + every { settings.uriLoadGrowthLastSent = capture(updateSlot) } returns Unit + + storage.updateSentState(Event.GrowthData.FirstUriLoadForDay) + + assertTrue(updateSlot.captured > 0) + } } diff --git a/app/src/test/java/org/mozilla/fenix/telemetry/TelemetryMiddlewareTest.kt b/app/src/test/java/org/mozilla/fenix/telemetry/TelemetryMiddlewareTest.kt index f24af884f..77cf0b383 100644 --- a/app/src/test/java/org/mozilla/fenix/telemetry/TelemetryMiddlewareTest.kt +++ b/app/src/test/java/org/mozilla/fenix/telemetry/TelemetryMiddlewareTest.kt @@ -6,6 +6,7 @@ package org.mozilla.fenix.telemetry import androidx.test.core.app.ApplicationProvider import io.mockk.mockk +import io.mockk.verify import mozilla.components.browser.state.action.ContentAction import mozilla.components.browser.state.action.EngineAction import mozilla.components.browser.state.action.TabListAction @@ -32,6 +33,8 @@ import org.junit.Test import org.junit.runner.RunWith import org.mozilla.fenix.GleanMetrics.Events import org.mozilla.fenix.GleanMetrics.Metrics +import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.GleanMetrics.EngineTab as EngineMetrics @@ -50,13 +53,14 @@ class TelemetryMiddlewareTest { val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext()) private val clock = FakeClock() + private val metrics: MetricController = mockk() @Before fun setUp() { Clock.delegate = clock settings = Settings(testContext) - telemetryMiddleware = TelemetryMiddleware(settings) + telemetryMiddleware = TelemetryMiddleware(settings, metrics) store = BrowserStore( middleware = listOf(telemetryMiddleware) + EngineMiddleware.create(engine = mockk()), initialState = BrowserState(), @@ -348,6 +352,13 @@ class TelemetryMiddlewareTest { assertNull(EngineMetrics.killForegroundAge.testGetValue()) assertEquals(600_000_000, EngineMetrics.killBackgroundAge.testGetValue()!!.sum) } + + @Test + fun `WHEN uri loaded to engine THEN matching event is sent to metrics`() { + store.dispatch(EngineAction.LoadUrlAction("", "")).joinBlocking() + + verify { metrics.track(Event.GrowthData.FirstUriLoadForDay) } + } } internal class FakeClock : Clock.Delegate {