commit 77b0724ec38e27341fcd1426446700e841f7c155
parent a88d21076eaac14468c66311e75f7519c29edb14
Author: Tif Tran <ttran@mozilla.com>
Date: Fri, 14 Nov 2025 21:20:23 +0000
Bug 1974132: Nimbus to use remotesettingsservice r=bdk,jonalmeida
Differential Revision: https://phabricator.services.mozilla.com/D255069
Diffstat:
6 files changed, 71 insertions(+), 39 deletions(-)
diff --git a/mobile/android/android-components/samples/glean/src/main/java/org/mozilla/samples/glean/GleanApplication.kt b/mobile/android/android-components/samples/glean/src/main/java/org/mozilla/samples/glean/GleanApplication.kt
@@ -7,7 +7,6 @@ package org.mozilla.samples.glean
import android.app.Application
import android.content.Context
import androidx.core.content.edit
-import androidx.core.net.toUri
import mozilla.components.lib.fetch.httpurlconnection.HttpURLConnectionClient
import mozilla.components.service.glean.net.ConceptFetchHttpUploader
import mozilla.components.service.nimbus.Nimbus
@@ -80,7 +79,6 @@ class GleanApplication : Application() {
private fun initNimbus(isFirstRun: Boolean) {
RustLog.enable()
RustHttpConfig.setClient(lazy { HttpURLConnectionClient() })
- val url = getString(R.string.nimbus_default_endpoint).toUri()
val appInfo = NimbusAppInfo(
appName = "samples-glean",
channel = "samples",
@@ -88,7 +86,7 @@ class GleanApplication : Application() {
nimbus = Nimbus(
context = this,
appInfo = appInfo,
- server = NimbusServerSettings(url),
+ server = NimbusServerSettings(remoteSettingsService = null),
recordedContext = null,
).also { nimbus ->
if (isFirstRun) {
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt
@@ -197,7 +197,26 @@ class Components(private val context: Context) {
}
val analytics by lazyMonitored { Analytics(context, nimbus, performance.visualCompletenessQueue) }
- val nimbus by lazyMonitored { NimbusComponents(context) }
+
+ val remoteSettingsService = lazyMonitored {
+ RemoteSettingsService(
+ context,
+ if (context.settings().useProductionRemoteSettingsServer) {
+ RemoteSettingsServer.Prod.into()
+ } else {
+ RemoteSettingsServer.Stage.into()
+ },
+ channel = BuildConfig.BUILD_TYPE,
+ // Need to send this value separately, since `isLargeScreenSize()` is a fenix extension
+ isLargeScreenSize = context.isLargeScreenSize(),
+ )
+ }
+ val nimbus by lazyMonitored {
+ NimbusComponents(
+ context = context,
+ remoteSettingsService = remoteSettingsService.value.remoteSettingsService,
+ )
+ }
val publicSuffixList by lazyMonitored { PublicSuffixList(context) }
val clipboardHandler by lazyMonitored { ClipboardHandler(context) }
val performance by lazyMonitored { PerformanceComponent() }
@@ -321,20 +340,6 @@ class Components(private val context: Context) {
null
}
- val remoteSettingsService = lazyMonitored {
- RemoteSettingsService(
- context,
- if (context.settings().useProductionRemoteSettingsServer) {
- RemoteSettingsServer.Prod.into()
- } else {
- RemoteSettingsServer.Stage.into()
- },
- channel = BuildConfig.BUILD_TYPE,
- // Need to send this value separately, since `isLargeScreenSize()` is a fenix extension
- isLargeScreenSize = context.isLargeScreenSize(),
- )
- }
-
val fxSuggest by lazyMonitored { FxSuggest(context, remoteSettingsService.value) }
val distributionIdManager by lazyMonitored {
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/NimbusComponents.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/NimbusComponents.kt
@@ -5,6 +5,7 @@
package org.mozilla.fenix.components
import android.content.Context
+import mozilla.appservices.remotesettings.RemoteSettingsService
import mozilla.components.service.nimbus.NimbusApi
import mozilla.components.service.nimbus.messaging.FxNimbusMessaging
import mozilla.components.service.nimbus.messaging.NimbusMessagingController
@@ -21,14 +22,14 @@ import org.mozilla.fenix.perf.lazyMonitored
/**
* Component group for access to Nimbus and other Nimbus services.
*/
-class NimbusComponents(private val context: Context) {
+class NimbusComponents(private val context: Context, remoteSettingsService: RemoteSettingsService?) {
/**
* 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)
+ createNimbus(context, BuildConfig.NIMBUS_ENDPOINT, remoteSettingsService)
}
/**
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/experiments/NimbusSetup.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/experiments/NimbusSetup.kt
@@ -5,9 +5,11 @@
package org.mozilla.fenix.experiments
import android.content.Context
+import mozilla.appservices.remotesettings.RemoteSettingsService
import mozilla.components.service.nimbus.NimbusApi
import mozilla.components.service.nimbus.NimbusAppInfo
import mozilla.components.service.nimbus.NimbusBuilder
+import mozilla.components.service.nimbus.NimbusServerSettings
import mozilla.components.service.nimbus.messaging.FxNimbusMessaging
import mozilla.components.service.nimbus.messaging.NimbusSystem
import mozilla.components.support.base.log.logger.Logger
@@ -34,7 +36,11 @@ private val logger = Logger("service/Nimbus")
/**
* Create the Nimbus singleton object for the Fenix app.
*/
-fun createNimbus(context: Context, urlString: String?): NimbusApi {
+fun createNimbus(
+ context: Context,
+ urlString: String?,
+ remoteSettingsService: RemoteSettingsService?,
+): NimbusApi {
// These values can be used in the JEXL expressions when targeting experiments.
val customTargetingAttributes = CustomAttributeProvider.getCustomTargetingAttributes(context)
@@ -48,6 +54,17 @@ fun createNimbus(context: Context, urlString: String?): NimbusApi {
isFirstRun = isAppFirstRun,
)
+ val serverSettings: NimbusServerSettings? = remoteSettingsService?.let { service ->
+ NimbusServerSettings(
+ remoteSettingsService = service,
+ collection = if (context.settings().nimbusUsePreview) {
+ "nimbus-preview"
+ } else {
+ "nimbus-mobile-experiments"
+ },
+ )
+ }
+
// The name "fenix" here corresponds to the app_name defined for the family of apps
// that encompasses all of the channels for the Fenix app. This is defined upstream in
// the telemetry system. For more context on where the app_name come from see:
@@ -68,7 +85,6 @@ fun createNimbus(context: Context, urlString: String?): NimbusApi {
errorReporter = context::reportError
initialExperiments = R.raw.initial_experiments
timeoutLoadingExperiment = TIME_OUT_LOADING_EXPERIMENT_FROM_DISK_MS
- usePreviewCollection = context.settings().nimbusUsePreview
sharedPreferences = context.settings().preferences
isFirstRun = isAppFirstRun
featureManifest = FxNimbus
@@ -76,7 +92,7 @@ fun createNimbus(context: Context, urlString: String?): NimbusApi {
context.settings().nimbusExperimentsFetched = true
}
recordedContext = recordedNimbusContext
- }.build(appInfo).also { nimbusApi ->
+ }.build(appInfo, serverSettings).also { nimbusApi ->
nimbusApi.recordIsReady(FxNimbus.features.nimbusIsReady.value().eventCount)
}
}
diff --git a/mobile/android/focus-android/app/src/main/java/org/mozilla/focus/Components.kt b/mobile/android/focus-android/app/src/main/java/org/mozilla/focus/Components.kt
@@ -262,8 +262,20 @@ class Components(
)
}
+ val remoteSettingsService by lazy {
+ RemoteSettingsService(
+ context,
+ if (context.settings.useProductionRemoteSettingsServer) {
+ RemoteSettingsServer.Prod.into()
+ } else {
+ RemoteSettingsServer.Stage.into()
+ },
+ channel = BuildConfig.BUILD_TYPE,
+ )
+ }
+
val experiments: NimbusApi by lazy {
- createNimbus(context, BuildConfig.NIMBUS_ENDPOINT)
+ createNimbus(context, BuildConfig.NIMBUS_ENDPOINT, remoteSettingsService.remoteSettingsService)
}
val adsTelemetry: AdsTelemetry by lazy { AdsTelemetry() }
@@ -290,18 +302,6 @@ class Components(
val dateTimeProvider: DateTimeProvider by lazy { DefaultDateTimeProvider() }
val downloadEstimator: DownloadEstimator by lazy { DownloadEstimator(dateTimeProvider = dateTimeProvider) }
-
- val remoteSettingsService by lazy {
- RemoteSettingsService(
- context,
- if (context.settings.useProductionRemoteSettingsServer) {
- RemoteSettingsServer.Prod.into()
- } else {
- RemoteSettingsServer.Stage.into()
- },
- channel = BuildConfig.BUILD_TYPE,
- )
- }
}
private fun createCrashReporter(context: Context): CrashReporter {
diff --git a/mobile/android/focus-android/app/src/main/java/org/mozilla/focus/experiments/NimbusSetup.kt b/mobile/android/focus-android/app/src/main/java/org/mozilla/focus/experiments/NimbusSetup.kt
@@ -5,9 +5,11 @@
package org.mozilla.focus.experiments
import android.content.Context
+import mozilla.appservices.remotesettings.RemoteSettingsService
import mozilla.components.service.nimbus.NimbusApi
import mozilla.components.service.nimbus.NimbusAppInfo
import mozilla.components.service.nimbus.NimbusBuilder
+import mozilla.components.service.nimbus.NimbusServerSettings
import mozilla.components.support.base.log.logger.Logger
import org.json.JSONObject
import org.mozilla.experiments.nimbus.NimbusInterface
@@ -29,7 +31,7 @@ private const val TIME_OUT_LOADING_EXPERIMENT_FROM_DISK_MS = 200L
/**
* Create the Nimbus singleton object for the Focus/Klar apps.
*/
-fun createNimbus(context: Context, urlString: String?): NimbusApi {
+fun createNimbus(context: Context, urlString: String?, remoteSettingsService: RemoteSettingsService?): NimbusApi {
val isAppFirstRun = context.settings.isFirstRun
// These values can be used in the JEXL expressions when targeting experiments.
@@ -58,6 +60,17 @@ fun createNimbus(context: Context, urlString: String?): NimbusApi {
customTargetingAttributes = customTargetingAttributes,
)
+ val serverSettings: NimbusServerSettings? = remoteSettingsService?.let { service ->
+ NimbusServerSettings(
+ remoteSettingsService = service,
+ collection = if (context.settings.shouldUseNimbusPreview) {
+ "nimbus-preview"
+ } else {
+ "nimbus-mobile-experiments"
+ },
+ )
+ }
+
return NimbusBuilder(context).apply {
url = urlString
errorReporter = { message, e ->
@@ -68,11 +81,10 @@ fun createNimbus(context: Context, urlString: String?): NimbusApi {
}
initialExperiments = R.raw.initial_experiments
timeoutLoadingExperiment = TIME_OUT_LOADING_EXPERIMENT_FROM_DISK_MS
- usePreviewCollection = context.settings.shouldUseNimbusPreview
sharedPreferences = context.settings.preferences
isFirstRun = isAppFirstRun
featureManifest = FocusNimbus
- }.build(appInfo)
+ }.build(appInfo, serverSettings)
}
internal fun finishNimbusInitialization(experiments: NimbusApi) =