forked from mirrors/gecko-dev
		
	In cases, where the caller is looking for the locale to be used for JS Intl API, we can now replace it with `undefined` which causes JS Intl API to use the default locale which since bug 1346674 is resolved to the app locale. This allows us to remove a lot of calls for the app locale. The remaining ones are split between `AsBCP47` and `AsLangTag`. Here, the `AsLangTag` is used, as described in the API docs, for cases where the language string is used for localization purposes, such as language negotaition matching to our language resources etc. `AsBCP47` is used when the returned value is handed over to ICU API. MozReview-Commit-ID: DzmFEUvMq3N --HG-- extra : rebase_source : 513ed31d995864939aa893e73c81ffdf591a6617
		
			
				
	
	
		
			431 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			431 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| .. _experiments_manifests:
 | |
| 
 | |
| =====================
 | |
| Experiments Manifests
 | |
| =====================
 | |
| 
 | |
| *Experiments Manifests* are documents that describe the set of active
 | |
| experiments a client may run.
 | |
| 
 | |
| *Experiments Manifests* are fetched periodically by clients. When
 | |
| fetched, clients look at the experiments within the manifest and
 | |
| determine which experiments are applicable. If an experiment is
 | |
| applicable, the client may download and start the experiment.
 | |
| 
 | |
| Manifest Format
 | |
| ===============
 | |
| 
 | |
| Manifests are JSON documents where the main element is an object.
 | |
| 
 | |
| The *schema* of the object is versioned and defined by the presence
 | |
| of a top-level ``version`` property, whose integer value is the
 | |
| schema version used by that manifest. Each version is documented
 | |
| in the sections below.
 | |
| 
 | |
| Version 1
 | |
| ---------
 | |
| 
 | |
| Version 1 is the original manifest format.
 | |
| 
 | |
| The following properties may exist in the root object:
 | |
| 
 | |
| experiments
 | |
|    An array of objects describing candidate experiments. The format of
 | |
|    these objects is documented below.
 | |
| 
 | |
|    An array is used to create an explicit priority of experiments.
 | |
|    Experiments listed at the beginning of the array take priority over
 | |
|    experiments that follow.
 | |
| 
 | |
| Experiments Objects
 | |
| ^^^^^^^^^^^^^^^^^^^
 | |
| 
 | |
| Each object in the ``experiments`` array may contain the following
 | |
| properties:
 | |
| 
 | |
| id
 | |
|    (required) String identifier of this experiment. The identifier should
 | |
|    be treated as opaque by clients. It is used to uniquely identify an
 | |
|    experiment for all of time.
 | |
| 
 | |
| xpiURL
 | |
|    (required) String URL of the XPI that implements this experiment.
 | |
| 
 | |
|    If the experiment is activated, the client will download and install this
 | |
|    XPI.
 | |
| 
 | |
| xpiHash
 | |
|    (required) String hash of the XPI that implements this experiment.
 | |
| 
 | |
|    The value is composed of a hash identifier followed by a colon
 | |
|    followed by the hash value. e.g.
 | |
|    `sha1:f677428b9172e22e9911039aef03f3736e7f78a7`. `sha1` and `sha256`
 | |
|    are the two supported hashing mechanisms. The hash value is the hex
 | |
|    encoding of the binary hash.
 | |
| 
 | |
|    When the client downloads the XPI for the experiment, it should compare
 | |
|    the hash of that XPI against this value. If the hashes don't match,
 | |
|    the client should not install the XPI.
 | |
| 
 | |
|    Clients may also use this hash as a means of determining when an
 | |
|    experiment's XPI has changed and should be refreshed.
 | |
| 
 | |
| startTime
 | |
|    Integer seconds since UNIX epoch that this experiment should
 | |
|    start. Clients should not start an experiment if *now()* is less than
 | |
|    this value.
 | |
| 
 | |
| maxStartTime
 | |
|    (optional) Integer seconds since UNIX epoch after which this experiment
 | |
|    should no longer start.
 | |
| 
 | |
|    Some experiments may wish to impose hard deadlines after which no new
 | |
|    clients should activate the experiment. This property may be used to
 | |
|    facilitate that.
 | |
| 
 | |
| endTime
 | |
|    Integer seconds since UNIX epoch after which this experiment
 | |
|    should no longer run. Clients should cease an experiment when the current
 | |
|    time is beyond this value.
 | |
| 
 | |
| maxActiveSeconds
 | |
|    Integer seconds defining the max wall time this experiment should be
 | |
|    active for.
 | |
| 
 | |
|    The client should deactivate the experiment this many seconds after
 | |
|    initial activation.
 | |
| 
 | |
|    This value only involves wall time, not browser activity or session time.
 | |
| 
 | |
| appName
 | |
|    Array of application names this experiment should run on.
 | |
| 
 | |
|    An application name comes from ``nsIXULAppInfo.name``. It is a value
 | |
|    like ``Firefox``, ``Fennec``, or `B2G`.
 | |
| 
 | |
|    The client should compare its application name against the members of
 | |
|    this array. If a match is found, the experiment is applicable.
 | |
| 
 | |
| minVersion
 | |
|    (optional) String version number of the minimum application version this
 | |
|    experiment should run on.
 | |
| 
 | |
|    A version number is something like ``27.0.0`` or ``28``.
 | |
| 
 | |
|    The client should compare its version number to this value. If the client's
 | |
|    version is greater or equal to this version (using a version-aware comparison
 | |
|    function), the experiment is applicable.
 | |
| 
 | |
|    If this is not specified, there is no lower bound to versions this
 | |
|    experiment should run on.
 | |
| 
 | |
| maxVersion
 | |
|    (optional) String version number of the maximum application version this
 | |
|    experiment should run on.
 | |
| 
 | |
|    This is similar to ``minVersion`` except it sets the upper bound for
 | |
|    application versions.
 | |
| 
 | |
|    If the client's version is less than or equal to this version, the
 | |
|    experiment is applicable.
 | |
| 
 | |
|    If this is not specified, there is no upper bound to versions this
 | |
|    experiment should run on.
 | |
| 
 | |
| version
 | |
|    (optional) Array of application versions this experiment should run on.
 | |
| 
 | |
|    This is similar to ``minVersion`` and ``maxVersion`` except only a
 | |
|    whitelisted set of specific versions are allowed.
 | |
| 
 | |
|    The client should compare its version to members of this array. If a match
 | |
|    is found, the experiment is applicable.
 | |
| 
 | |
| minBuildID
 | |
|    (optional) String minimum Build ID this experiment should run on.
 | |
| 
 | |
|    Build IDs are values like ``201402261424``.
 | |
| 
 | |
|    The client should perform a string comparison of its Build ID against this
 | |
|    value. If its value is greater than or equal to this value, the experiment
 | |
|    is applicable.
 | |
| 
 | |
| maxBuildID
 | |
|    (optional) String maximum Build ID this experiment should run on.
 | |
| 
 | |
|    This is similar to ``minBuildID`` except it sets the upper bound
 | |
|    for Build IDs.
 | |
| 
 | |
|    The client should perform a string comparison of its Build ID against
 | |
|    this value. If its value is less than or equal to this value, the
 | |
|    experiment is applicable.
 | |
| 
 | |
| buildIDs
 | |
|    (optional) Array of Build IDs this experiment should run on.
 | |
| 
 | |
|    This is similar to ``minBuildID`` and ``maxBuildID`` except only a
 | |
|    whitelisted set of Build IDs are considered.
 | |
| 
 | |
|    The client should compare its Build ID to members of this array. If a
 | |
|    match is found, the experiment is applicable.
 | |
| 
 | |
| os
 | |
|    (optional) Array of operating system identifiers this experiment should
 | |
|    run on.
 | |
| 
 | |
|    Values for this array come from ``nsIXULRuntime.OS``.
 | |
| 
 | |
|    The client will compare its operating system identifier to members
 | |
|    of this array. If a match is found, the experiment is applicable to the
 | |
|    client.
 | |
| 
 | |
| channel
 | |
|    (optional) Array of release channel identifiers this experiment should run
 | |
|    on.
 | |
| 
 | |
|    The client will compare its channel to members of this array. If a match
 | |
|    is found, the experiment is applicable.
 | |
| 
 | |
|    If this property is not defined, the client should assume the experiment
 | |
|    is to run on all channels.
 | |
| 
 | |
| locale
 | |
|    (optional) Array of locale identifiers this experiment should run on.
 | |
| 
 | |
|    A locale identifier is a string like ``en-US`` or ``zh-CN`` and is
 | |
|    obtained by looking at
 | |
|    ``LocaleService.getAppLocaleAsLangTag()``.
 | |
|    For infamous `ja-JP-mac` case, this will return it in
 | |
|    the language tag form (`ja-JP-mac`).
 | |
| 
 | |
|    The client should compare its locale identifier to members of this array.
 | |
|    If a match is found, the experiment is applicable.
 | |
| 
 | |
|    If this property is not defined, the client should assume the experiment
 | |
|    is to run on all locales.
 | |
| 
 | |
| sample
 | |
|    (optional) Decimal number indicating the sampling rate for this experiment.
 | |
| 
 | |
|    This will contain a value between ``0.0`` and ``1.0``. The client should
 | |
|    generate a random decimal between ``0.0`` and ``1.0``. If the randomly
 | |
|    generated number is less than or equal to the value of this field, the
 | |
|    experiment is applicable.
 | |
| 
 | |
| disabled
 | |
|    (optional) Boolean value indicating whether an experiment is disabled.
 | |
| 
 | |
|    Normally, experiments are deactivated after a certain time has passed or
 | |
|    after the experiment itself determines it no longer needs to run (perhaps
 | |
|    it collected sufficient data already).
 | |
| 
 | |
|    This property serves as a backup mechanism to remotely disable an
 | |
|    experiment before it was scheduled to be disabled. It can be used to
 | |
|    kill experiments that are found to be doing wrong or bad things or that
 | |
|    aren't useful.
 | |
| 
 | |
|    If this property is not defined or is false, the client should assume
 | |
|    the experiment is active and a candidate for activation.
 | |
| 
 | |
| frozen
 | |
|    (optional) Boolean value indicating this experiment is frozen and no
 | |
|    longer accepting new enrollments.
 | |
| 
 | |
|    If a client sees a true value in this field, it should not attempt to
 | |
|    activate an experiment.
 | |
| 
 | |
| jsfilter
 | |
|     (optional) JavaScript code that will be evaluated to determine experiment
 | |
|     applicability.
 | |
| 
 | |
|     This property contains the string representation of JavaScript code that
 | |
|     will be evaluated in a sandboxed environment using JavaScript's
 | |
|     ``eval()``.
 | |
| 
 | |
|     The string is expected to contain the definition of a JavaScript function
 | |
|     ``filter(context)``. This function receives as its argument an object
 | |
|     holding application state. See the section below for the definition of
 | |
|     this object.
 | |
| 
 | |
|     The purpose of this property is to allow experiments to define complex
 | |
|     rules and logic for evaluating experiment applicability in a manner
 | |
|     that is privacy conscious and doesn't require the transmission of
 | |
|     excessive data.
 | |
| 
 | |
|     The return value of this filter indicates whether the experiment is
 | |
|     applicable. Functions should return true if the experiment is
 | |
|     applicable.
 | |
| 
 | |
|     If an experiment is not applicable, they should throw an Error whose
 | |
|     message contains the reason the experiment is not applicable. This
 | |
|     message may be logged and sent to remote servers, so it should not
 | |
|     contain private or otherwise sensitive data that wouldn't normally
 | |
|     be submitted.
 | |
| 
 | |
|     If a falsey (or undefined) value is returned, the client should
 | |
|     assume the experiment is not applicable.
 | |
| 
 | |
|     If this property is not defined, the client does not consider a custom
 | |
|     JavaScript filter function when determining whether an experiment is
 | |
|     applicable.
 | |
| 
 | |
| JavaScript Filter Context Objects
 | |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | |
| 
 | |
| The object passed to a ``jsfilter`` ``filter()`` function contains the
 | |
| following properties:
 | |
| 
 | |
| healthReportSubmissionEnabled
 | |
|    This property contains a boolean indicating whether Firefox Health
 | |
|    Report has its data submission flag enabled (whether Firefox Health
 | |
|    Report is sending data to remote servers).
 | |
| 
 | |
| healthReportPayload
 | |
|    This property contains the current Firefox Health Report payload.
 | |
| 
 | |
|    The payload format is documented at :ref:`healthreport_dataformat`.
 | |
| 
 | |
| telemetryPayload
 | |
|    This property contains the current Telemetry payload.
 | |
| 
 | |
| The evaluation sandbox for the JavaScript filters may be destroyed
 | |
| immediately after ``filter()`` returns. This function should not assume
 | |
| async code will finish.
 | |
| 
 | |
| Experiment Applicability and Client Behavior
 | |
| ============================================
 | |
| 
 | |
| The point of an experiment manifest is to define which experiments are
 | |
| available and where and how to run them. This section explains those
 | |
| rules in more detail.
 | |
| 
 | |
| Many of the properties in *Experiment Objects* are related to determining
 | |
| whether an experiment should run on a given client. This evaluation is
 | |
| performed client side.
 | |
| 
 | |
| 1. Multiple conditions in an experiment
 | |
| ---------------------------------------
 | |
| 
 | |
| If multiple conditions are defined for an experiment, the client should
 | |
| combine each condition with a logical *AND*: all conditions must be
 | |
| satisfied for an experiment to run. If one condition fails, the experiment
 | |
| is not applicable.
 | |
| 
 | |
| 2. Active experiment disappears from manifest
 | |
| ---------------------------------------------
 | |
| 
 | |
| If a specific experiment disappears from the manifest, the client should
 | |
| continue conducting an already-active experiment. Furthermore, the
 | |
| client should remember what the expiration events were for an experiment
 | |
| and honor them.
 | |
| 
 | |
| The rationale here is that we want to prevent an accidental deletion
 | |
| or temporary failure on the server to inadvertantly deactivate
 | |
| supposed-to-be-active experiments. We also don't want premature deletion
 | |
| of an experiment from the manifest to result in indefinite activation
 | |
| periods.
 | |
| 
 | |
| 3. Inactive experiment disappears from manifest
 | |
| -----------------------------------------------
 | |
| 
 | |
| If an inactive but scheduled-to-be-active experiment disappears from the
 | |
| manifest, the client should not activate the experiment.
 | |
| 
 | |
| If that experiment reappears in the manifest, the client should not
 | |
| treat that experiment any differently than any other new experiment. Put
 | |
| another way, the fact an inactive experiment disappears and then
 | |
| reappears should not be significant.
 | |
| 
 | |
| The rationale here is that server operators should have complete
 | |
| control of an inactive experiment up to it's go-live date.
 | |
| 
 | |
| 4. Re-evaluating applicability on manifest refresh
 | |
| --------------------------------------------------
 | |
| 
 | |
| When an experiment manifest is refreshed or updated, the client should
 | |
| re-evaluate the applicability of each experiment therein.
 | |
| 
 | |
| The rationale here is that the server may change the parameters of an
 | |
| experiment and want clients to pick those up.
 | |
| 
 | |
| 5. Activating a previously non-applicable experiment
 | |
| ----------------------------------------------------
 | |
| 
 | |
| If the conditions of an experiment change or the state of the client
 | |
| changes to allow an experiment to transition from previously
 | |
| non-applicable to applicable, the experiment should be activated.
 | |
| 
 | |
| For example, if a client is running version 28 and the experiment
 | |
| initially requires version 29 or above, the client will not mark the
 | |
| experiment as applicable. But if the client upgrades to version 29 or if
 | |
| the manifest is updated to require 28 or above, the experiment will
 | |
| become applicable.
 | |
| 
 | |
| 6. Deactivating a previously active experiment
 | |
| ----------------------------------------------
 | |
| 
 | |
| If the conditions of an experiment change or the state of the client
 | |
| changes and an active experiment is no longer applicable, that
 | |
| experiment should be deactivated.
 | |
| 
 | |
| 7. Calculation of sampling-based applicability
 | |
| ----------------------------------------------
 | |
| 
 | |
| For calculating sampling-based applicability, the client will associate
 | |
| a random value between ``0.0`` and ``1.0`` for each observed experiment
 | |
| ID. This random value will be generated the first time sampling
 | |
| applicability is evaluated. This random value will be persisted and used
 | |
| in future applicability evaluations for this experiment.
 | |
| 
 | |
| By saving and re-using the value, the client is able to reliably and
 | |
| consistently evaluate applicability, even if the sampling threshold
 | |
| in the manifest changes.
 | |
| 
 | |
| Clients should retain the randomly-generated sampling value for
 | |
| experiments that no longer appear in a manifest for a period of at least
 | |
| 30 days. The rationale is that if an experiment disappears and reappears
 | |
| from a manifest, the client will not have multiple opportunities to
 | |
| generate a random value that satisfies the sampling criteria.
 | |
| 
 | |
| 8. Incompatible version numbers
 | |
| -------------------------------
 | |
| 
 | |
| If a client receives a manifest with a version number that it doesn't
 | |
| recognize, it should ignore the manifest.
 | |
| 
 | |
| 9. Usage of old manifests
 | |
| -------------------------
 | |
| 
 | |
| If a client experiences an error fetching a manifest (server not
 | |
| available) or if the manifest is corrupt, not readable, or compatible,
 | |
| the client may use a previously-fetched (cached) manifest.
 | |
| 
 | |
| 10. Updating XPIs
 | |
| -----------------
 | |
| 
 | |
| If the URL or hash of an active experiment's XPI changes, the client
 | |
| should fetch the new XPI, uninstall the old XPI, and install the new
 | |
| XPI.
 | |
| 
 | |
| Examples
 | |
| ========
 | |
| 
 | |
| Here is an example manifest::
 | |
| 
 | |
|    {
 | |
|      "version": 1,
 | |
|      "experiments": [
 | |
|        {
 | |
|          "id": "da9d7f4f-f3f9-4f81-bacd-6f0626ffa360",
 | |
|          "xpiURL": "https://experiments.mozilla.org/foo.xpi",
 | |
|          "xpiHash": "sha1:cb1eb32b89d86d78b7326f416cf404548c5e0099",
 | |
|          "startTime": 1393000000,
 | |
|          "endTime": 1394000000,
 | |
|          "appName": ["Firefox", "Fennec"],
 | |
|          "minVersion": "28",
 | |
|          "maxVersion": "30",
 | |
|          "os": ["windows", "linux", "osx"],
 | |
|          "jsfilter": "function filter(context) { return context.healthReportEnabled; }"
 | |
|        }
 | |
|      ]
 | |
|    }
 |