browser(firefox): wait for search and addon manager initialization (#4081)

It looks like terminating browser when search service or addon manager is
not fully initialized results in a broken shutdown sequence. As of
today, this results in multiple errors in the browser STDERR. In future,
this might also result in browser stalling instead of terminating.

This starts awaiting search and addon manager termination.

References #3995
This commit is contained in:
Andrey Lushnikov 2020-10-07 10:24:16 -07:00 committed by GitHub
parent 3b4232864d
commit 6beef551d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 2 deletions

View File

@ -1,2 +1,2 @@
1185
Changed: lushnikov@chromium.org Wed Oct 7 08:45:05 PDT 2020
1186
Changed: lushnikov@chromium.org Wed Oct 7 09:26:45 PDT 2020

View File

@ -4,6 +4,7 @@
"use strict";
const {AddonManager} = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
const {TargetRegistry} = ChromeUtils.import("chrome://juggler/content/TargetRegistry.js");
const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
@ -45,6 +46,18 @@ class BrowserHandler {
for (const target of this._targetRegistry.targets())
this._onTargetCreated(target);
// Wait to complete initialization of addon manager and search
// service before returning from this method. Failing to do so will result
// in a broken shutdown sequence and multiple errors in browser STDERR log.
//
// NOTE: we have to put this here instead of in the `Browser.close` handler
// since browser shutdown can be initiated when the last tab is closed, e.g.
// with persistent context.
await Promise.all([
waitForAddonManager(),
waitForSearchService(),
]);
}
async ['Browser.createBrowserContext']({removeOnDetach}) {
@ -243,6 +256,26 @@ class BrowserHandler {
}
}
async function waitForSearchService() {
const searchService = Components.classes["@mozilla.org/browser/search-service;1"].getService(Components.interfaces.nsISearchService);
await searchService.init();
}
async function waitForAddonManager() {
if (AddonManager.isReady)
return;
await new Promise(resolve => {
let listener = {
onStartup() {
AddonManager.removeManagerListener(listener);
resolve();
},
onShutdown() { },
};
AddonManager.addManagerListener(listener);
});
}
function nullToUndefined(value) {
return value === null ? undefined : value;
}