Dactyloidae/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js

366 lines
12 KiB
JavaScript

/* 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();