summaryrefslogtreecommitdiffstats
path: root/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js')
-rw-r--r--dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js366
1 files changed, 366 insertions, 0 deletions
diff --git a/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js b/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js
new file mode 100644
index 000000000..82d7362b2
--- /dev/null
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js
@@ -0,0 +1,366 @@
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+* You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict';
+
+const { classes: Cc, interfaces: Ci, manager: Cm, utils: Cu, results: Cr } = Components;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
+
+const uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
+ .getService(Ci.nsIUUIDGenerator);
+
+function debug(str) {
+ // dump('DEBUG -*- PresentationSessionChromeScript1UA -*-: ' + str + '\n');
+}
+
+const originalFactoryData = [];
+var sessionId; // Store the uuid generated by PresentationRequest.
+var triggerControlChannelError = false; // For simulating error during control channel establishment.
+
+// control channel of sender
+const mockControlChannelOfSender = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
+ set listener(listener) {
+ // PresentationControllingInfo::SetControlChannel
+ if (listener) {
+ debug('set listener for mockControlChannelOfSender without null');
+ } else {
+ debug('set listener for mockControlChannelOfSender with null');
+ }
+ this._listener = listener;
+ },
+ get listener() {
+ return this._listener;
+ },
+ notifyConnected: function() {
+ // send offer after notifyConnected immediately
+ this._listener
+ .QueryInterface(Ci.nsIPresentationControlChannelListener)
+ .notifyConnected();
+ },
+ notifyReconnected: function() {
+ // send offer after notifyOpened immediately
+ this._listener
+ .QueryInterface(Ci.nsIPresentationControlChannelListener)
+ .notifyReconnected();
+ },
+ sendOffer: function(offer) {
+ Services.tm.mainThread.dispatch(() => {
+ mockControlChannelOfReceiver.onOffer(offer);
+ }, Ci.nsIThread.DISPATCH_NORMAL);
+ },
+ onAnswer: function(answer) {
+ this._listener
+ .QueryInterface(Ci.nsIPresentationControlChannelListener)
+ .onAnswer(answer);
+ },
+ launch: function(presentationId, url) {
+ sessionId = presentationId;
+ sendAsyncMessage('sender-launch', url);
+ },
+ disconnect: function(reason) {
+ if (!this._listener) {
+ return;
+ }
+ this._listener
+ .QueryInterface(Ci.nsIPresentationControlChannelListener)
+ .notifyDisconnected(reason);
+ mockControlChannelOfReceiver.disconnect();
+ },
+ terminate: function(presentationId) {
+ sendAsyncMessage('sender-terminate');
+ },
+ reconnect: function(presentationId, url) {
+ sendAsyncMessage('start-reconnect', url);
+ },
+ sendIceCandidate: function(candidate) {
+ mockControlChannelOfReceiver.notifyIceCandidate(candidate);
+ },
+ notifyIceCandidate: function(candidate) {
+ if (!this._listener) {
+ return;
+ }
+
+ this._listener
+ .QueryInterface(Ci.nsIPresentationControlChannelListener)
+ .onIceCandidate(candidate);
+ },
+};
+
+// control channel of receiver
+const mockControlChannelOfReceiver = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
+ set listener(listener) {
+ // PresentationPresentingInfo::SetControlChannel
+ if (listener) {
+ debug('set listener for mockControlChannelOfReceiver without null');
+ } else {
+ debug('set listener for mockControlChannelOfReceiver with null');
+ }
+ this._listener = listener;
+
+ if (this._pendingOpened) {
+ this._pendingOpened = false;
+ this.notifyConnected();
+ }
+ },
+ get listener() {
+ return this._listener;
+ },
+ notifyConnected: function() {
+ // do nothing
+ if (!this._listener) {
+ this._pendingOpened = true;
+ return;
+ }
+ this._listener
+ .QueryInterface(Ci.nsIPresentationControlChannelListener)
+ .notifyConnected();
+ },
+ onOffer: function(offer) {
+ this._listener
+ .QueryInterface(Ci.nsIPresentationControlChannelListener)
+ .onOffer(offer);
+ },
+ sendAnswer: function(answer) {
+ Services.tm.mainThread.dispatch(() => {
+ mockControlChannelOfSender.onAnswer(answer);
+ }, Ci.nsIThread.DISPATCH_NORMAL);
+ },
+ disconnect: function(reason) {
+ if (!this._listener) {
+ return;
+ }
+
+ this._listener
+ .QueryInterface(Ci.nsIPresentationControlChannelListener)
+ .notifyDisconnected(reason);
+ sendAsyncMessage('control-channel-receiver-closed', reason);
+ },
+ terminate: function(presentaionId) {
+ },
+ sendIceCandidate: function(candidate) {
+ mockControlChannelOfReceiver.notifyIceCandidate(candidate);
+ },
+ notifyIceCandidate: function(candidate) {
+ if (!this._listener) {
+ return;
+ }
+
+ this._listener
+ .QueryInterface(Ci.nsIPresentationControlChannelListener)
+ .onIceCandidate(candidate);
+ },
+};
+
+const mockDevice = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevice]),
+ id: 'id',
+ name: 'name',
+ type: 'type',
+ establishControlChannel: function(url, presentationId) {
+ if (triggerControlChannelError) {
+ throw Cr.NS_ERROR_FAILURE;
+ }
+ sendAsyncMessage('control-channel-established');
+ return mockControlChannelOfSender;
+ },
+ disconnect: function() {
+ sendAsyncMessage('device-disconnected');
+ },
+ isRequestedUrlSupported: function(requestedUrl) {
+ return true;
+ },
+};
+
+const mockDevicePrompt = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevicePrompt,
+ Ci.nsIFactory]),
+ createInstance: function(aOuter, aIID) {
+ if (aOuter) {
+ throw Components.results.NS_ERROR_NO_AGGREGATION;
+ }
+ return this.QueryInterface(aIID);
+ },
+ set request(request) {
+ this._request = request;
+ },
+ get request() {
+ return this._request;
+ },
+ promptDeviceSelection: function(request) {
+ this._request = request;
+ sendAsyncMessage('device-prompt');
+ },
+ simulateSelect: function() {
+ this._request.select(mockDevice);
+ },
+ simulateCancel: function() {
+ this._request.cancel();
+ }
+};
+
+const mockRequestUIGlue = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationRequestUIGlue,
+ Ci.nsIFactory]),
+ set promise(aPromise) {
+ this._promise = aPromise
+ },
+ get promise() {
+ return this._promise;
+ },
+ createInstance: function(aOuter, aIID) {
+ if (aOuter) {
+ throw Components.results.NS_ERROR_NO_AGGREGATION;
+ }
+ return this.QueryInterface(aIID);
+ },
+ sendRequest: function(aUrl, aSessionId) {
+ return this.promise;
+ },
+};
+
+function initMockAndListener() {
+
+ function registerMockFactory(contractId, mockClassId, mockFactory) {
+ var originalClassId, originalFactory;
+
+ var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+ if (!registrar.isCIDRegistered(mockClassId)) {
+ 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(mockClassId, "", contractId, mockFactory);
+ }
+
+ return { contractId: contractId,
+ mockClassId: mockClassId,
+ mockFactory: mockFactory,
+ originalClassId: originalClassId,
+ originalFactory: originalFactory };
+ }
+ // Register mock factories.
+ const uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
+ .getService(Ci.nsIUUIDGenerator);
+ originalFactoryData.push(registerMockFactory("@mozilla.org/presentation-device/prompt;1",
+ uuidGenerator.generateUUID(),
+ mockDevicePrompt));
+ originalFactoryData.push(registerMockFactory("@mozilla.org/presentation/requestuiglue;1",
+ uuidGenerator.generateUUID(),
+ mockRequestUIGlue));
+
+ addMessageListener('trigger-device-add', function() {
+ debug('Got message: trigger-device-add');
+ var deviceManager = Cc['@mozilla.org/presentation-device/manager;1']
+ .getService(Ci.nsIPresentationDeviceManager);
+ deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener)
+ .addDevice(mockDevice);
+ });
+
+ addMessageListener('trigger-device-prompt-select', function() {
+ debug('Got message: trigger-device-prompt-select');
+ mockDevicePrompt.simulateSelect();
+ });
+
+ addMessageListener('trigger-on-session-request', function(url) {
+ debug('Got message: trigger-on-session-request');
+ var deviceManager = Cc['@mozilla.org/presentation-device/manager;1']
+ .getService(Ci.nsIPresentationDeviceManager);
+ deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener)
+ .onSessionRequest(mockDevice,
+ url,
+ sessionId,
+ mockControlChannelOfReceiver);
+ });
+
+ addMessageListener('trigger-on-terminate-request', function() {
+ debug('Got message: trigger-on-terminate-request');
+ var deviceManager = Cc['@mozilla.org/presentation-device/manager;1']
+ .getService(Ci.nsIPresentationDeviceManager);
+ deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener)
+ .onTerminateRequest(mockDevice,
+ sessionId,
+ mockControlChannelOfReceiver,
+ false);
+ });
+
+ addMessageListener('trigger-control-channel-open', function(reason) {
+ debug('Got message: trigger-control-channel-open');
+ mockControlChannelOfSender.notifyConnected();
+ mockControlChannelOfReceiver.notifyConnected();
+ });
+
+ addMessageListener('trigger-control-channel-error', function(reason) {
+ debug('Got message: trigger-control-channel-open');
+ triggerControlChannelError = true;
+ });
+
+ addMessageListener('trigger-reconnected-acked', function(url) {
+ debug('Got message: trigger-reconnected-acked');
+ mockControlChannelOfSender.notifyReconnected();
+ var deviceManager = Cc['@mozilla.org/presentation-device/manager;1']
+ .getService(Ci.nsIPresentationDeviceManager);
+ deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener)
+ .onReconnectRequest(mockDevice,
+ url,
+ sessionId,
+ mockControlChannelOfReceiver);
+ });
+
+ // Used to call sendAsyncMessage in chrome script from receiver.
+ addMessageListener('forward-command', function(command_data) {
+ let command = JSON.parse(command_data);
+ sendAsyncMessage(command.name, command.data);
+ });
+
+ addMessageListener('teardown', teardown);
+
+ var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+ obs.addObserver(function setupRequestPromiseHandler(aSubject, aTopic, aData) {
+ debug('Got observer: setup-request-promise');
+ obs.removeObserver(setupRequestPromiseHandler, aTopic);
+ mockRequestUIGlue.promise = aSubject;
+ sendAsyncMessage('promise-setup-ready');
+ }, 'setup-request-promise', false);
+}
+
+function teardown() {
+
+ function registerOriginalFactory(contractId, mockedClassId, mockedFactory, originalClassId, originalFactory) {
+ if (originalFactory) {
+ var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+ registrar.unregisterFactory(mockedClassId, mockedFactory);
+ registrar.registerFactory(originalClassId, "", contractId, originalFactory);
+ }
+ }
+
+ mockRequestUIGlue.promise = null;
+ mockControlChannelOfSender.listener = null;
+ mockControlChannelOfReceiver.listener = null;
+ mockDevicePrompt.request = null;
+
+ var deviceManager = Cc['@mozilla.org/presentation-device/manager;1']
+ .getService(Ci.nsIPresentationDeviceManager);
+ deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener)
+ .removeDevice(mockDevice);
+ // Register original factories.
+ for (var data of originalFactoryData) {
+ registerOriginalFactory(data.contractId, data.mockClassId,
+ data.mockFactory, data.originalClassId,
+ data.originalFactory);
+ }
+ sendAsyncMessage('teardown-complete');
+}
+
+initMockAndListener();