mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-09 19:10:42 +00:00
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).
This commit is contained in:
parent
4851bf7545
commit
ab678a21ff
236
app/src/debug/res/raw/initial_experiments.json
Normal file
236
app/src/debug/res/raw/initial_experiments.json
Normal file
@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -9,7 +9,7 @@ import android.os.Build
|
|||||||
import mozilla.components.lib.dataprotect.SecurePrefsReliabilityExperiment
|
import mozilla.components.lib.dataprotect.SecurePrefsReliabilityExperiment
|
||||||
import mozilla.components.service.nimbus.NimbusApi
|
import mozilla.components.service.nimbus.NimbusApi
|
||||||
import org.mozilla.fenix.experiments.ExperimentBranch
|
import org.mozilla.fenix.experiments.ExperimentBranch
|
||||||
import org.mozilla.fenix.experiments.Experiments
|
import org.mozilla.fenix.experiments.FeatureId
|
||||||
import org.mozilla.fenix.ext.withExperiment
|
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+
|
// The Android Keystore is used to secure the shared prefs only on API 23+
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
// These tests should run only if the experiment is live
|
// 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.
|
// .. and this device is not in the control group.
|
||||||
if (experimentBranch == ExperimentBranch.TREATMENT) {
|
if (experimentBranch == ExperimentBranch.TREATMENT) {
|
||||||
SecurePrefsReliabilityExperiment(appContext)()
|
SecurePrefsReliabilityExperiment(appContext)()
|
||||||
|
@ -41,7 +41,7 @@ import org.mozilla.fenix.R
|
|||||||
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
||||||
import org.mozilla.fenix.components.accounts.FenixAccountManager
|
import org.mozilla.fenix.components.accounts.FenixAccountManager
|
||||||
import org.mozilla.fenix.experiments.ExperimentBranch
|
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.asActivity
|
||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
import org.mozilla.fenix.ext.settings
|
import org.mozilla.fenix.ext.settings
|
||||||
@ -632,7 +632,7 @@ open class DefaultToolbarMenu(
|
|||||||
val experiments = context.components.analytics.experiments
|
val experiments = context.components.analytics.experiments
|
||||||
val browsers = BrowsersCache.all(context)
|
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 &&
|
if (experimentBranch == ExperimentBranch.DEFAULT_BROWSER_TOOLBAR_MENU &&
|
||||||
!browsers.isFirefoxDefaultBrowser
|
!browsers.isFirefoxDefaultBrowser
|
||||||
) {
|
) {
|
||||||
|
@ -4,14 +4,23 @@
|
|||||||
|
|
||||||
package org.mozilla.fenix.experiments
|
package org.mozilla.fenix.experiments
|
||||||
|
|
||||||
class Experiments {
|
/**
|
||||||
companion object {
|
* Enums to identify features in the app. These will likely grow and shrink depending
|
||||||
const val A_A_NIMBUS_VALIDATION = "fenix-nimbus-validation-v3"
|
* on the experiments we want to perform.
|
||||||
const val ANDROID_KEYSTORE = "fenix-android-keystore"
|
*
|
||||||
const val DEFAULT_BROWSER = "fenix-default-browser"
|
* @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 {
|
class ExperimentBranch {
|
||||||
companion object {
|
companion object {
|
||||||
const val TREATMENT = "treatment"
|
const val TREATMENT = "treatment"
|
||||||
|
@ -15,6 +15,7 @@ import mozilla.components.service.nimbus.NimbusDisabled
|
|||||||
import mozilla.components.service.nimbus.NimbusServerSettings
|
import mozilla.components.service.nimbus.NimbusServerSettings
|
||||||
import mozilla.components.support.base.log.logger.Logger
|
import mozilla.components.support.base.log.logger.Logger
|
||||||
import org.mozilla.fenix.BuildConfig
|
import org.mozilla.fenix.BuildConfig
|
||||||
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.components.isSentryEnabled
|
import org.mozilla.fenix.components.isSentryEnabled
|
||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
import org.mozilla.fenix.ext.settings
|
import org.mozilla.fenix.ext.settings
|
||||||
@ -66,6 +67,10 @@ fun createNimbus(context: Context, url: String?): NimbusApi =
|
|||||||
globalUserParticipation = enabled
|
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
|
// 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
|
// 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.
|
// the same thing throughout the session. This call does its work on the db thread.
|
||||||
|
@ -5,38 +5,98 @@
|
|||||||
package org.mozilla.fenix.ext
|
package org.mozilla.fenix.ext
|
||||||
|
|
||||||
import mozilla.components.service.nimbus.NimbusApi
|
import mozilla.components.service.nimbus.NimbusApi
|
||||||
import mozilla.components.support.base.log.logger.Logger
|
import org.mozilla.experiments.nimbus.Variables
|
||||||
import org.mozilla.fenix.FeatureFlags
|
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
|
* If we're not enrolled in the experiment, or the experiment is not valid then the transform
|
||||||
* is passed a `null`.
|
* is passed a `null`.
|
||||||
*/
|
*/
|
||||||
@Suppress("TooGenericExceptionCaught")
|
fun <T> NimbusApi.withExperiment(featureId: FeatureId, transform: (String?) -> T): T {
|
||||||
fun <T> NimbusApi.withExperiment(experimentId: String, transform: (String?) -> T): T {
|
return transform(getExperimentBranch(featureId.jsonName))
|
||||||
val branch = if (FeatureFlags.nimbusExperiments) {
|
|
||||||
try {
|
|
||||||
getExperimentBranch(experimentId)
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
Logger.error("Failed to getExperimentBranch($experimentId)", e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
return transform(branch)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 `mozilla.components.service.nimbus.NimbusApi.getExperimentBranch`.
|
* Short-hand for ` org.mozilla.experiments.nimbus.NimbusApi.getExperimentBranch`.
|
||||||
*/
|
*/
|
||||||
fun NimbusApi.withExperiment(experimentId: String) =
|
fun NimbusApi.withExperiment(featureId: FeatureId) =
|
||||||
this.withExperiment(experimentId, ::identity)
|
getExperimentBranch(featureId.jsonName)
|
||||||
|
|
||||||
private fun <T> identity(value: T) = value
|
/**
|
||||||
|
* 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)`.
|
||||||
|
*
|
||||||
|
* 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 <T> NimbusApi.withVariables(featureId: FeatureId, sendExposureEvent: Boolean = true, transform: (Variables) -> T) =
|
||||||
|
transform(getVariables(featureId, sendExposureEvent))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
@ -27,11 +27,10 @@ import org.mozilla.fenix.FeatureFlags
|
|||||||
import org.mozilla.fenix.FeatureFlags.tabsTrayRewrite
|
import org.mozilla.fenix.FeatureFlags.tabsTrayRewrite
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.components.accounts.FenixAccountManager
|
import org.mozilla.fenix.components.accounts.FenixAccountManager
|
||||||
import org.mozilla.fenix.experiments.ExperimentBranch
|
import org.mozilla.fenix.experiments.FeatureId
|
||||||
import org.mozilla.fenix.experiments.Experiments
|
|
||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
|
import org.mozilla.fenix.ext.getVariables
|
||||||
import org.mozilla.fenix.ext.settings
|
import org.mozilla.fenix.ext.settings
|
||||||
import org.mozilla.fenix.ext.withExperiment
|
|
||||||
import org.mozilla.fenix.theme.ThemeManager
|
import org.mozilla.fenix.theme.ThemeManager
|
||||||
import org.mozilla.fenix.whatsnew.WhatsNew
|
import org.mozilla.fenix.whatsnew.WhatsNew
|
||||||
|
|
||||||
@ -142,23 +141,9 @@ class HomeMenu(
|
|||||||
onItemTapped.invoke(Item.Bookmarks)
|
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(
|
val historyItem = BrowserMenuImageText(
|
||||||
context.getString(R.string.library_history),
|
context.getString(R.string.library_history),
|
||||||
historyIcon,
|
R.drawable.ic_history,
|
||||||
primaryTextColor
|
primaryTextColor
|
||||||
) {
|
) {
|
||||||
onItemTapped.invoke(Item.History)
|
onItemTapped.invoke(Item.History)
|
||||||
@ -172,9 +157,11 @@ class HomeMenu(
|
|||||||
onItemTapped.invoke(Item.Extensions)
|
onItemTapped.invoke(Item.Extensions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use nimbus to set the icon and title.
|
||||||
|
val variables = experiments.getVariables(FeatureId.NIMBUS_VALIDATION)
|
||||||
val settingsItem = BrowserMenuImageText(
|
val settingsItem = BrowserMenuImageText(
|
||||||
context.getString(R.string.browser_menu_settings),
|
variables.getText("settings-title") ?: context.getString(R.string.browser_menu_settings),
|
||||||
R.drawable.ic_settings,
|
variables.getDrawableResource("settings-icon") ?: R.drawable.ic_settings,
|
||||||
primaryTextColor
|
primaryTextColor
|
||||||
) {
|
) {
|
||||||
onItemTapped.invoke(Item.Settings)
|
onItemTapped.invoke(Item.Settings)
|
||||||
@ -252,23 +239,9 @@ class HomeMenu(
|
|||||||
onItemTapped.invoke(Item.Bookmarks)
|
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(
|
val historyItem = BrowserMenuImageText(
|
||||||
context.getString(R.string.library_history),
|
context.getString(R.string.library_history),
|
||||||
historyIcon,
|
R.drawable.ic_history,
|
||||||
primaryTextColor
|
primaryTextColor
|
||||||
) {
|
) {
|
||||||
onItemTapped.invoke(Item.History)
|
onItemTapped.invoke(Item.History)
|
||||||
@ -310,9 +283,11 @@ class HomeMenu(
|
|||||||
onItemTapped.invoke(Item.Help)
|
onItemTapped.invoke(Item.Help)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use nimbus to set the icon and title.
|
||||||
|
val variables = experiments.getVariables(FeatureId.NIMBUS_VALIDATION)
|
||||||
val settingsItem = BrowserMenuImageText(
|
val settingsItem = BrowserMenuImageText(
|
||||||
context.getString(R.string.browser_menu_settings),
|
variables.getText("settings-title") ?: context.getString(R.string.browser_menu_settings),
|
||||||
R.drawable.ic_settings,
|
variables.getDrawableResource("settings-icon") ?: R.drawable.ic_settings,
|
||||||
primaryTextColor
|
primaryTextColor
|
||||||
) {
|
) {
|
||||||
onItemTapped.invoke(Item.Settings)
|
onItemTapped.invoke(Item.Settings)
|
||||||
|
@ -79,7 +79,7 @@ class NimbusBranchesFragment : Fragment() {
|
|||||||
try {
|
try {
|
||||||
val experiments = requireContext().components.analytics.experiments
|
val experiments = requireContext().components.analytics.experiments
|
||||||
val branches = experiments.getExperimentBranches(args.experimentId) ?: emptyList()
|
val branches = experiments.getExperimentBranches(args.experimentId) ?: emptyList()
|
||||||
val selectedBranch = experiments.withExperiment(args.experimentId) ?: ""
|
val selectedBranch = experiments.getExperimentBranch(args.experimentId) ?: ""
|
||||||
|
|
||||||
nimbusBranchesStore.dispatch(
|
nimbusBranchesStore.dispatch(
|
||||||
NimbusBranchesAction.UpdateBranches(
|
NimbusBranchesAction.UpdateBranches(
|
||||||
|
@ -42,7 +42,7 @@ import org.mozilla.fenix.HomeActivity
|
|||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
import org.mozilla.fenix.components.metrics.Event
|
||||||
import org.mozilla.fenix.experiments.ExperimentBranch
|
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.application
|
||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
import org.mozilla.fenix.ext.getPreferenceKey
|
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.requireComponents
|
||||||
import org.mozilla.fenix.ext.settings
|
import org.mozilla.fenix.ext.settings
|
||||||
import org.mozilla.fenix.ext.REQUEST_CODE_BROWSER_ROLE
|
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.openSetDefaultBrowserOption
|
||||||
import org.mozilla.fenix.ext.showToolbar
|
import org.mozilla.fenix.ext.showToolbar
|
||||||
import org.mozilla.fenix.ext.withExperiment
|
import org.mozilla.fenix.ext.withExperiment
|
||||||
@ -161,7 +162,13 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.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
|
// 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.
|
// 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 {
|
private fun isDefaultBrowserExperimentBranch(): Boolean {
|
||||||
val experiments = context?.components?.analytics?.experiments
|
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)
|
(experimentBranch == ExperimentBranch.DEFAULT_BROWSER_SETTINGS_MENU)
|
||||||
} == true
|
} == true
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ import org.mozilla.fenix.components.settings.counterPreference
|
|||||||
import org.mozilla.fenix.components.settings.featureFlagPreference
|
import org.mozilla.fenix.components.settings.featureFlagPreference
|
||||||
import org.mozilla.fenix.components.toolbar.ToolbarPosition
|
import org.mozilla.fenix.components.toolbar.ToolbarPosition
|
||||||
import org.mozilla.fenix.experiments.ExperimentBranch
|
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.components
|
||||||
import org.mozilla.fenix.ext.getPreferenceKey
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
import org.mozilla.fenix.ext.withExperiment
|
import org.mozilla.fenix.ext.withExperiment
|
||||||
@ -312,10 +312,10 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
|||||||
val browsers = BrowsersCache.all(appContext)
|
val browsers = BrowsersCache.all(appContext)
|
||||||
val experiments = appContext.components.analytics.experiments
|
val experiments = appContext.components.analytics.experiments
|
||||||
val isExperimentBranch =
|
val isExperimentBranch =
|
||||||
experiments.withExperiment(Experiments.DEFAULT_BROWSER) { experimentBranch ->
|
experiments.withExperiment(FeatureId.DEFAULT_BROWSER) { experimentBranch ->
|
||||||
(experimentBranch == ExperimentBranch.DEFAULT_BROWSER_NEW_TAB_BANNER)
|
(experimentBranch == ExperimentBranch.DEFAULT_BROWSER_NEW_TAB_BANNER)
|
||||||
}
|
}
|
||||||
return isExperimentBranch &&
|
return isExperimentBranch == true &&
|
||||||
!userDismissedExperimentCard &&
|
!userDismissedExperimentCard &&
|
||||||
!browsers.isFirefoxDefaultBrowser &&
|
!browsers.isFirefoxDefaultBrowser &&
|
||||||
numberOfAppLaunches > APP_LAUNCHES_TO_SHOW_DEFAULT_BROWSER_CARD
|
numberOfAppLaunches > APP_LAUNCHES_TO_SHOW_DEFAULT_BROWSER_CARD
|
||||||
|
3
app/src/main/res/raw/initial_experiments.json
Normal file
3
app/src/main/res/raw/initial_experiments.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"data": []
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user