diff options
Diffstat (limited to 'gfx/layers/apz/test/mochitest/FissionTestHelperChild.sys.mjs')
-rw-r--r-- | gfx/layers/apz/test/mochitest/FissionTestHelperChild.sys.mjs | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/gfx/layers/apz/test/mochitest/FissionTestHelperChild.sys.mjs b/gfx/layers/apz/test/mochitest/FissionTestHelperChild.sys.mjs new file mode 100644 index 0000000000..c0695b7abb --- /dev/null +++ b/gfx/layers/apz/test/mochitest/FissionTestHelperChild.sys.mjs @@ -0,0 +1,157 @@ +// 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; + } + } +} |