Source code

Revision control

Copy as Markdown

Other Tools

// This code runs in the content process that holds the window to which
// this actor is attached. There is one instance of this class for each
// "inner window" (i.e. one per content document, including iframes/nested
// iframes).
// There is a 1:1 relationship between instances of this class and
// FissionTestHelperParent instances, and the pair are entangled such
// that they can communicate with each other regardless of which process
// they live in.
export class FissionTestHelperChild extends JSWindowActorChild {
constructor() {
super();
this._msgCounter = 0;
this._oopifResponsePromiseResolvers = [];
}
cw() {
return this.contentWindow.wrappedJSObject;
}
initialize() {
// This exports a bunch of things into the content window so that
// the test can access them. Most things are scoped inside the
// FissionTestHelper object on the window to avoid polluting the global
// namespace.
let cw = this.cw();
Cu.exportFunction(
(cond, msg) => this.sendAsyncMessage("ok", { cond, msg }),
cw,
{ defineAs: "ok" }
);
Cu.exportFunction(
(a, b, msg) => this.sendAsyncMessage("is", { a, b, msg }),
cw,
{ defineAs: "is" }
);
let FissionTestHelper = Cu.createObjectIn(cw, {
defineAs: "FissionTestHelper",
});
FissionTestHelper.startTestPromise = new cw.Promise(
Cu.exportFunction(resolve => {
this._startTestPromiseResolver = resolve;
}, cw)
);
Cu.exportFunction(this.subtestDone.bind(this), FissionTestHelper, {
defineAs: "subtestDone",
});
Cu.exportFunction(this.subtestFailed.bind(this), FissionTestHelper, {
defineAs: "subtestFailed",
});
Cu.exportFunction(this.sendToOopif.bind(this), FissionTestHelper, {
defineAs: "sendToOopif",
});
Cu.exportFunction(this.fireEventInEmbedder.bind(this), FissionTestHelper, {
defineAs: "fireEventInEmbedder",
});
}
// Called by the subtest to indicate completion to the top-level browser-chrome
// mochitest.
subtestDone() {
let cw = this.cw();
if (cw.ApzCleanup) {
cw.ApzCleanup.execute();
}
this.sendAsyncMessage("Test:Complete", {});
}
// Called by the subtest to indicate subtest failure. Only one of subtestDone
// or subtestFailed should be called.
subtestFailed(msg) {
this.sendAsyncMessage("ok", { cond: false, msg });
this.subtestDone();
}
// Called by the subtest to eval some code in the OOP iframe. This returns
// a promise that resolves to the return value from the eval.
sendToOopif(iframeElement, stringToEval) {
let browsingContextId = iframeElement.browsingContext.id;
let msgId = ++this._msgCounter;
let cw = this.cw();
let responsePromise = new cw.Promise(
Cu.exportFunction(resolve => {
this._oopifResponsePromiseResolvers[msgId] = resolve;
}, cw)
);
this.sendAsyncMessage("EmbedderToOopif", {
browsingContextId,
msgId,
stringToEval,
});
return responsePromise;
}
// Called by OOP iframes to dispatch an event in the embedder window. This
// can be used by the OOP iframe to asynchronously notify the embedder of
// things that happen. The embedder can use promiseOneEvent from
// helper_fission_utils.js to listen for these events.
fireEventInEmbedder(eventType, data) {
this.sendAsyncMessage("OopifToEmbedder", { eventType, data });
}
handleEvent(evt) {
switch (evt.type) {
case "FissionTestHelper:Init":
this.initialize();
break;
}
}
receiveMessage(msg) {
switch (msg.name) {
case "Test:Start":
this._startTestPromiseResolver();
delete this._startTestPromiseResolver;
break;
case "FromEmbedder":
let evalResult = this.contentWindow.eval(msg.data.stringToEval);
this.sendAsyncMessage("OopifToEmbedder", {
msgId: msg.data.msgId,
evalResult,
});
break;
case "FromOopif":
if (typeof msg.data.msgId == "number") {
if (!(msg.data.msgId in this._oopifResponsePromiseResolvers)) {
dump(
"Error: FromOopif got a message with unknown numeric msgId in " +
this.contentWindow.location.href +
"\n"
);
}
this._oopifResponsePromiseResolvers[msg.data.msgId](
msg.data.evalResult
);
delete this._oopifResponsePromiseResolvers[msg.data.msgId];
} else if (typeof msg.data.eventType == "string") {
let cw = this.cw();
let event = new cw.Event(msg.data.eventType);
event.data = Cu.cloneInto(msg.data.data, cw);
this.contentWindow.dispatchEvent(event);
} else {
dump(
"Warning: Unrecognized FromOopif message received in " +
this.contentWindow.location.href +
"\n"
);
}
break;
}
}
}