From ab678a21ffa308ee958cd6a9e3439f584911a08f Mon Sep 17 00:00:00 2001 From: James Hugman Date: Fri, 21 May 2021 20:11:35 +0100 Subject: [PATCH] Add an experiment to demontrate the Feature API This is not visible in production, but only debug. It shows three variables being used to change the settings screen (title, icon and title-punctuation). --- .../debug/res/raw/initial_experiments.json | 236 ++++++++++++++++++ .../metrics/SecurePrefsTelemetry.kt | 4 +- .../components/toolbar/DefaultToolbarMenu.kt | 4 +- .../mozilla/fenix/experiments/Experiments.kt | 21 +- .../mozilla/fenix/experiments/NimbusSetup.kt | 5 + .../main/java/org/mozilla/fenix/ext/Nimbus.kt | 104 ++++++-- .../java/org/mozilla/fenix/home/HomeMenu.kt | 49 +--- .../fenix/nimbus/NimbusBranchesFragment.kt | 2 +- .../fenix/settings/SettingsFragment.kt | 13 +- .../java/org/mozilla/fenix/utils/Settings.kt | 6 +- app/src/main/res/raw/initial_experiments.json | 3 + 11 files changed, 371 insertions(+), 76 deletions(-) create mode 100644 app/src/debug/res/raw/initial_experiments.json create mode 100644 app/src/main/res/raw/initial_experiments.json diff --git a/app/src/debug/res/raw/initial_experiments.json b/app/src/debug/res/raw/initial_experiments.json new file mode 100644 index 0000000000..fdff360285 --- /dev/null +++ b/app/src/debug/res/raw/initial_experiments.json @@ -0,0 +1,236 @@ +{ + "data": [{ + "slug": "feature-text-variables-validation-android", + "appId": "org.mozilla.fenix", + "appName": "fenix", + "channel": "nightly", + "branches": [{ + "slug": "control", + "ratio": 100, + "feature": { + "value": {}, + "enabled": true, + "featureId": "nimbus-validation" + } + }, + { + "slug": "a1", + "ratio": 0, + "feature": { + "value": { + "settings-title": "settings_title", + "settings-title-punctuation": "…" + }, + "enabled": true, + "featureId": "nimbus-validation" + } + }, + { + "slug": "a2", + "ratio": 0, + "feature": { + "value": { + "settings-title": "preferences_category_general", + "settings-title-punctuation": "!" + }, + "enabled": true, + "featureId": "nimbus-validation" + } + } + ], + "outcomes": [], + "arguments": {}, + "probeSets": [], + "startDate": null, + "targeting": "true", + "featureIds": [ + "nimbus-validation" + ], + "application": "org.mozilla.firefox_beta", + "bucketConfig": { + "count": 0, + "start": 0, + "total": 10000, + "namespace": "nimbus-validation-2", + "randomizationUnit": "nimbus_id" + }, + "schemaVersion": "1.5.0", + "userFacingName": "Nimbus Text Variables Validation", + "referenceBranch": "control", + "proposedDuration": 14, + "isEnrollmentPaused": false, + "proposedEnrollment": 7, + "userFacingDescription": "Demonstration experiment to make trivial visible changes to text in Settings", + "last_modified": 1621443780172 + }, + { + "slug": "feature-icon-variables-validation-android", + "appId": "org.mozilla.fenix", + "appName": "fenix", + "channel": "nightly", + "branches": [{ + "slug": "control", + "ratio": 100, + "feature": { + "value": {}, + "enabled": true, + "featureId": "nimbus-validation" + } + }, + { + "slug": "treatment", + "ratio": 0, + "feature": { + "value": { + "settings-title": "Fancy Settings", + "settings-icon": "ic_edit" + }, + "enabled": true, + "featureId": "nimbus-validation" + } + } + ], + "outcomes": [], + "arguments": {}, + "probeSets": [], + "startDate": null, + "targeting": "true", + "featureIds": [ + "nimbus-validation" + ], + "application": "org.mozilla.firefox_beta", + "bucketConfig": { + "count": 0, + "start": 0, + "total": 10000, + "namespace": "nimbus-validation-2", + "randomizationUnit": "nimbus_id" + }, + "schemaVersion": "1.5.0", + "userFacingName": "Nimbus Icon Variables Validation", + "referenceBranch": "control", + "proposedDuration": 14, + "isEnrollmentPaused": false, + "proposedEnrollment": 7, + "userFacingDescription": "Demonstration experiment to make trivial visible changes to icons in Settings", + "last_modified": 1621443780172 + }, + + { + "slug": "feature-text-variables-validation-ios", + "appId": "org.mozilla.ios.Fennec", + "appName": "firefox_ios", + "channel": "nightly", + "branches": [{ + "slug": "control", + "ratio": 100, + "feature": { + "value": {}, + "enabled": true, + "featureId": "nimbus-validation" + } + }, + { + "slug": "a1", + "ratio": 0, + "feature": { + "value": { + "settings-title": "Menu/Menu.OpenSettingsAction.Title", + "settings-title-punctuation": "…" + }, + "enabled": true, + "featureId": "nimbus-validation" + } + }, + { + "slug": "a2", + "ratio": 0, + "feature": { + "value": { + "settings-title": "Settings.General.SectionName", + "settings-title-punctuation": "!" + }, + "enabled": true, + "featureId": "nimbus-validation" + } + } + ], + "outcomes": [], + "arguments": {}, + "probeSets": [], + "startDate": null, + "targeting": "true", + "featureIds": [ + "nimbus-validation" + ], + "application": "org.mozilla.ios.Fennec", + "bucketConfig": { + "count": 0, + "start": 0, + "total": 10000, + "namespace": "nimbus-validation-2", + "randomizationUnit": "nimbus_id" + }, + "schemaVersion": "1.5.0", + "userFacingName": "Nimbus Text Variables Validation", + "referenceBranch": "control", + "proposedDuration": 14, + "isEnrollmentPaused": false, + "proposedEnrollment": 7, + "userFacingDescription": "Demonstration experiment to make trivial visible changes to text in Settings", + "last_modified": 1621443780172 + }, + { + "slug": "feature-icon-variables-validation-ios", + "appId": "org.mozilla.ios.Fennec", + "appName": "firefox_ios", + "channel": "nightly", + "branches": [{ + "slug": "control", + "ratio": 100, + "feature": { + "value": {}, + "enabled": true, + "featureId": "nimbus-validation" + } + }, + { + "slug": "treatment", + "ratio": 0, + "feature": { + "value": { + "settings-title": "Fancy Settings", + "settings-icon": "menu-ViewMobile" + }, + "enabled": true, + "featureId": "nimbus-validation" + } + } + ], + "outcomes": [], + "arguments": {}, + "probeSets": [], + "startDate": null, + "targeting": "true", + "featureIds": [ + "nimbus-validation" + ], + "application": "org.mozilla.ios.Fennec", + "bucketConfig": { + "count": 0, + "start": 0, + "total": 10000, + "namespace": "nimbus-validation-2", + "randomizationUnit": "nimbus_id" + }, + "schemaVersion": "1.5.0", + "userFacingName": "Nimbus Icon Variables Validation", + "referenceBranch": "control", + "proposedDuration": 14, + "isEnrollmentPaused": false, + "proposedEnrollment": 7, + "userFacingDescription": "Demonstration experiment to make trivial visible changes to icons in Settings", + "last_modified": 1621443780172 + } + ] +} diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/SecurePrefsTelemetry.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/SecurePrefsTelemetry.kt index 47a34497a5..c88841f16d 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/SecurePrefsTelemetry.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/SecurePrefsTelemetry.kt @@ -9,7 +9,7 @@ import android.os.Build import mozilla.components.lib.dataprotect.SecurePrefsReliabilityExperiment import mozilla.components.service.nimbus.NimbusApi import org.mozilla.fenix.experiments.ExperimentBranch -import org.mozilla.fenix.experiments.Experiments +import org.mozilla.fenix.experiments.FeatureId import org.mozilla.fenix.ext.withExperiment /** @@ -24,7 +24,7 @@ class SecurePrefsTelemetry( // The Android Keystore is used to secure the shared prefs only on API 23+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // These tests should run only if the experiment is live - experiments.withExperiment(Experiments.ANDROID_KEYSTORE) { experimentBranch -> + experiments.withExperiment(FeatureId.ANDROID_KEYSTORE) { experimentBranch -> // .. and this device is not in the control group. if (experimentBranch == ExperimentBranch.TREATMENT) { SecurePrefsReliabilityExperiment(appContext)() diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt index a4b4737b89..0cf53913a5 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt @@ -41,7 +41,7 @@ import org.mozilla.fenix.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.accounts.FenixAccountManager import org.mozilla.fenix.experiments.ExperimentBranch -import org.mozilla.fenix.experiments.Experiments +import org.mozilla.fenix.experiments.FeatureId import org.mozilla.fenix.ext.asActivity import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings @@ -632,7 +632,7 @@ open class DefaultToolbarMenu( val experiments = context.components.analytics.experiments val browsers = BrowsersCache.all(context) - return experiments.withExperiment(Experiments.DEFAULT_BROWSER) { experimentBranch -> + return experiments.withExperiment(FeatureId.DEFAULT_BROWSER) { experimentBranch -> if (experimentBranch == ExperimentBranch.DEFAULT_BROWSER_TOOLBAR_MENU && !browsers.isFirefoxDefaultBrowser ) { diff --git a/app/src/main/java/org/mozilla/fenix/experiments/Experiments.kt b/app/src/main/java/org/mozilla/fenix/experiments/Experiments.kt index 92808c5ffc..6f83567f3f 100644 --- a/app/src/main/java/org/mozilla/fenix/experiments/Experiments.kt +++ b/app/src/main/java/org/mozilla/fenix/experiments/Experiments.kt @@ -4,14 +4,23 @@ package org.mozilla.fenix.experiments -class Experiments { - companion object { - const val A_A_NIMBUS_VALIDATION = "fenix-nimbus-validation-v3" - const val ANDROID_KEYSTORE = "fenix-android-keystore" - const val DEFAULT_BROWSER = "fenix-default-browser" - } +/** + * Enums to identify features in the app. These will likely grow and shrink depending + * on the experiments we want to perform. + * + * @property jsonName the kebab-case version of the feature id as represented in the Nimbus + * experiment JSON. + */ +enum class FeatureId(val jsonName: String) { + NIMBUS_VALIDATION("nimbus-validation"), + ANDROID_KEYSTORE("fenix-android-keystore"), + DEFAULT_BROWSER("fenix-default-browser") } +/** + * Experiment branches are becoming less interesting, though we collect some well + * defined ones here. + */ class ExperimentBranch { companion object { const val TREATMENT = "treatment" diff --git a/app/src/main/java/org/mozilla/fenix/experiments/NimbusSetup.kt b/app/src/main/java/org/mozilla/fenix/experiments/NimbusSetup.kt index 4362056ccc..9933439e79 100644 --- a/app/src/main/java/org/mozilla/fenix/experiments/NimbusSetup.kt +++ b/app/src/main/java/org/mozilla/fenix/experiments/NimbusSetup.kt @@ -15,6 +15,7 @@ import mozilla.components.service.nimbus.NimbusDisabled import mozilla.components.service.nimbus.NimbusServerSettings import mozilla.components.support.base.log.logger.Logger import org.mozilla.fenix.BuildConfig +import org.mozilla.fenix.R import org.mozilla.fenix.components.isSentryEnabled import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings @@ -66,6 +67,10 @@ fun createNimbus(context: Context, url: String?): NimbusApi = globalUserParticipation = enabled } + if (url.isNullOrBlank()) { + setExperimentsLocally(R.raw.initial_experiments) + } + // We may have downloaded experiments on a previous run, so let's start using them // now. We didn't do this earlier, so as to make getExperimentBranch and friends returns // the same thing throughout the session. This call does its work on the db thread. diff --git a/app/src/main/java/org/mozilla/fenix/ext/Nimbus.kt b/app/src/main/java/org/mozilla/fenix/ext/Nimbus.kt index e1ab7fa39c..634a12f388 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/Nimbus.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/Nimbus.kt @@ -5,38 +5,98 @@ package org.mozilla.fenix.ext import mozilla.components.service.nimbus.NimbusApi -import mozilla.components.support.base.log.logger.Logger -import org.mozilla.fenix.FeatureFlags +import org.mozilla.experiments.nimbus.Variables +import org.mozilla.fenix.experiments.FeatureId /** - * Gets the branch of the given `experimentId` and transforms it with given closure. + * Gets the branch name of an experiment acting on the feature given `featureId`, and transforms it + * with given closure. * - * If we're enrolled in the experiment, the transform is passed the branch id/slug as a `String`. + * You are probably looking for `withVariables`. + * + * If we're enrolled in an experiment, the transform is passed the branch id/slug as a `String`. * * If we're not enrolled in the experiment, or the experiment is not valid then the transform * is passed a `null`. */ -@Suppress("TooGenericExceptionCaught") -fun NimbusApi.withExperiment(experimentId: String, transform: (String?) -> T): T { - val branch = if (FeatureFlags.nimbusExperiments) { - try { - getExperimentBranch(experimentId) - } catch (e: Throwable) { - Logger.error("Failed to getExperimentBranch($experimentId)", e) - null - } - } else { - null - } - return transform(branch) +fun NimbusApi.withExperiment(featureId: FeatureId, transform: (String?) -> T): T { + return transform(getExperimentBranch(featureId.jsonName)) } /** - * The degenerate case of `withExperiment(String, (String?) -> T))`, with an identity transform. + * The synonym for [getExperimentBranch] to complement [withExperiment(String, (String?) -> T))]. + * + * Short-hand for ` org.mozilla.experiments.nimbus.NimbusApi.getExperimentBranch`. + */ +fun NimbusApi.withExperiment(featureId: FeatureId) = + getExperimentBranch(featureId.jsonName) + +/** + * Get the variables needed to configure the feature given by `featureId`. + * + * @param featureId The feature id that identifies the feature under experiment. + * + * @param sendExposureEvent Passing `true` to this parameter will record the exposure event + * automatically if the client is enrolled in an experiment for the given [featureId]. + * Passing `false` here indicates that the application will manually record the exposure + * event by calling the `sendExposureEvent` function at the time of the exposure to the + * feature. + * + * See [sendExposureEvent] for more information on manually recording the event. + * + * @return a [Variables] object used to configure the feature. + */ +fun NimbusApi.getVariables(featureId: FeatureId, sendExposureEvent: Boolean = true) = + getVariables(featureId.jsonName, sendExposureEvent) + +/** + * A synonym for `getVariables(featureId, sendExposureEvent)`. * - * Short-hand for `mozilla.components.service.nimbus.NimbusApi.getExperimentBranch`. + * This exists as a complement to the `withVariable(featureId, sendExposureEvent, transform)` method. + * + * @param featureId the id of the feature as it appears in `Experimenter` + * @param sendExposureEvent by default `true`. This logs an event that the user was exposed to an experiment + * involving this feature. + * @return a `Variables` object providing typed accessors to a remotely configured JSON object. + */ +fun NimbusApi.withVariables(featureId: FeatureId, sendExposureEvent: Boolean = true) = + getVariables(featureId, sendExposureEvent) + +/** + * Get a `Variables` object for this feature and use that to configure the feature itself or a more type safe configuration object. + * + * @param featureId the id of the feature as it appears in `Experimenter` + * @param sendExposureEvent by default `true`. This logs an event that the user was exposed to an experiment + * involving this feature. */ -fun NimbusApi.withExperiment(experimentId: String) = - this.withExperiment(experimentId, ::identity) +fun NimbusApi.withVariables(featureId: FeatureId, sendExposureEvent: Boolean = true, transform: (Variables) -> T) = + transform(getVariables(featureId, sendExposureEvent)) -private fun identity(value: T) = value +/** + * Records the `exposure` event in telemetry. + * + * This is a manual function to accomplish the same purpose as passing `true` as the + * `sendExposureEvent` property of the `getVariables` function. It is intended to be used + * when requesting feature variables must occur at a different time than the actual user's + * exposure to the feature within the app. + * + * - Examples: + * - If the `Variables` are needed at a different time than when the exposure to the feature + * actually happens, such as constructing a menu happening at a different time than the + * user seeing the menu. + * - If `getVariables` is required to be called multiple times for the same feature and it is + * desired to only record the exposure once, such as if `getVariables` were called + * with every keystroke. + * + * In the case where the use of this function is required, then the `getVariables` function + * should be called with `false` so that the exposure event is not recorded when the variables + * are fetched. + * + * This function is safe to call even when there is no active experiment for the feature. The SDK + * will ensure that an event is only recorded for active experiments. + * + * @param featureId string representing the id of the feature for which to record the exposure + * event. + */ +fun NimbusApi.recordExposureEvent(featureId: FeatureId) = + recordExposureEvent(featureId.jsonName) diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt b/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt index cf89bd2bb6..4184f59db3 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt @@ -27,11 +27,10 @@ import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.FeatureFlags.tabsTrayRewrite import org.mozilla.fenix.R import org.mozilla.fenix.components.accounts.FenixAccountManager -import org.mozilla.fenix.experiments.ExperimentBranch -import org.mozilla.fenix.experiments.Experiments +import org.mozilla.fenix.experiments.FeatureId import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.getVariables import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.ext.withExperiment import org.mozilla.fenix.theme.ThemeManager import org.mozilla.fenix.whatsnew.WhatsNew @@ -142,23 +141,9 @@ class HomeMenu( onItemTapped.invoke(Item.Bookmarks) } - // We want to validate that the Nimbus experiments library is working, from the android UI - // all the way back to the data science backend. We're not testing the user's preference - // or response, we're end-to-end testing the experiments platform. - // So here, we're running multiple identical branches with the same treatment, and if the - // user isn't targeted, then we get still get the same treatment. - // The `let` block is degenerate here, but left here so as to document the form of how experiments - // are implemented here. - val historyIcon = experiments.withExperiment(Experiments.A_A_NIMBUS_VALIDATION) { - when (it) { - ExperimentBranch.A1 -> R.drawable.ic_history - ExperimentBranch.A2 -> R.drawable.ic_history - else -> R.drawable.ic_history - } - } val historyItem = BrowserMenuImageText( context.getString(R.string.library_history), - historyIcon, + R.drawable.ic_history, primaryTextColor ) { onItemTapped.invoke(Item.History) @@ -172,9 +157,11 @@ class HomeMenu( onItemTapped.invoke(Item.Extensions) } + // Use nimbus to set the icon and title. + val variables = experiments.getVariables(FeatureId.NIMBUS_VALIDATION) val settingsItem = BrowserMenuImageText( - context.getString(R.string.browser_menu_settings), - R.drawable.ic_settings, + variables.getText("settings-title") ?: context.getString(R.string.browser_menu_settings), + variables.getDrawableResource("settings-icon") ?: R.drawable.ic_settings, primaryTextColor ) { onItemTapped.invoke(Item.Settings) @@ -252,23 +239,9 @@ class HomeMenu( onItemTapped.invoke(Item.Bookmarks) } - // We want to validate that the Nimbus experiments library is working, from the android UI - // all the way back to the data science backend. We're not testing the user's preference - // or response, we're end-to-end testing the experiments platform. - // So here, we're running multiple identical branches with the same treatment, and if the - // user isn't targeted, then we get still get the same treatment. - // The `let` block is degenerate here, but left here so as to document the form of how experiments - // are implemented here. - val historyIcon = experiments.withExperiment(Experiments.A_A_NIMBUS_VALIDATION) { - when (it) { - ExperimentBranch.A1 -> R.drawable.ic_history - ExperimentBranch.A2 -> R.drawable.ic_history - else -> R.drawable.ic_history - } - } val historyItem = BrowserMenuImageText( context.getString(R.string.library_history), - historyIcon, + R.drawable.ic_history, primaryTextColor ) { onItemTapped.invoke(Item.History) @@ -310,9 +283,11 @@ class HomeMenu( onItemTapped.invoke(Item.Help) } + // Use nimbus to set the icon and title. + val variables = experiments.getVariables(FeatureId.NIMBUS_VALIDATION) val settingsItem = BrowserMenuImageText( - context.getString(R.string.browser_menu_settings), - R.drawable.ic_settings, + variables.getText("settings-title") ?: context.getString(R.string.browser_menu_settings), + variables.getDrawableResource("settings-icon") ?: R.drawable.ic_settings, primaryTextColor ) { onItemTapped.invoke(Item.Settings) diff --git a/app/src/main/java/org/mozilla/fenix/nimbus/NimbusBranchesFragment.kt b/app/src/main/java/org/mozilla/fenix/nimbus/NimbusBranchesFragment.kt index 689afecd56..9f2f09293b 100644 --- a/app/src/main/java/org/mozilla/fenix/nimbus/NimbusBranchesFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/nimbus/NimbusBranchesFragment.kt @@ -79,7 +79,7 @@ class NimbusBranchesFragment : Fragment() { try { val experiments = requireContext().components.analytics.experiments val branches = experiments.getExperimentBranches(args.experimentId) ?: emptyList() - val selectedBranch = experiments.withExperiment(args.experimentId) ?: "" + val selectedBranch = experiments.getExperimentBranch(args.experimentId) ?: "" nimbusBranchesStore.dispatch( NimbusBranchesAction.UpdateBranches( diff --git a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt index 77bd567baa..af76d99456 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -42,7 +42,7 @@ import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.experiments.ExperimentBranch -import org.mozilla.fenix.experiments.Experiments +import org.mozilla.fenix.experiments.FeatureId import org.mozilla.fenix.ext.application import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.getPreferenceKey @@ -52,6 +52,7 @@ import org.mozilla.fenix.ext.navigateToNotificationsSettings import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.REQUEST_CODE_BROWSER_ROLE +import org.mozilla.fenix.ext.getVariables import org.mozilla.fenix.ext.openSetDefaultBrowserOption import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.ext.withExperiment @@ -161,7 +162,13 @@ class SettingsFragment : PreferenceFragmentCompat() { override fun onResume() { super.onResume() - showToolbar(getString(R.string.settings_title)) + // Use nimbus to set the title, and a trivial addition + val experiments = requireContext().components.analytics.experiments + val variables = experiments.getVariables(FeatureId.NIMBUS_VALIDATION) + val title = variables.getText("settings-title") ?: getString(R.string.settings_title) + val suffix = variables.getString("settings-title-punctuation") ?: "" + + showToolbar("$title$suffix") // Account UI state is updated as part of `onCreate`. To not do it twice in a row, we only // update it here if we're not going through the `onCreate->onStart->onResume` lifecycle chain. @@ -589,7 +596,7 @@ class SettingsFragment : PreferenceFragmentCompat() { private fun isDefaultBrowserExperimentBranch(): Boolean { val experiments = context?.components?.analytics?.experiments - return experiments?.withExperiment(Experiments.DEFAULT_BROWSER) { experimentBranch -> + return experiments?.withExperiment(FeatureId.DEFAULT_BROWSER) { experimentBranch -> (experimentBranch == ExperimentBranch.DEFAULT_BROWSER_SETTINGS_MENU) } == true } 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 b7c29857de..d838c9ebd5 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -34,7 +34,7 @@ import org.mozilla.fenix.components.settings.counterPreference import org.mozilla.fenix.components.settings.featureFlagPreference import org.mozilla.fenix.components.toolbar.ToolbarPosition import org.mozilla.fenix.experiments.ExperimentBranch -import org.mozilla.fenix.experiments.Experiments +import org.mozilla.fenix.experiments.FeatureId import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.getPreferenceKey import org.mozilla.fenix.ext.withExperiment @@ -312,10 +312,10 @@ class Settings(private val appContext: Context) : PreferencesHolder { val browsers = BrowsersCache.all(appContext) val experiments = appContext.components.analytics.experiments val isExperimentBranch = - experiments.withExperiment(Experiments.DEFAULT_BROWSER) { experimentBranch -> + experiments.withExperiment(FeatureId.DEFAULT_BROWSER) { experimentBranch -> (experimentBranch == ExperimentBranch.DEFAULT_BROWSER_NEW_TAB_BANNER) } - return isExperimentBranch && + return isExperimentBranch == true && !userDismissedExperimentCard && !browsers.isFirefoxDefaultBrowser && numberOfAppLaunches > APP_LAUNCHES_TO_SHOW_DEFAULT_BROWSER_CARD diff --git a/app/src/main/res/raw/initial_experiments.json b/app/src/main/res/raw/initial_experiments.json new file mode 100644 index 0000000000..268c73f0e3 --- /dev/null +++ b/app/src/main/res/raw/initial_experiments.json @@ -0,0 +1,3 @@ +{ + "data": [] +}