summaryrefslogtreecommitdiffstats
path: root/dom/presentation/tests/mochitest/PresentationSessionFrameScript.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/presentation/tests/mochitest/PresentationSessionFrameScript.js')
-rw-r--r--dom/presentation/tests/mochitest/PresentationSessionFrameScript.js291
1 files changed, 291 insertions, 0 deletions
diff --git a/dom/presentation/tests/mochitest/PresentationSessionFrameScript.js b/dom/presentation/tests/mochitest/PresentationSessionFrameScript.js
new file mode 100644
index 0000000000..5385e5d9b9
--- /dev/null
+++ b/dom/presentation/tests/mochitest/PresentationSessionFrameScript.js
@@ -0,0 +1,291 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* eslint-env mozilla/frame-script */
+
+function loadPrivilegedScriptTest() {
+ /**
+ * The script is loaded as
+ * (a) a privileged script in content process for dc_sender.html
+ * (b) a frame script in the remote iframe process for dc_receiver_oop.html
+ * |type port == "undefined"| indicates the script is load by
+ * |loadPrivilegedScript| which is the first case.
+ */
+ function sendMessage(type, data) {
+ if (typeof port == "undefined") {
+ sendAsyncMessage(type, { data });
+ } else {
+ port.postMessage({ type, data });
+ }
+ }
+
+ if (typeof port != "undefined") {
+ /**
+ * When the script is loaded by |loadPrivilegedScript|, these APIs
+ * are exposed to this script.
+ */
+ port.onmessage = e => {
+ var type = e.data.type;
+ if (!handlers.hasOwnProperty(type)) {
+ return;
+ }
+ var args = [e];
+ handlers[type].forEach(handler => handler.apply(null, args));
+ };
+ var handlers = {};
+ /* eslint-disable-next-line no-global-assign */
+ addMessageListener = function(message, handler) {
+ if (handlers.hasOwnProperty(message)) {
+ handlers[message].push(handler);
+ } else {
+ handlers[message] = [handler];
+ }
+ };
+ /* eslint-disable-next-line no-global-assign */
+ removeMessageListener = function(message, handler) {
+ if (!handler || !handlers.hasOwnProperty(message)) {
+ return;
+ }
+ var index = handlers[message].indexOf(handler);
+ if (index != -1) {
+ handlers[message].splice(index, 1);
+ }
+ };
+ }
+
+ const Cm = Components.manager;
+
+ const mockedChannelDescription = {
+ /* eslint-disable-next-line mozilla/use-chromeutils-generateqi */
+ QueryInterface(iid) {
+ const interfaces = [Ci.nsIPresentationChannelDescription];
+
+ if (!interfaces.some(v => iid.equals(v))) {
+ throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
+ }
+ return this;
+ },
+ get type() {
+ /* global Services */
+ if (
+ Services.prefs.getBoolPref(
+ "dom.presentation.session_transport.data_channel.enable"
+ )
+ ) {
+ return Ci.nsIPresentationChannelDescription.TYPE_DATACHANNEL;
+ }
+ return Ci.nsIPresentationChannelDescription.TYPE_TCP;
+ },
+ get dataChannelSDP() {
+ return "test-sdp";
+ },
+ };
+
+ function setTimeout(callback, delay) {
+ let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ timer.initWithCallback(
+ { notify: callback },
+ delay,
+ Ci.nsITimer.TYPE_ONE_SHOT
+ );
+ return timer;
+ }
+
+ const mockedSessionTransport = {
+ /* eslint-disable-next-line mozilla/use-chromeutils-generateqi */
+ QueryInterface(iid) {
+ const interfaces = [
+ Ci.nsIPresentationSessionTransport,
+ Ci.nsIPresentationDataChannelSessionTransportBuilder,
+ Ci.nsIFactory,
+ ];
+
+ if (!interfaces.some(v => iid.equals(v))) {
+ throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
+ }
+ return this;
+ },
+ createInstance(aOuter, aIID) {
+ if (aOuter) {
+ throw Components.Exception("", Cr.NS_ERROR_NO_AGGREGATION);
+ }
+ return this.QueryInterface(aIID);
+ },
+ set callback(callback) {
+ this._callback = callback;
+ },
+ get callback() {
+ return this._callback;
+ },
+ /* OOP case */
+ buildDataChannelTransport(role, window, listener) {
+ dump("PresentationSessionFrameScript: build data channel transport\n");
+ this._listener = listener;
+ this._role = role;
+
+ var hasNavigator = window
+ ? typeof window.navigator != "undefined"
+ : false;
+ sendMessage("check-navigator", hasNavigator);
+
+ if (this._role == Ci.nsIPresentationService.ROLE_CONTROLLER) {
+ this._listener.sendOffer(mockedChannelDescription);
+ }
+ },
+
+ enableDataNotification() {
+ sendMessage("data-transport-notification-enabled");
+ },
+ send(data) {
+ sendMessage("message-sent", data);
+ },
+ close(reason) {
+ sendMessage("data-transport-closed", reason);
+ this._callback
+ .QueryInterface(Ci.nsIPresentationSessionTransportCallback)
+ .notifyTransportClosed(reason);
+ this._callback = null;
+ },
+ simulateTransportReady() {
+ this._callback
+ .QueryInterface(Ci.nsIPresentationSessionTransportCallback)
+ .notifyTransportReady();
+ },
+ simulateIncomingMessage(message) {
+ this._callback
+ .QueryInterface(Ci.nsIPresentationSessionTransportCallback)
+ .notifyData(message, false);
+ },
+ onOffer(aOffer) {
+ this._listener.sendAnswer(mockedChannelDescription);
+ this._onSessionTransport();
+ },
+ onAnswer(aAnswer) {
+ this._onSessionTransport();
+ },
+ _onSessionTransport() {
+ setTimeout(() => {
+ this._listener.onSessionTransport(this);
+ this.simulateTransportReady();
+ this._listener = null;
+ }, 0);
+ },
+ };
+
+ function tearDown() {
+ mockedSessionTransport.callback = null;
+
+ /* Register original factories. */
+ for (var data of originalFactoryData) {
+ registerOriginalFactory(
+ data.contractId,
+ data.mockedClassId,
+ data.mockedFactory,
+ data.originalClassId,
+ data.originalFactory
+ );
+ }
+ sendMessage("teardown-complete");
+ }
+
+ function registerMockedFactory(contractId, mockedClassId, mockedFactory) {
+ var originalClassId, originalFactory;
+ var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+
+ if (!registrar.isCIDRegistered(mockedClassId)) {
+ try {
+ originalClassId = registrar.contractIDToCID(contractId);
+ originalFactory = Cm.getClassObject(Cc[contractId], Ci.nsIFactory);
+ } catch (ex) {
+ originalClassId = "";
+ originalFactory = null;
+ }
+ registrar.registerFactory(mockedClassId, "", contractId, mockedFactory);
+ }
+
+ return {
+ contractId,
+ mockedClassId,
+ mockedFactory,
+ originalClassId,
+ originalFactory,
+ };
+ }
+
+ function registerOriginalFactory(
+ contractId,
+ mockedClassId,
+ mockedFactory,
+ originalClassId,
+ originalFactory
+ ) {
+ if (originalFactory) {
+ var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+ registrar.unregisterFactory(mockedClassId, mockedFactory);
+ registrar.registerFactory(originalClassId, "", contractId, null);
+ }
+ }
+
+ /* Register mocked factories. */
+ const originalFactoryData = [];
+ const uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(
+ Ci.nsIUUIDGenerator
+ );
+ originalFactoryData.push(
+ registerMockedFactory(
+ "@mozilla.org/presentation/datachanneltransportbuilder;1",
+ uuidGenerator.generateUUID(),
+ mockedSessionTransport
+ )
+ );
+
+ addMessageListener("trigger-incoming-message", function(event) {
+ mockedSessionTransport.simulateIncomingMessage(event.data.data);
+ });
+ addMessageListener("teardown", () => tearDown());
+}
+
+// Exposed to the caller of |loadPrivilegedScript|
+var contentScript = {
+ handlers: {},
+ addMessageListener(message, handler) {
+ if (this.handlers.hasOwnProperty(message)) {
+ this.handlers[message].push(handler);
+ } else {
+ this.handlers[message] = [handler];
+ }
+ },
+ removeMessageListener(message, handler) {
+ if (!handler || !this.handlers.hasOwnProperty(message)) {
+ return;
+ }
+ var index = this.handlers[message].indexOf(handler);
+ if (index != -1) {
+ this.handlers[message].splice(index, 1);
+ }
+ },
+ sendAsyncMessage(message, data) {
+ port.postMessage({ type: message, data });
+ },
+};
+
+if (!SpecialPowers.isMainProcess()) {
+ var port;
+ try {
+ port = SpecialPowers.loadPrivilegedScript(
+ loadPrivilegedScriptTest.toString()
+ );
+ } catch (e) {
+ ok(false, "loadPrivilegedScript should not throw" + e);
+ }
+
+ port.onmessage = e => {
+ var type = e.data.type;
+ if (!contentScript.handlers.hasOwnProperty(type)) {
+ return;
+ }
+ var args = [e.data.data];
+ contentScript.handlers[type].forEach(handler => handler.apply(null, args));
+ };
+}