Bug 1588193 - Fix BrowserTestUtils.waitForContentEvent with Fission, r=mccr8

This also changes BrowserTestUtils.addContentEventListener to use browsing
contexts to track added listeners and their associated targets.

Depends on D52105

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Kashav Madan 2019-11-07 21:16:01 +00:00
Родитель 86d7dbce4d
Коммит 53846e37ba
2 изменённых файлов: 26 добавлений и 54 удалений

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

@ -1151,12 +1151,15 @@ var BrowserTestUtils = {
* event is the expected one, or false if it should be ignored and
* listening should continue. If not specified, the first event with
* the specified name resolves the returned promise.
* @param {bool} wantsUntrusted [optional]
* @param {bool} wantUntrusted [optional]
* Whether to accept untrusted events
*
* @note Because this function is intended for testing, any error in checkFn
* will cause the returned promise to be rejected instead of waiting for
* the next event, since this is probably a bug in the test.
* @note As of bug 1588193, this function no longer rejects the returned
* promise in the case of a checkFn error. Instead, since checkFn is now
* called through eval in the content process, the error is thrown in
* the listener created by ContentEventListenerChild. Work to improve
* error handling (eg. to reject the promise as before and to preserve
* the filename/stack) is being tracked in bug 1593811.
*
* @returns {Promise}
*/
@ -1165,46 +1168,20 @@ var BrowserTestUtils = {
eventName,
capture = false,
checkFn,
wantsUntrusted = false
wantUntrusted = false
) {
let parameters = {
eventName,
capture,
checkFnSource: checkFn ? checkFn.toSource() : null,
wantsUntrusted,
};
/* eslint-disable no-eval */
return ContentTask.spawn(browser, parameters, function({
eventName,
capture,
checkFnSource,
wantsUntrusted,
}) {
let checkFn;
if (checkFnSource) {
checkFn = eval(`(() => (${checkFnSource}))()`);
}
return new Promise((resolve, reject) => {
addEventListener(
eventName,
function listener(event) {
let completion = resolve;
try {
if (checkFn && !checkFn(event)) {
return;
}
} catch (e) {
completion = () => reject(e);
}
removeEventListener(eventName, listener, capture);
completion();
},
capture,
wantsUntrusted
);
});
return new Promise(resolve => {
let removeEventListener = this.addContentEventListener(
browser,
eventName,
() => {
removeEventListener();
resolve();
},
{ capture, wantUntrusted },
checkFn
);
});
/* eslint-enable no-eval */
},
/**
@ -1261,7 +1238,10 @@ var BrowserTestUtils = {
) {
let id = gListenerId++;
let contentEventListeners = this._contentEventListeners;
contentEventListeners.set(id, { listener, browser });
contentEventListeners.set(id, {
listener,
browsingContext: browser.browsingContext,
});
let eventListenerState = this._contentEventListenerSharedState;
eventListenerState.set(id, {
@ -1296,12 +1276,12 @@ var BrowserTestUtils = {
* BrowserTestUtilsParent.jsm when a content event we were listening for
* happens.
*/
_receivedContentEventListener(listenerId, browser) {
_receivedContentEventListener(listenerId, browsingContext) {
let listenerData = this._contentEventListeners.get(listenerId);
if (!listenerData) {
return;
}
if (listenerData.browser != browser) {
if (listenerData.browsingContext != browsingContext) {
return;
}
listenerData.listener();

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

@ -14,17 +14,9 @@ class ContentEventListenerParent extends JSWindowActorParent {
receiveMessage(aMessage) {
switch (aMessage.name) {
case "ContentEventListener:Run": {
let browser = this.browsingContext.top.embedderElement;
if (!browser) {
break;
}
// Handle RDM.
if (browser.outerBrowser) {
browser = browser.outerBrowser;
}
BrowserTestUtils._receivedContentEventListener(
aMessage.data.listenerId,
browser
this.browsingContext.top
);
break;
}