Bug 1594035 p1 - Register UI listener sooner in Normandy init to avoid race conditions r=Gijs

Without this patch, the UI finished listener is only registered after the
migrations are completely run. If the UI finishes intializating before this
happens, then our listener will never fire, and we'll miss the event. This
causes initialization to never proceed.

With this patch, we register the listener synchronously (before the first
`await`) and so are guaranteed to receive the event, no matter how long the
migrations take to run.

Differential Revision: https://phabricator.services.mozilla.com/D53896

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Michael Cooper 2019-11-21 16:58:17 +00:00
Родитель 00a4140def
Коммит 95327e78e3
1 изменённых файлов: 17 добавлений и 11 удалений

Просмотреть файл

@ -20,6 +20,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
RecipeRunner: "resource://normandy/lib/RecipeRunner.jsm",
ShieldPreferences: "resource://normandy/lib/ShieldPreferences.jsm",
TelemetryEvents: "resource://normandy/lib/TelemetryEvents.jsm",
PromiseUtils: "resource://gre/modules/PromiseUtils.jsm",
});
var EXPORTED_SYMBOLS = ["Normandy"];
@ -43,6 +44,13 @@ var Normandy = {
rolloutPrefsChanged: {},
async init({ runAsync = true } = {}) {
this.uiAvailableDeferred = PromiseUtils.defer();
if (runAsync) {
Services.obs.addObserver(this, UI_AVAILABLE_NOTIFICATION);
} else {
this.uiAvailableDeferred.resolve();
}
// Initialization that needs to happen before the first paint on startup.
await NormandyMigrations.applyAll();
this.rolloutPrefsChanged = this.applyStartupPrefs(
@ -52,26 +60,24 @@ var Normandy = {
STARTUP_EXPERIMENT_PREFS_BRANCH
);
if (runAsync) {
Services.obs.addObserver(this, UI_AVAILABLE_NOTIFICATION);
} else {
// Remove any observers, if present.
try {
Services.obs.removeObserver(this, UI_AVAILABLE_NOTIFICATION);
} catch (e) {}
await this.finishInit();
}
// Once the UI has loaded (and so we are no longer at risk of delaying it),
// call finishInit.
this.uiAvailableDeferred.promise.then(() => this.finishInit());
},
observe(subject, topic, data) {
if (topic === UI_AVAILABLE_NOTIFICATION) {
Services.obs.removeObserver(this, UI_AVAILABLE_NOTIFICATION);
this.finishInit();
this.uiAvailableDeferred.resolve();
}
},
async finishInit() {
// Remove any observers, if present.
try {
Services.obs.removeObserver(this, UI_AVAILABLE_NOTIFICATION);
} catch (e) {}
try {
TelemetryEvents.init();
} catch (err) {