mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1041537 - Prevent ContentSearch from leaking the browser if it's still processing a message while the test suite shuts down r=adw
This commit is contained in:
parent
2fbc0da862
commit
576d19c572
@ -81,7 +81,7 @@ this.ContentSearch = {
|
||||
// them immediately, which would result in non-FIFO responses due to the
|
||||
// asynchrononicity added by converting image data URIs to ArrayBuffers.
|
||||
_eventQueue: [],
|
||||
_currentEvent: null,
|
||||
_currentEventPromise: null,
|
||||
|
||||
// This is used to handle search suggestions. It maps xul:browsers to objects
|
||||
// { controller, previousFormHistoryResult }. See _onMessageGetSuggestions.
|
||||
@ -94,6 +94,16 @@ this.ContentSearch = {
|
||||
Services.obs.addObserver(this, "browser-search-engine-modified", false);
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
Cc["@mozilla.org/globalmessagemanager;1"].
|
||||
getService(Ci.nsIMessageListenerManager).
|
||||
removeMessageListener(INBOUND_MESSAGE, this);
|
||||
Services.obs.removeObserver(this, "browser-search-engine-modified");
|
||||
|
||||
this._eventQueue.length = 0;
|
||||
return Promise.resolve(this._currentEventPromise);
|
||||
},
|
||||
|
||||
/**
|
||||
* Focuses the search input in the page with the given message manager.
|
||||
* @param messageManager
|
||||
@ -141,22 +151,24 @@ this.ContentSearch = {
|
||||
}
|
||||
},
|
||||
|
||||
_processEventQueue: Task.async(function* () {
|
||||
if (this._currentEvent || !this._eventQueue.length) {
|
||||
_processEventQueue: function () {
|
||||
if (this._currentEventPromise || !this._eventQueue.length) {
|
||||
return;
|
||||
}
|
||||
this._currentEvent = this._eventQueue.shift();
|
||||
try {
|
||||
yield this["_on" + this._currentEvent.type](this._currentEvent.data);
|
||||
}
|
||||
catch (err) {
|
||||
Cu.reportError(err);
|
||||
}
|
||||
finally {
|
||||
this._currentEvent = null;
|
||||
this._processEventQueue();
|
||||
}
|
||||
}),
|
||||
|
||||
let event = this._eventQueue.shift();
|
||||
|
||||
return this._currentEventPromise = Task.spawn(function* () {
|
||||
try {
|
||||
yield this["_on" + event.type](event.data);
|
||||
} catch (err) {
|
||||
Cu.reportError(err);
|
||||
} finally {
|
||||
this._currentEventPromise = null;
|
||||
this._processEventQueue();
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_onMessage: Task.async(function* (msg) {
|
||||
let methodName = "_onMessage" + msg.data.type;
|
||||
|
@ -16,10 +16,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserNewTabPreloader",
|
||||
"resource:///modules/BrowserNewTabPreloader.jsm", "BrowserNewTabPreloader");
|
||||
"resource:///modules/BrowserNewTabPreloader.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "CustomizationTabPreloader",
|
||||
"resource:///modules/CustomizationTabPreloader.jsm", "CustomizationTabPreloader");
|
||||
"resource:///modules/CustomizationTabPreloader.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
|
||||
"resource:///modules/ContentSearch.jsm");
|
||||
|
||||
const SIMPLETEST_OVERRIDES =
|
||||
["ok", "is", "isnot", "ise", "todo", "todo_is", "todo_isnot", "info", "expectAssertions"];
|
||||
@ -455,6 +458,8 @@ Tester.prototype = {
|
||||
// is invoked to start the tests.
|
||||
this.waitForWindowsState((function () {
|
||||
if (this.done) {
|
||||
let promise = Promise.resolve();
|
||||
|
||||
// Uninitialize a few things explicitly so that they can clean up
|
||||
// frames and browser intentionally kept alive until shutdown to
|
||||
// eliminate false positives.
|
||||
@ -484,6 +489,9 @@ Tester.prototype = {
|
||||
SocialFlyout.unload();
|
||||
SocialShare.uninit();
|
||||
TabView.uninit();
|
||||
|
||||
// Destroying ContentSearch is asynchronous.
|
||||
promise = ContentSearch.destroy();
|
||||
}
|
||||
|
||||
// Schedule GC and CC runs before finishing in order to detect
|
||||
@ -515,20 +523,22 @@ Tester.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
checkForLeakedGlobalWindows(aResults => {
|
||||
if (aResults.length == 0) {
|
||||
this.finish();
|
||||
return;
|
||||
}
|
||||
// After the first check, if there are reported leaked windows, sleep
|
||||
// for a while, to allow off-main-thread work to complete and free up
|
||||
// main-thread objects. Then check again.
|
||||
setTimeout(() => {
|
||||
checkForLeakedGlobalWindows(aResults => {
|
||||
reportLeaks(aResults);
|
||||
promise.then(() => {
|
||||
checkForLeakedGlobalWindows(aResults => {
|
||||
if (aResults.length == 0) {
|
||||
this.finish();
|
||||
});
|
||||
}, 1000);
|
||||
return;
|
||||
}
|
||||
// After the first check, if there are reported leaked windows, sleep
|
||||
// for a while, to allow off-main-thread work to complete and free up
|
||||
// main-thread objects. Then check again.
|
||||
setTimeout(() => {
|
||||
checkForLeakedGlobalWindows(aResults => {
|
||||
reportLeaks(aResults);
|
||||
this.finish();
|
||||
});
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user