зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset d402c8657d3f (bug 1699701) for failing newtab's activity-stream:AboutPreferences Feed and more. CLOSED TREE
This commit is contained in:
Родитель
480efa657d
Коммит
ebd583fd80
|
@ -19,7 +19,7 @@ const { PrivateBrowsingUtils } = ChromeUtils.import(
|
|||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.jsm",
|
||||
ExperimentFeature: "resource://nimbus/ExperimentAPI.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
|
@ -29,13 +29,23 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
|||
false
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "awExperimentFeature", () => {
|
||||
return new ExperimentFeature("aboutwelcome");
|
||||
});
|
||||
|
||||
// Note: newtab feature info is currently being loaded in PrefsFeed.jsm,
|
||||
// But we're recording exposure events here.
|
||||
XPCOMUtils.defineLazyGetter(this, "newtabExperimentFeature", () => {
|
||||
return new ExperimentFeature("newtab");
|
||||
});
|
||||
|
||||
class AboutNewTabChild extends JSWindowActorChild {
|
||||
handleEvent(event) {
|
||||
if (event.type == "DOMContentLoaded") {
|
||||
// If the separate about:welcome page is enabled, we can skip all of this,
|
||||
// since that mode doesn't load any of the Activity Stream bits.
|
||||
if (
|
||||
NimbusFeatures.aboutwelcome.isEnabled({ defaultValue: true }) &&
|
||||
awExperimentFeature.isEnabled({ defaultValue: true }) &&
|
||||
this.contentWindow.location.pathname.includes("welcome")
|
||||
) {
|
||||
return;
|
||||
|
@ -81,9 +91,8 @@ class AboutNewTabChild extends JSWindowActorChild {
|
|||
) {
|
||||
this.sendAsyncMessage("DefaultBrowserNotification");
|
||||
|
||||
// Note: newtab feature info is currently being loaded in PrefsFeed.jsm,
|
||||
// But we're recording exposure events here.
|
||||
NimbusFeatures.newtab.recordExposureEvent();
|
||||
// Send an exposure event to record when we have an experiment active
|
||||
newtabExperimentFeature.recordExposureEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
DownloadsCommon: "resource:///modules/DownloadsCommon.jsm",
|
||||
DownloadUtils: "resource://gre/modules/DownloadUtils.jsm",
|
||||
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.jsm",
|
||||
ExtensionsUI: "resource:///modules/ExtensionsUI.jsm",
|
||||
HomePage: "resource:///modules/HomePage.jsm",
|
||||
LightweightThemeConsumer:
|
||||
|
@ -614,6 +613,15 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
|||
false
|
||||
);
|
||||
|
||||
/* Import aboutWelcomeFeature from Nimbus Experiment API
|
||||
to access experiment values */
|
||||
XPCOMUtils.defineLazyGetter(this, "aboutWelcomeFeature", () => {
|
||||
const { ExperimentFeature } = ChromeUtils.import(
|
||||
"resource://nimbus/ExperimentAPI.jsm"
|
||||
);
|
||||
return new ExperimentFeature("aboutwelcome");
|
||||
});
|
||||
|
||||
customElements.setElementCreationCallback("translation-notification", () => {
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://browser/content/translation-notification.js",
|
||||
|
@ -2224,7 +2232,7 @@ var gBrowserInit = {
|
|||
// property set to true, if yes remove focus from urlbar for about:welcome
|
||||
const aboutWelcomeSkipUrlBarFocus =
|
||||
uriToLoad == "about:welcome" &&
|
||||
NimbusFeatures.aboutwelcome.getValue()?.skipFocus;
|
||||
aboutWelcomeFeature.getValue()?.skipFocus;
|
||||
|
||||
if (
|
||||
(isBlankPageURL(uriToLoad) && !aboutWelcomeSkipUrlBarFocus) ||
|
||||
|
|
|
@ -41,8 +41,11 @@ const { E10SUtils } = ChromeUtils.import(
|
|||
"resource://gre/modules/E10SUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.jsm",
|
||||
XPCOMUtils.defineLazyGetter(this, "awExperimentFeature", () => {
|
||||
const { ExperimentFeature } = ChromeUtils.import(
|
||||
"resource://nimbus/ExperimentAPI.jsm"
|
||||
);
|
||||
return new ExperimentFeature("aboutwelcome");
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -446,7 +449,7 @@ class BaseAboutNewTabService {
|
|||
*/
|
||||
|
||||
if (
|
||||
NimbusFeatures.aboutwelcome.isEnabled({
|
||||
awExperimentFeature.isEnabled({
|
||||
defaultValue: true,
|
||||
sendExposureEvent: true,
|
||||
})
|
||||
|
|
|
@ -17,7 +17,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
TippyTopProvider: "resource://activity-stream/lib/TippyTopProvider.jsm",
|
||||
AboutWelcomeDefaults:
|
||||
"resource://activity-stream/aboutwelcome/lib/AboutWelcomeDefaults.jsm",
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
|
@ -27,6 +26,13 @@ XPCOMUtils.defineLazyGetter(this, "log", () => {
|
|||
return new Logger("AboutWelcomeChild");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "aboutWelcomeFeature", () => {
|
||||
const { ExperimentFeature } = ChromeUtils.import(
|
||||
"resource://nimbus/ExperimentAPI.jsm"
|
||||
);
|
||||
return new ExperimentFeature("aboutwelcome");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "tippyTopProvider", () =>
|
||||
(async () => {
|
||||
const provider = new TippyTopProvider();
|
||||
|
@ -216,7 +222,7 @@ class AboutWelcomeChild extends JSWindowActorChild {
|
|||
ExperimentAPI.getExperimentMetaData({
|
||||
featureId: "aboutwelcome",
|
||||
}) || {};
|
||||
let featureConfig = NimbusFeatures.aboutwelcome.getValue() || {};
|
||||
let featureConfig = aboutWelcomeFeature.getValue() || {};
|
||||
|
||||
if (experimentMetadata?.slug) {
|
||||
log.debug(
|
||||
|
|
|
@ -14,8 +14,11 @@ const { actionTypes: at, actionCreators: ac } = ChromeUtils.import(
|
|||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const PREFERENCES_LOADED_EVENT = "home-pane-loaded";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.jsm",
|
||||
XPCOMUtils.defineLazyGetter(this, "aboutNewTabFeature", () => {
|
||||
const { ExperimentFeature } = ChromeUtils.import(
|
||||
"resource://nimbus/ExperimentAPI.jsm"
|
||||
);
|
||||
return new ExperimentFeature("newtab");
|
||||
});
|
||||
|
||||
// These "section" objects are formatted in a way to be similar to the ones from
|
||||
|
@ -148,7 +151,7 @@ this.AboutPreferences = class AboutPreferences {
|
|||
sections = this.handleDiscoverySettings(sections);
|
||||
}
|
||||
|
||||
const featureConfig = NimbusFeatures.newtab.getValue() || {};
|
||||
const featureConfig = aboutNewTabFeature.getValue() || {};
|
||||
|
||||
this.renderPreferences(window, [
|
||||
...PREFS_BEFORE_SECTIONS(featureConfig),
|
||||
|
|
|
@ -14,13 +14,31 @@ const { Prefs } = ChromeUtils.import(
|
|||
);
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.jsm",
|
||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
|
||||
Region: "resource://gre/modules/Region.jsm",
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm"
|
||||
);
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"AppConstants",
|
||||
"resource://gre/modules/AppConstants.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "aboutNewTabFeature", () => {
|
||||
const { ExperimentFeature } = ChromeUtils.import(
|
||||
"resource://nimbus/ExperimentAPI.jsm"
|
||||
);
|
||||
return new ExperimentFeature("newtab");
|
||||
});
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"Region",
|
||||
"resource://gre/modules/Region.jsm"
|
||||
);
|
||||
|
||||
this.PrefsFeed = class PrefsFeed {
|
||||
constructor(prefMap) {
|
||||
this._prefMap = prefMap;
|
||||
|
@ -65,7 +83,7 @@ this.PrefsFeed = class PrefsFeed {
|
|||
* Handler for when experiment data updates.
|
||||
*/
|
||||
onExperimentUpdated(event, reason) {
|
||||
const value = NimbusFeatures.newtab.getValue() || {};
|
||||
const value = aboutNewTabFeature.getValue() || {};
|
||||
this.store.dispatch(
|
||||
ac.BroadcastToContent({
|
||||
type: at.PREF_CHANGED,
|
||||
|
@ -79,7 +97,7 @@ this.PrefsFeed = class PrefsFeed {
|
|||
|
||||
init() {
|
||||
this._prefs.observeBranch(this);
|
||||
NimbusFeatures.newtab.onUpdate(this.onExperimentUpdated);
|
||||
aboutNewTabFeature.onUpdate(this.onExperimentUpdated);
|
||||
|
||||
this._storage = this.store.dbStorage.getDbTable("sectionPrefs");
|
||||
|
||||
|
@ -154,7 +172,7 @@ this.PrefsFeed = class PrefsFeed {
|
|||
});
|
||||
|
||||
// Add experiment values and default values
|
||||
values.featureConfig = NimbusFeatures.newtab.getValue() || {};
|
||||
values.featureConfig = aboutNewTabFeature.getValue() || {};
|
||||
this._setBoolPref(values, "logowordmark.alwaysVisible", false);
|
||||
this._setBoolPref(values, "feeds.section.topstories", false);
|
||||
this._setBoolPref(values, "discoverystream.enabled", false);
|
||||
|
@ -191,7 +209,7 @@ this.PrefsFeed = class PrefsFeed {
|
|||
|
||||
removeListeners() {
|
||||
this._prefs.ignoreBranch(this);
|
||||
NimbusFeatures.newtab.off(this.onExperimentUpdated);
|
||||
aboutNewTabFeature.off(this.onExperimentUpdated);
|
||||
if (this.geo === "") {
|
||||
Services.obs.removeObserver(this, Region.REGION_TOPIC);
|
||||
}
|
||||
|
|
|
@ -17,9 +17,18 @@ const { getDefaultOptions } = ChromeUtils.import(
|
|||
"resource://activity-stream/lib/ActivityStreamStorage.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.jsm",
|
||||
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "aboutNewTabFeature", () => {
|
||||
const { ExperimentFeature } = ChromeUtils.import(
|
||||
"resource://nimbus/ExperimentAPI.jsm"
|
||||
);
|
||||
|
||||
return new ExperimentFeature("newtab");
|
||||
});
|
||||
|
||||
/*
|
||||
|
@ -205,7 +214,7 @@ const SectionsManager = {
|
|||
sections: new Map(),
|
||||
async init(prefs = {}, storage) {
|
||||
this._storage = storage;
|
||||
const featureConfig = NimbusFeatures.newtab.getValue() || {};
|
||||
const featureConfig = aboutNewTabFeature.getValue() || {};
|
||||
|
||||
for (const feedPrefName of Object.keys(BUILT_IN_SECTIONS(featureConfig))) {
|
||||
const optionsPrefName = `${feedPrefName}.options`;
|
||||
|
@ -254,7 +263,7 @@ const SectionsManager = {
|
|||
async addBuiltInSection(feedPrefName, optionsPrefValue = "{}") {
|
||||
let options;
|
||||
let storedPrefs;
|
||||
const featureConfig = NimbusFeatures.newtab.getValue() || {};
|
||||
const featureConfig = aboutNewTabFeature.getValue() || {};
|
||||
try {
|
||||
options = JSON.parse(optionsPrefValue);
|
||||
} catch (e) {
|
||||
|
|
|
@ -27,7 +27,7 @@ ChromeUtils.defineModuleGetter(
|
|||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"NimbusFeatures",
|
||||
"ExperimentFeature",
|
||||
"resource://nimbus/ExperimentAPI.jsm"
|
||||
);
|
||||
|
||||
|
@ -134,9 +134,10 @@ var gSearchPane = {
|
|||
this._updateSuggestionCheckboxes();
|
||||
this._showAddEngineButton();
|
||||
this._updateQuickSuggest = this._updateQuickSuggest.bind(this);
|
||||
NimbusFeatures.urlbar.onUpdate(this._updateQuickSuggest);
|
||||
this.urlbarExperimentFeature = new ExperimentFeature("urlbar");
|
||||
this.urlbarExperimentFeature.onUpdate(this._updateQuickSuggest);
|
||||
window.addEventListener("unload", () => {
|
||||
NimbusFeatures.urlbar.off(this._updateQuickSuggest);
|
||||
this.urlbarExperimentFeature.off(this._updateQuickSuggest);
|
||||
});
|
||||
this._updateQuickSuggest(true);
|
||||
},
|
||||
|
@ -248,7 +249,7 @@ var gSearchPane = {
|
|||
let container = document.getElementById("showQuickSuggestContainer");
|
||||
let desc = document.getElementById("searchSuggestionsDesc");
|
||||
|
||||
if (!NimbusFeatures.urlbar.getValue().quickSuggestEnabled) {
|
||||
if (!this.urlbarExperimentFeature.getValue().quickSuggestEnabled) {
|
||||
// The experiment is not enabled. This is the default, so to avoid
|
||||
// accidentally messing anything up, only modify the doc if we're being
|
||||
// called due to a change in the experiment enabled status.
|
||||
|
|
|
@ -13,7 +13,6 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
CONTEXTUAL_SERVICES_PING_TYPES:
|
||||
"resource:///modules/PartnerLinkAttribution.jsm",
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.jsm",
|
||||
PartnerLinkAttribution: "resource:///modules/PartnerLinkAttribution.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm",
|
||||
|
@ -23,6 +22,13 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
UrlbarUtils: "resource:///modules/UrlbarUtils.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "urlbarExperimentFeature", () => {
|
||||
const { ExperimentFeature } = ChromeUtils.import(
|
||||
"resource://nimbus/ExperimentAPI.jsm"
|
||||
);
|
||||
return new ExperimentFeature("urlbar");
|
||||
});
|
||||
|
||||
// These prefs are relative to the `browser.urlbar` branch.
|
||||
const SUGGEST_PREF = "suggest.quicksuggest";
|
||||
|
||||
|
@ -45,7 +51,7 @@ class ProviderQuickSuggest extends UrlbarProvider {
|
|||
super(...args);
|
||||
this._updateExperimentState();
|
||||
UrlbarPrefs.addObserver(this);
|
||||
NimbusFeatures.urlbar.onUpdate(this._updateExperimentState);
|
||||
urlbarExperimentFeature.onUpdate(this._updateExperimentState);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,7 +102,7 @@ class ProviderQuickSuggest extends UrlbarProvider {
|
|||
return (
|
||||
queryContext.trimmedSearchString &&
|
||||
!queryContext.searchMode &&
|
||||
NimbusFeatures.urlbar.getValue().quickSuggestEnabled &&
|
||||
urlbarExperimentFeature.getValue().quickSuggestEnabled &&
|
||||
UrlbarPrefs.get(SUGGEST_PREF) &&
|
||||
UrlbarPrefs.get("suggest.searches") &&
|
||||
UrlbarPrefs.get("browser.search.suggest.enabled") &&
|
||||
|
@ -277,12 +283,12 @@ class ProviderQuickSuggest extends UrlbarProvider {
|
|||
_updateExperimentState() {
|
||||
Services.telemetry.setEventRecordingEnabled(
|
||||
TELEMETRY_EVENT_CATEGORY,
|
||||
NimbusFeatures.urlbar.getValue().quickSuggestEnabled
|
||||
urlbarExperimentFeature.getValue().quickSuggestEnabled
|
||||
);
|
||||
// QuickSuggest is only loaded by the UrlBar on it's first query, however
|
||||
// there is work it can preload when idle instead of starting it on user
|
||||
// input. Referencing it here will trigger its import and init.
|
||||
if (NimbusFeatures.urlbar.getValue().quickSuggestEnabled) {
|
||||
if (urlbarExperimentFeature.getValue().quickSuggestEnabled) {
|
||||
UrlbarQuickSuggest; // eslint-disable-line no-unused-expressions
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
RemoteSettings: "resource://services-settings/remote-settings.js",
|
||||
UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm",
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.jsm",
|
||||
ExperimentFeature: "resource://nimbus/ExperimentAPI.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["TextDecoder"]);
|
||||
|
@ -53,13 +53,14 @@ class Suggestions {
|
|||
this._initPromise = Promise.resolve();
|
||||
this._rs = RemoteSettings(RS_COLLECTION);
|
||||
this.onFeatureUpdate = this.onFeatureUpdate.bind(this);
|
||||
if (NimbusFeatures.urlbar.getValue().quickSuggestEnabled) {
|
||||
this.urlbarExperimentFeature = new ExperimentFeature("urlbar");
|
||||
if (this.urlbarExperimentFeature.getValue().quickSuggestEnabled) {
|
||||
this._initPromise = new Promise(resolve => (this._initResolve = resolve));
|
||||
Services.tm.idleDispatchToMainThread(
|
||||
this._setupRemoteSettings.bind(this)
|
||||
);
|
||||
} else {
|
||||
NimbusFeatures.urlbar.onUpdate(this.onFeatureUpdate);
|
||||
this.urlbarExperimentFeature.onUpdate(this.onFeatureUpdate);
|
||||
}
|
||||
return this._initPromise;
|
||||
}
|
||||
|
@ -154,7 +155,7 @@ class Suggestions {
|
|||
* Called if a Urlbar Experiment Feature is changed.
|
||||
*/
|
||||
onFeatureUpdate() {
|
||||
if (NimbusFeatures.urlbar.getValue().quickSuggestEnabled) {
|
||||
if (this.urlbarExperimentFeature.getValue().quickSuggestEnabled) {
|
||||
this._setupRemoteSettings();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,4 +5,12 @@ About
|
|||
------
|
||||
|
||||
Nimbus is an automated experimentation system.
|
||||
Our API docs are hosted with the `Experimenter Docs <https://mozilla.github.io/experimenter-docs/desktop-feature-api>`_.
|
||||
|
||||
Learn more
|
||||
---------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
integration.md
|
||||
testing.md
|
|
@ -0,0 +1,80 @@
|
|||
# Nimbus Integration and Migration Guide for Desktop Front-End Experiments
|
||||
|
||||
This guide will help you integrate `ExperimentAPI.jsm` in your Desktop front-end code to run Nimbus experiments, while still being able to use preferences for default values and local development.
|
||||
|
||||
In order to use `ExperimentAPI.jsm` your code must be able to import `jsm`s in the parent process or a privileged child process.
|
||||
|
||||
## Register a new feature
|
||||
|
||||
A feature is just some area of code instrumented for experiments – it can be as small as a single function or as complex as a whole about: page. You need to choose an identifier for your feature (e.g. "aboutnewtab").
|
||||
|
||||
```javascript
|
||||
// In ExperimentAPI.jsm
|
||||
|
||||
const MANIFEST = {
|
||||
// Our feature name
|
||||
aboutwelcome: {
|
||||
description: "The about:welcome page",
|
||||
// Control if the feature is on or off
|
||||
enabledFallbackPref: "browser.aboutwelcome.enabled",
|
||||
variables: {
|
||||
// Additional (optional) values that we can control
|
||||
// The name of these variables is up to you
|
||||
skipFocus: {
|
||||
type: "boolean",
|
||||
fallbackPref: "browser.aboutwelcome.skipFocus",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// In firefox.js
|
||||
pref("browser.aboutwelcome.enable", true);
|
||||
pref("skipFocus", false);
|
||||
```
|
||||
|
||||
> By setting fallback preferences for Nimbus features, you will be able to still run Normandy roll-outs and experiments while you are partially migrated. We do not recommend running Nimbus and Normandy experiments on the same feature/preference simultaneously.
|
||||
|
||||
## How to use an Experiment Feature
|
||||
|
||||
Import `ExperimentFeature` from `ExperimentAPI.jsm` and instantiate an instance
|
||||
|
||||
```jsx
|
||||
XPCOMUtils.defineLazyGetter(this, "feature", () => {
|
||||
const { ExperimentFeature } = ChromeUtils.import(
|
||||
"resource://nimbus/ExperimentAPI.jsm"
|
||||
);
|
||||
// Here we use the same name we defined in the MANIFEST
|
||||
return new ExperimentFeature("aboutwelcome");
|
||||
});
|
||||
```
|
||||
|
||||
Access feature values:
|
||||
|
||||
```jsx
|
||||
if (feature.isEnabled() {
|
||||
// Do something!
|
||||
// This is controllbed by the `enabledFallbackPref` defined in the MANIFEST
|
||||
}
|
||||
|
||||
// props: { skipFocus: boolean }
|
||||
const props = feature.getValue();
|
||||
renderSomeUI(props);
|
||||
```
|
||||
|
||||
Defaults values inline:
|
||||
|
||||
```jsx
|
||||
feature.isEnabled({ defaultValue: true });
|
||||
|
||||
const { skipFocus } = feature.getValue() || {};
|
||||
```
|
||||
|
||||
Listen to changes:
|
||||
|
||||
```jsx
|
||||
// Listen to changes, including to fallback prefs.
|
||||
feature.on(() => {
|
||||
updateUI(feature.getValue());
|
||||
});
|
||||
```
|
|
@ -0,0 +1,61 @@
|
|||
# Nimbus Testing Helpers
|
||||
|
||||
In order to make testing easier we created some helpers that can be accessed by including
|
||||
|
||||
```js
|
||||
const { ExperimentFakes } = ChromeUtils.import(
|
||||
"resource://testing-common/NimbusTestUtils.jsm"
|
||||
);
|
||||
```
|
||||
|
||||
## Testing your feature integrating with Nimbus
|
||||
|
||||
1. You need to create a recipe
|
||||
|
||||
```js
|
||||
let recipe = ExperimentFakes.recipe("my-cool-experiment", {
|
||||
branches: [
|
||||
{
|
||||
slug: "treatment-branch",
|
||||
ratio: 1,
|
||||
feature: {
|
||||
featureId: "<YOUR FEATURE>",
|
||||
// The feature is on
|
||||
enabled: true,
|
||||
// If you defined `variables` in the MANIFEST
|
||||
// the `value` should match that schema
|
||||
value: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
bucketConfig: {
|
||||
start: 0,
|
||||
// Ensure 100% enrollment
|
||||
count: 10000,
|
||||
total: 10000,
|
||||
namespace: "my-mochitest",
|
||||
randomizationUnit: "normandy_id",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
2. Now with the newly created recipe you want the test to enroll in the experiment
|
||||
|
||||
```js
|
||||
let {
|
||||
enrollmentPromise,
|
||||
doExperimentCleanup,
|
||||
} = ExperimentFakes.enrollmentHelper(recipe);
|
||||
|
||||
// Await for enrollment to complete
|
||||
|
||||
await enrollmentPromise;
|
||||
|
||||
// Now you can assume the feature is enabled so you can
|
||||
// test and that it's doing the right thing
|
||||
|
||||
// Assert.ok(It works!)
|
||||
|
||||
// Finishing up
|
||||
await doExperimentCleanup();
|
||||
```
|
|
@ -15,6 +15,13 @@ const LoginInfo = new Components.Constructor(
|
|||
"init"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "autocompleteFeature", () => {
|
||||
const { ExperimentFeature } = ChromeUtils.import(
|
||||
"resource://nimbus/ExperimentAPI.jsm"
|
||||
);
|
||||
return new ExperimentFeature("password-autocomplete");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "LoginRelatedRealmsParent", () => {
|
||||
const { LoginRelatedRealmsParent } = ChromeUtils.import(
|
||||
"resource://gre/modules/LoginRelatedRealms.jsm"
|
||||
|
@ -26,7 +33,6 @@ XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]);
|
|||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
ChromeMigrationUtils: "resource:///modules/ChromeMigrationUtils.jsm",
|
||||
NimbusFeatures: "resource://nimbus/ExperimentAPI.jsm",
|
||||
LoginHelper: "resource://gre/modules/LoginHelper.jsm",
|
||||
MigrationUtils: "resource:///modules/MigrationUtils.jsm",
|
||||
PasswordGenerator: "resource://gre/modules/PasswordGenerator.jsm",
|
||||
|
@ -335,8 +341,7 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
const profiles = await migrator.getSourceProfiles();
|
||||
if (
|
||||
profiles.length == 1 &&
|
||||
NimbusFeatures["password-autocomplete"].getValue()
|
||||
?.directMigrateSingleProfile
|
||||
autocompleteFeature.getValue()?.directMigrateSingleProfile
|
||||
) {
|
||||
const loginAdded = new Promise(resolve => {
|
||||
const obs = (subject, topic, data) => {
|
||||
|
|
Загрузка…
Ссылка в новой задаче