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.js258
1 files changed, 258 insertions, 0 deletions
diff --git a/dom/presentation/tests/mochitest/PresentationSessionFrameScript.js b/dom/presentation/tests/mochitest/PresentationSessionFrameScript.js
new file mode 100644
index 000000000..77240ab5f
--- /dev/null
+++ b/dom/presentation/tests/mochitest/PresentationSessionFrameScript.js
@@ -0,0 +1,258 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+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': data});
+ } else {
+ port.postMessage({'type': type,
+ 'data': 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 = {};
+ addMessageListener = function(message, handler) {
+ if (handlers.hasOwnProperty(message)) {
+ handlers[message].push(handler);
+ } else {
+ handlers[message] = [handler];
+ }
+ };
+ 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 { classes: Cc, interfaces: Ci, manager: Cm, utils: Cu, results: Cr } = Components;
+
+ const mockedChannelDescription = {
+ QueryInterface : function (iid) {
+ const interfaces = [Ci.nsIPresentationChannelDescription];
+
+ if (!interfaces.some(v => iid.equals(v))) {
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ }
+ return this;
+ },
+ get type() {
+ 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 = {
+ QueryInterface : function (iid) {
+ const interfaces = [Ci.nsIPresentationSessionTransport,
+ Ci.nsIPresentationDataChannelSessionTransportBuilder,
+ Ci.nsIFactory];
+
+ if (!interfaces.some(v => iid.equals(v))) {
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ }
+ return this;
+ },
+ createInstance: function(aOuter, aIID) {
+ if (aOuter) {
+ throw Components.results.NS_ERROR_NO_AGGREGATION;
+ }
+ return this.QueryInterface(aIID);
+ },
+ set callback(callback) {
+ this._callback = callback;
+ },
+ get callback() {
+ return this._callback;
+ },
+ /* OOP case */
+ buildDataChannelTransport: function(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: function() {
+ sendMessage('data-transport-notification-enabled');
+ },
+ send: function(data) {
+ sendMessage('message-sent', data);
+ },
+ close: function(reason) {
+ sendMessage('data-transport-closed', reason);
+ this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportClosed(reason);
+ this._callback = null;
+ },
+ simulateTransportReady: function() {
+ this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportReady();
+ },
+ simulateIncomingMessage: function(message) {
+ this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyData(message, false);
+ },
+ onOffer: function(aOffer) {
+ this._listener.sendAnswer(mockedChannelDescription);
+ this._onSessionTransport();
+ },
+ onAnswer: function(aAnswer) {
+ this._onSessionTransport();
+ },
+ _onSessionTransport: function() {
+ 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;
+ }
+ if (originalFactory) {
+ registrar.unregisterFactory(originalClassId, originalFactory);
+ }
+ registrar.registerFactory(mockedClassId, "", contractId, mockedFactory);
+ }
+
+ return { contractId: contractId,
+ mockedClassId: mockedClassId,
+ mockedFactory: mockedFactory,
+ originalClassId: originalClassId,
+ originalFactory: originalFactory };
+ }
+
+ function registerOriginalFactory(contractId, mockedClassId, mockedFactory, originalClassId, originalFactory) {
+ if (originalFactory) {
+ var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+ registrar.unregisterFactory(mockedClassId, mockedFactory);
+ registrar.registerFactory(originalClassId, "", contractId, originalFactory);
+ }
+ }
+
+ /* 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: function(message, handler) {
+ if (this.handlers.hasOwnProperty(message)) {
+ this.handlers[message].push(handler);
+ } else {
+ this.handlers[message] = [handler];
+ }
+ },
+ removeMessageListener: function(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: function(message, data) {
+ port.postMessage({'type': message,
+ 'data': data
+ });
+ }
+}
+
+if (!SpecialPowers.isMainProcess()) {
+ var port;
+ try {
+ port = SpecialPowers.loadPrivilegedScript(loadPrivilegedScriptTest.toSource());
+ } catch (e) {
+ ok(false, "loadPrivilegedScript shoulde 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));
+ };
+}