Bug 1524908 - Since the Search Service API is now asynchronous, the one-off-search (re)build method became re-entrant and evidently race-y. Let's guard against that. r=dao

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Mike de Boer 2019-02-06 11:51:04 +00:00
parent 76cfa49e64
commit 9f68077886
3 changed files with 27 additions and 3 deletions

View File

@ -21,7 +21,7 @@ if (AppConstants.platform != "macosx" &&
AppConstants.platform == "win")) {
EXPECTED_REFLOWS_FIRST_OPEN.push({
stack: [
"_rebuild@chrome://browser/content/search/search-one-offs.js",
"__rebuild@chrome://browser/content/search/search-one-offs.js",
/* This is limited to a one-line stack, because the next item is an async
function and as such not supported on all trees, according to bug 1501761.
"async*set popup@chrome://browser/content/search/search-one-offs.js",

View File

@ -22,7 +22,7 @@ if (AppConstants.platform != "macosx" &&
AppConstants.isPlatformAndVersionAtLeast("win", "10"))) {
EXPECTED_REFLOWS_FIRST_OPEN.push({
stack: [
"_rebuild@chrome://browser/content/search/search-one-offs.js",
"__rebuild@chrome://browser/content/search/search-one-offs.js",
/* This is limited to a one-line stack, because the next item is an async
function and as such not supported on all trees, according to bug 1501761.
"async*set popup@chrome://browser/content/search/search-one-offs.js",

View File

@ -78,6 +78,12 @@ class SearchOneOffs {
this._engines = null;
/**
* `_rebuild()` is async, because it queries the Search Service, which means
* there is a potential for a race when it's called multiple times in succession.
*/
this._rebuilding = false;
/**
* If a page offers more than this number of engines, the add-engines
* menu button is shown, instead of showing the engines directly in the
@ -399,9 +405,27 @@ class SearchOneOffs {
}
/**
* Builds all the UI.
* Infallible, non-re-entrant version of `__rebuild()`.
*/
async _rebuild() {
if (this._rebuilding) {
return;
}
this._rebuilding = true;
try {
await this.__rebuild();
} catch (ex) {
Cu.reportError("Search-one-offs::_rebuild() error: " + ex);
} finally {
this._rebuilding = false;
}
}
/**
* Builds all the UI.
*/
async __rebuild() {
// Update the 'Search for <keywords> with:" header.
this._updateAfterQueryChanged();