2
0
mirror of https://github.com/fork-maintainers/iceraven-browser synced 2024-11-15 18:12:54 +00:00

Bug 1880476 — Move nimbus from components.analytics to components.nimbus

This commit is contained in:
James Hugman 2024-01-29 13:03:54 +00:00 committed by mergify[bot]
parent fc0b206d1f
commit 64b636d2a9
17 changed files with 114 additions and 50 deletions

View File

@ -9,11 +9,8 @@ import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.TestHelper.appContext
object Experimentation {
val experiments =
appContext.components.analytics.experiments
fun withHelper(block: NimbusMessagingHelperInterface.() -> Unit) {
val helper = experiments.createMessageHelper()
val helper = appContext.components.nimbus.createJexlHelper()
block(helper)
}
}

View File

@ -20,7 +20,6 @@ import org.junit.Test
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.helpers.HomeActivityIntentTestRule
import org.mozilla.fenix.helpers.TestHelper
import org.mozilla.fenix.messaging.CustomAttributeProvider
/**
* This test is to test the integrity of messages hardcoded in the FML.
@ -35,7 +34,7 @@ class NimbusMessagingMessageTest {
private lateinit var context: Context
private val storage
get() = context.components.analytics.messagingStorage
get() = context.components.nimbus.messagingStorage
@get:Rule
val activityTestRule =
@ -73,10 +72,7 @@ class NimbusMessagingMessageTest {
*/
@Test
fun testAllMessageTriggers() = runTest {
val nimbus = context.components.analytics.experiments
val helper = nimbus.createMessageHelper(
CustomAttributeProvider.getCustomAttributes(context),
)
val helper = context.components.nimbus.createJexlHelper()
val messages = storage.getMessages()
messages.forEach { message ->
storage.isMessageEligible(message, helper)
@ -84,6 +80,7 @@ class NimbusMessagingMessageTest {
fail("${message.id} has a problem with its JEXL trigger: ${storage.malFormedMap.keys}")
}
}
helper.destroy()
}
private fun checkIsLocalized(string: String) {

View File

@ -38,7 +38,7 @@ class NimbusMessagingTriggerTest {
@Before
fun setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
nimbus = TestHelper.appContext.components.analytics.experiments
nimbus = TestHelper.appContext.components.nimbus.sdk
feature = FxNimbusMessaging.features.messaging.value()
}

View File

@ -433,7 +433,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
fun queueNimbusFetchInForeground() {
queue.runIfReadyOrQueue {
GlobalScope.launch(Dispatchers.IO) {
components.analytics.experiments.maybeFetchExperiments(
components.nimbus.sdk.maybeFetchExperiments(
context = this@FenixApplication,
)
}
@ -502,7 +502,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
beginSetupMegazord()
// This lazily constructs the Nimbus object…
val nimbus = components.analytics.experiments
val nimbus = components.nimbus.sdk
// … which we then can populate the feature configuration.
FxNimbus.initialize { nimbus }
}

View File

@ -225,7 +225,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
val startTimeProfiler = components.core.engine.profiler?.getProfilerTime()
// Setup nimbus-cli tooling. This is a NOOP when launching normally.
components.analytics.experiments.initializeTooling(applicationContext, intent)
components.nimbus.sdk.initializeTooling(applicationContext, intent)
components.strictMode.attachListenerToDisablePenaltyDeath(supportFragmentManager)
MarkersFragmentLifecycleCallbacks.register(supportFragmentManager, components.core.engine)
@ -354,7 +354,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
?.also {
Events.appOpened.record(Events.AppOpenedExtra(it))
// This will record an event in Nimbus' internal event store. Used for behavioral targeting
components.analytics.experiments.recordEvent("app_opened")
components.nimbus.events.recordEvent("app_opened")
if (safeIntent.action.equals(ACTION_OPEN_PRIVATE_TAB) && it == APP_ICON) {
AppIcon.newPrivateTabTapped.record(NoExtras())
@ -1221,7 +1221,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
}
private suspend fun showFullscreenMessageIfNeeded(context: Context) {
val messagingStorage = context.components.analytics.messagingStorage
val messagingStorage = context.components.nimbus.messagingStorage
val messages = messagingStorage.getMessages()
val nextMessage =
messagingStorage.getNextMessage(FenixMessageSurfaceId.SURVEY, messages)

View File

@ -14,10 +14,6 @@ import mozilla.components.lib.crash.sentry.SentryService
import mozilla.components.lib.crash.service.CrashReporterService
import mozilla.components.lib.crash.service.GleanCrashReporterService
import mozilla.components.lib.crash.service.MozillaSocorroService
import mozilla.components.service.nimbus.NimbusApi
import mozilla.components.service.nimbus.messaging.FxNimbusMessaging
import mozilla.components.service.nimbus.messaging.NimbusMessagingStorage
import mozilla.components.service.nimbus.messaging.OnDiskMessageMetadataStorage
import mozilla.components.support.ktx.android.content.isMainProcess
import mozilla.components.support.utils.BrowsersCache
import mozilla.components.support.utils.RunWhenReadyQueue
@ -33,10 +29,8 @@ import org.mozilla.fenix.components.metrics.InstallReferrerMetricsService
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.components.metrics.MetricsStorage
import org.mozilla.fenix.crashes.CrashFactCollector
import org.mozilla.fenix.experiments.createNimbus
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.messaging.CustomAttributeProvider
import org.mozilla.fenix.perf.lazyMonitored
import org.mozilla.geckoview.BuildConfig.MOZ_APP_BUILDID
import org.mozilla.geckoview.BuildConfig.MOZ_APP_VENDOR
@ -159,20 +153,6 @@ class Analytics(
context.settings(),
)
}
val experiments: NimbusApi by lazyMonitored {
createNimbus(context, BuildConfig.NIMBUS_ENDPOINT)
}
val messagingStorage by lazyMonitored {
NimbusMessagingStorage(
context = context,
metadataStorage = OnDiskMessageMetadataStorage(context),
nimbus = experiments,
messagingFeature = FxNimbusMessaging.features.messaging,
attributeProvider = CustomAttributeProvider,
)
}
}
private fun isSentryEnabled() = !BuildConfig.SENTRY_TOKEN.isNullOrEmpty()

View File

@ -230,7 +230,7 @@ internal class TelemetryAccountObserver(
// User signed-in into an existing FxA account.
AuthType.Signin -> {
SyncAuth.signIn.record(NoExtras())
context.components.analytics.experiments.recordEvent("sync_auth.sign_in")
context.components.nimbus.events.recordEvent("sync_auth.sign_in")
}
// User created a new FxA account.

View File

@ -170,6 +170,7 @@ class Components(private val context: Context) {
}
val analytics by lazyMonitored { Analytics(context, performance.visualCompletenessQueue.queue) }
val nimbus by lazyMonitored { NimbusComponents(context) }
val publicSuffixList by lazyMonitored { PublicSuffixList(context) }
val clipboardHandler by lazyMonitored { ClipboardHandler(context) }
val performance by lazyMonitored { PerformanceComponent() }
@ -231,7 +232,7 @@ class Components(private val context: Context) {
context.pocketStoriesSelectedCategoriesDataStore,
),
MessagingMiddleware(
messagingStorage = analytics.messagingStorage,
messagingStorage = nimbus.messagingStorage,
),
MetricsMiddleware(metrics = analytics.metrics),
),

View File

@ -0,0 +1,88 @@
/* 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.components
import android.content.Context
import mozilla.components.service.nimbus.NimbusApi
import mozilla.components.service.nimbus.messaging.FxNimbusMessaging
import mozilla.components.service.nimbus.messaging.NimbusMessagingStorage
import mozilla.components.service.nimbus.messaging.OnDiskMessageMetadataStorage
import org.mozilla.experiments.nimbus.NimbusEventStore
import org.mozilla.experiments.nimbus.NimbusMessagingHelperInterface
import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.experiments.createNimbus
import org.mozilla.fenix.messaging.CustomAttributeProvider
import org.mozilla.fenix.perf.lazyMonitored
/**
* Component group for access to Nimbus and other Nimbus services.
*/
class NimbusComponents(private val context: Context) {
/**
* The main entry point for the Nimbus SDK. Note that almost all access to feature configuration
* should be mediated through a FML generated class, e.g. [FxNimbus].
*/
val sdk: NimbusApi by lazyMonitored {
createNimbus(context, BuildConfig.NIMBUS_ENDPOINT)
}
/**
* Convenience method for getting the event store from the SDK.
*
* Before EXP-4354, this is the main write API for recording events to drive
* messaging, experiments and onboarding.
*
* Following EXP-4354, clients will not need to write these events
* themselves.
*
* Read access to the event store should be done through
* the JEXL helper available from [createJexlHelper].
*/
val events: NimbusEventStore by lazyMonitored {
sdk.events
}
/**
* Create a new JEXL evaluator suitable for use by any feature.
*
* JEXL evaluator context is provided by the app and changes over time.
*
* For this reason, an evaluator should be not be stored or cached.
*
* Since it has a native peer, to avoid leaking memory, the helper's [destroy] method
* should be called after finishing the set of evaluations.
*
* This can be done automatically using the interface's `use` method, e.g.
*
* ```
* val isEligible = nimbus.createJexlHelper().use { helper ->
* expressions.all { exp -> helper.evalJexl(exp) }
* }
* ```
*
* The helper has access to all context needed to drive decisions
* about messaging, onboarding and experimentation.
*
* It also has a built-in cache.
*/
fun createJexlHelper(): NimbusMessagingHelperInterface =
messagingStorage.createMessagingHelper()
/**
* Low level access to the messaging component.
*
* The app should access this through a [mozilla.components.service.nimbus.messaging.NimbusMessagingController].
*/
val messagingStorage by lazyMonitored {
NimbusMessagingStorage(
context = context,
metadataStorage = OnDiskMessageMetadataStorage(context),
nimbus = sdk,
messagingFeature = FxNimbusMessaging.features.messaging,
attributeProvider = CustomAttributeProvider,
)
}
}

View File

@ -360,7 +360,7 @@ class HomeFragment : Fragment() {
engine = components.core.engine,
messageController = DefaultMessageController(
appStore = components.appStore,
messagingController = FenixNimbusMessagingController(components.analytics.messagingStorage),
messagingController = FenixNimbusMessagingController(components.nimbus.messagingStorage),
homeActivity = activity,
),
store = store,

View File

@ -45,7 +45,7 @@ class MessageNotificationWorker(
override suspend fun doWork(): Result {
val context = applicationContext
val messagingStorage = context.components.analytics.messagingStorage
val messagingStorage = context.components.nimbus.messagingStorage
val messages = messagingStorage.getMessages()
val nextMessage =
messagingStorage.getNextMessage(FenixMessageSurfaceId.NOTIFICATION, messages)
@ -178,7 +178,7 @@ class NotificationDismissedService : LifecycleService() {
if (intent != null) {
val nimbusMessagingController =
FenixNimbusMessagingController(applicationContext.components.analytics.messagingStorage)
FenixNimbusMessagingController(applicationContext.components.nimbus.messagingStorage)
lifecycleScope.launch {
// Get the relevant message.
@ -209,7 +209,7 @@ class NotificationClickedReceiverActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
val nimbusMessagingController =
FenixNimbusMessagingController(components.analytics.messagingStorage)
FenixNimbusMessagingController(components.nimbus.messagingStorage)
lifecycleScope.launch {
// Get the relevant message.

View File

@ -51,7 +51,7 @@ class NimbusBranchesFragment : Fragment() {
context = requireContext(),
navController = findNavController(),
nimbusBranchesStore = nimbusBranchesStore,
experiments = requireContext().components.analytics.experiments,
experiments = requireContext().components.nimbus.sdk,
experimentId = args.experimentId,
)
@ -77,7 +77,7 @@ class NimbusBranchesFragment : Fragment() {
private fun loadExperimentBranches() {
lifecycleScope.launch(Dispatchers.IO) {
try {
val experiments = requireContext().components.analytics.experiments
val experiments = requireContext().components.nimbus.sdk
val branches = experiments.getExperimentBranches(args.experimentId) ?: emptyList()
val selectedBranch = experiments.getExperimentBranch(args.experimentId) ?: ""

View File

@ -35,7 +35,7 @@ class NimbusExperimentsFragment : Fragment() {
setContent {
FirefoxTheme {
val experiments =
requireContext().components.analytics.experiments.getAvailableExperiments()
requireContext().components.nimbus.sdk.getAvailableExperiments()
NimbusExperiments(
experiments = experiments,

View File

@ -232,7 +232,7 @@ class OnboardingFragment : Fragment() {
showAddWidgetPage: Boolean,
): List<OnboardingPageUiData> {
val jexlConditions = FxNimbus.features.junoOnboarding.value().conditions
val jexlHelper = requireContext().components.analytics.messagingStorage.createMessagingHelper()
val jexlHelper = requireContext().components.nimbus.createJexlHelper()
val privacyCaption = Caption(
text = getString(R.string.juno_onboarding_privacy_notice_text),

View File

@ -37,7 +37,7 @@ class DataChoicesFragment : PreferenceFragmentCompat() {
// Reset experiment identifiers on both opt-in and opt-out; it's likely
// that in future we will need to pass in the new telemetry client_id
// to this method when the user opts back in.
context.components.analytics.experiments.resetTelemetryIdentifiers()
context.components.nimbus.sdk.resetTelemetryIdentifiers()
} else if (key == getPreferenceKey(R.string.pref_key_marketing_telemetry)) {
if (context.settings().isMarketingTelemetryEnabled) {
context.components.analytics.metrics.start(MetricServiceType.Marketing)

View File

@ -30,7 +30,7 @@ class StudiesFragment : Fragment() {
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
val experiments = requireComponents.analytics.experiments
val experiments = requireComponents.nimbus.sdk
_binding = SettingsStudiesBinding.inflate(inflater, container, false)
val interactor = DefaultStudiesInteractor((activity as HomeActivity), experiments)
StudiesView(

View File

@ -56,8 +56,9 @@ class BackgroundServicesTest {
val mockComponents: Components = mockk()
every { mockComponents.settings } returns settings
every { mockComponents.analytics } returns mockk {
every { experiments } returns nimbus
every { mockComponents.nimbus } returns mockk {
every { sdk } returns nimbus
every { events } returns nimbus
}
every { context.components } returns mockComponents
every { nimbus.recordEvent(any()) } returns Unit