gecko-dev/dom/presentation/tests/xpcshell/test_tcp_control_channel.js
Kris Maglione e930b89c34 Bug 1514594: Part 3 - Change ChromeUtils.import API.
***
Bug 1514594: Part 3a - Change ChromeUtils.import to return an exports object; not pollute global. r=mccr8

This changes the behavior of ChromeUtils.import() to return an exports object,
rather than a module global, in all cases except when `null` is passed as a
second argument, and changes the default behavior not to pollute the global
scope with the module's exports. Thus, the following code written for the old
model:

  ChromeUtils.import("resource://gre/modules/Services.jsm");

is approximately the same as the following, in the new model:

  var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");

Since the two behaviors are mutually incompatible, this patch will land with a
scripted rewrite to update all existing callers to use the new model rather
than the old.
***
Bug 1514594: Part 3b - Mass rewrite all JS code to use the new ChromeUtils.import API. rs=Gijs

This was done using the followng script:

https://bitbucket.org/kmaglione/m-c-rewrites/src/tip/processors/cu-import-exports.jsm
***
Bug 1514594: Part 3c - Update ESLint plugin for ChromeUtils.import API changes. r=Standard8

Differential Revision: https://phabricator.services.mozilla.com/D16747
***
Bug 1514594: Part 3d - Remove/fix hundreds of duplicate imports from sync tests. r=Gijs

Differential Revision: https://phabricator.services.mozilla.com/D16748
***
Bug 1514594: Part 3e - Remove no-op ChromeUtils.import() calls. r=Gijs

Differential Revision: https://phabricator.services.mozilla.com/D16749
***
Bug 1514594: Part 3f.1 - Cleanup various test corner cases after mass rewrite. r=Gijs
***
Bug 1514594: Part 3f.2 - Cleanup various non-test corner cases after mass rewrite. r=Gijs

Differential Revision: https://phabricator.services.mozilla.com/D16750

--HG--
extra : rebase_source : 359574ee3064c90f33bf36c2ebe3159a24cc8895
extra : histedit_source : b93c8f42808b1599f9122d7842d2c0b3e656a594%2C64a3a4e3359dc889e2ab2b49461bab9e27fc10a7
2019-01-17 10:18:31 -08:00

394 lines
14 KiB
JavaScript

/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
var pcs;
// Call |run_next_test| if all functions in |names| are called
function makeJointSuccess(names) {
let funcs = {}, successCount = 0;
names.forEach(function(name) {
funcs[name] = function() {
info("got expected: " + name);
if (++successCount === names.length)
run_next_test();
};
});
return funcs;
}
function TestDescription(aType, aTcpAddress, aTcpPort) {
this.type = aType;
this.tcpAddress = Cc["@mozilla.org/array;1"]
.createInstance(Ci.nsIMutableArray);
for (let address of aTcpAddress) {
let wrapper = Cc["@mozilla.org/supports-cstring;1"]
.createInstance(Ci.nsISupportsCString);
wrapper.data = address;
this.tcpAddress.appendElement(wrapper);
}
this.tcpPort = aTcpPort;
}
TestDescription.prototype = {
QueryInterface: ChromeUtils.generateQI([Ci.nsIPresentationChannelDescription]),
};
const CONTROLLER_CONTROL_CHANNEL_PORT = 36777;
const PRESENTER_CONTROL_CHANNEL_PORT = 36888;
var CLOSE_CONTROL_CHANNEL_REASON = Cr.NS_OK;
var candidate;
// presenter's presentation channel description
const OFFER_ADDRESS = "192.168.123.123";
const OFFER_PORT = 123;
// controller's presentation channel description
const ANSWER_ADDRESS = "192.168.321.321";
const ANSWER_PORT = 321;
function loopOfferAnser() {
pcs = Cc["@mozilla.org/presentation/control-service;1"]
.createInstance(Ci.nsIPresentationControlService);
pcs.id = "controllerID";
pcs.listener = {
onServerReady() {
testPresentationServer();
},
};
// First run with TLS enabled.
pcs.startServer(true, PRESENTER_CONTROL_CHANNEL_PORT);
}
function testPresentationServer() {
let yayFuncs = makeJointSuccess(["controllerControlChannelClose",
"presenterControlChannelClose",
"controllerControlChannelReconnect",
"presenterControlChannelReconnect"]);
let presenterControlChannel;
pcs.listener = {
onSessionRequest(deviceInfo, url, presentationId, controlChannel) {
presenterControlChannel = controlChannel;
Assert.equal(deviceInfo.id, pcs.id, "expected device id");
Assert.equal(deviceInfo.address, "127.0.0.1", "expected device address");
Assert.equal(url, "http://example.com", "expected url");
Assert.equal(presentationId, "testPresentationId", "expected presentation id");
presenterControlChannel.listener = {
status: "created",
onOffer(aOffer) {
Assert.equal(this.status, "opened", "1. presenterControlChannel: get offer, send answer");
this.status = "onOffer";
let offer = aOffer.QueryInterface(Ci.nsIPresentationChannelDescription);
Assert.strictEqual(offer.tcpAddress.queryElementAt(0, Ci.nsISupportsCString).data,
OFFER_ADDRESS,
"expected offer address array");
Assert.equal(offer.tcpPort, OFFER_PORT, "expected offer port");
try {
let tcpType = Ci.nsIPresentationChannelDescription.TYPE_TCP;
let answer = new TestDescription(tcpType, [ANSWER_ADDRESS], ANSWER_PORT);
presenterControlChannel.sendAnswer(answer);
} catch (e) {
Assert.ok(false, "sending answer fails" + e);
}
},
onAnswer(aAnswer) {
Assert.ok(false, "get answer");
},
onIceCandidate(aCandidate) {
Assert.ok(true, "3. presenterControlChannel: get ice candidate, close channel");
let recvCandidate = JSON.parse(aCandidate);
for (let key in recvCandidate) {
if (typeof(recvCandidate[key]) !== "function") {
Assert.equal(recvCandidate[key], candidate[key], "key " + key + " should match.");
}
}
presenterControlChannel.disconnect(CLOSE_CONTROL_CHANNEL_REASON);
},
notifyConnected() {
Assert.equal(this.status, "created", "0. presenterControlChannel: opened");
this.status = "opened";
},
notifyDisconnected(aReason) {
Assert.equal(this.status, "onOffer", "4. presenterControlChannel: closed");
Assert.equal(aReason, CLOSE_CONTROL_CHANNEL_REASON, "presenterControlChannel notify closed");
this.status = "closed";
yayFuncs.controllerControlChannelClose();
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
};
},
onReconnectRequest(deviceInfo, url, presentationId, controlChannel) {
Assert.equal(url, "http://example.com", "expected url");
Assert.equal(presentationId, "testPresentationId", "expected presentation id");
yayFuncs.presenterControlChannelReconnect();
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIPresentationControlServerListener]),
};
let presenterDeviceInfo = {
id: "presentatorID",
address: "127.0.0.1",
port: PRESENTER_CONTROL_CHANNEL_PORT,
certFingerprint: pcs.certFingerprint,
QueryInterface: ChromeUtils.generateQI([Ci.nsITCPDeviceInfo]),
};
let controllerControlChannel = pcs.connect(presenterDeviceInfo);
controllerControlChannel.listener = {
status: "created",
onOffer(offer) {
Assert.ok(false, "get offer");
},
onAnswer(aAnswer) {
Assert.equal(this.status, "opened", "2. controllerControlChannel: get answer, send ICE candidate");
let answer = aAnswer.QueryInterface(Ci.nsIPresentationChannelDescription);
Assert.strictEqual(answer.tcpAddress.queryElementAt(0, Ci.nsISupportsCString).data,
ANSWER_ADDRESS,
"expected answer address array");
Assert.equal(answer.tcpPort, ANSWER_PORT, "expected answer port");
candidate = {
candidate: "1 1 UDP 1 127.0.0.1 34567 type host",
sdpMid: "helloworld",
sdpMLineIndex: 1,
};
controllerControlChannel.sendIceCandidate(JSON.stringify(candidate));
},
onIceCandidate(aCandidate) {
Assert.ok(false, "get ICE candidate");
},
notifyConnected() {
Assert.equal(this.status, "created", "0. controllerControlChannel: opened, send offer");
controllerControlChannel.launch("testPresentationId", "http://example.com");
this.status = "opened";
try {
let tcpType = Ci.nsIPresentationChannelDescription.TYPE_TCP;
let offer = new TestDescription(tcpType, [OFFER_ADDRESS], OFFER_PORT);
controllerControlChannel.sendOffer(offer);
} catch (e) {
Assert.ok(false, "sending offer fails:" + e);
}
},
notifyDisconnected(aReason) {
this.status = "closed";
Assert.equal(aReason, CLOSE_CONTROL_CHANNEL_REASON, "4. controllerControlChannel notify closed");
yayFuncs.presenterControlChannelClose();
let reconnectControllerControlChannel = pcs.connect(presenterDeviceInfo);
reconnectControllerControlChannel.listener = {
notifyConnected() {
reconnectControllerControlChannel.reconnect("testPresentationId", "http://example.com");
},
notifyReconnected() {
yayFuncs.controllerControlChannelReconnect();
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
};
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
};
}
function terminateRequest() {
let yayFuncs = makeJointSuccess(["controllerControlChannelConnected",
"controllerControlChannelDisconnected",
"presenterControlChannelDisconnected",
"terminatedByController",
"terminatedByReceiver"]);
let controllerControlChannel;
let terminatePhase = "controller";
pcs.listener = {
onTerminateRequest(deviceInfo, presentationId, controlChannel, isFromReceiver) {
Assert.equal(deviceInfo.address, "127.0.0.1", "expected device address");
Assert.equal(presentationId, "testPresentationId", "expected presentation id");
controlChannel.terminate(presentationId); // Reply terminate ack.
if (terminatePhase === "controller") {
controllerControlChannel = controlChannel;
Assert.equal(deviceInfo.id, pcs.id, "expected controller device id");
Assert.equal(isFromReceiver, false, "expected request from controller");
yayFuncs.terminatedByController();
controllerControlChannel.listener = {
notifyConnected() {
Assert.ok(true, "control channel notify connected");
yayFuncs.controllerControlChannelConnected();
terminatePhase = "receiver";
controllerControlChannel.terminate("testPresentationId");
},
notifyDisconnected(aReason) {
Assert.equal(aReason, CLOSE_CONTROL_CHANNEL_REASON, "controllerControlChannel notify disconncted");
yayFuncs.controllerControlChannelDisconnected();
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
};
} else {
Assert.equal(deviceInfo.id, presenterDeviceInfo.id, "expected presenter device id");
Assert.equal(isFromReceiver, true, "expected request from receiver");
yayFuncs.terminatedByReceiver();
presenterControlChannel.disconnect(CLOSE_CONTROL_CHANNEL_REASON);
}
},
QueryInterface: ChromeUtils.generateQI([Ci.nsITCPPresentationServerListener]),
};
let presenterDeviceInfo = {
id: "presentatorID",
address: "127.0.0.1",
port: PRESENTER_CONTROL_CHANNEL_PORT,
certFingerprint: pcs.certFingerprint,
QueryInterface: ChromeUtils.generateQI([Ci.nsITCPDeviceInfo]),
};
let presenterControlChannel = pcs.connect(presenterDeviceInfo);
presenterControlChannel.listener = {
notifyConnected() {
presenterControlChannel.terminate("testPresentationId");
},
notifyDisconnected(aReason) {
Assert.equal(aReason, CLOSE_CONTROL_CHANNEL_REASON, "4. presenterControlChannel notify disconnected");
yayFuncs.presenterControlChannelDisconnected();
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
};
}
function terminateRequestAbnormal() {
let yayFuncs = makeJointSuccess(["controllerControlChannelConnected",
"controllerControlChannelDisconnected",
"presenterControlChannelDisconnected"]);
let controllerControlChannel;
pcs.listener = {
onTerminateRequest(deviceInfo, presentationId, controlChannel, isFromReceiver) {
Assert.equal(deviceInfo.id, pcs.id, "expected controller device id");
Assert.equal(deviceInfo.address, "127.0.0.1", "expected device address");
Assert.equal(presentationId, "testPresentationId", "expected presentation id");
Assert.equal(isFromReceiver, false, "expected request from controller");
controlChannel.terminate("unmatched-presentationId"); // Reply abnormal terminate ack.
controllerControlChannel = controlChannel;
controllerControlChannel.listener = {
notifyConnected() {
Assert.ok(true, "control channel notify connected");
yayFuncs.controllerControlChannelConnected();
},
notifyDisconnected(aReason) {
Assert.equal(aReason, Cr.NS_ERROR_FAILURE, "controllerControlChannel notify disconncted with error");
yayFuncs.controllerControlChannelDisconnected();
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
};
},
QueryInterface: ChromeUtils.generateQI([Ci.nsITCPPresentationServerListener]),
};
let presenterDeviceInfo = {
id: "presentatorID",
address: "127.0.0.1",
port: PRESENTER_CONTROL_CHANNEL_PORT,
certFingerprint: pcs.certFingerprint,
QueryInterface: ChromeUtils.generateQI([Ci.nsITCPDeviceInfo]),
};
let presenterControlChannel = pcs.connect(presenterDeviceInfo);
presenterControlChannel.listener = {
notifyConnected() {
presenterControlChannel.terminate("testPresentationId");
},
notifyDisconnected(aReason) {
Assert.equal(aReason, Cr.NS_ERROR_FAILURE, "4. presenterControlChannel notify disconnected with error");
yayFuncs.presenterControlChannelDisconnected();
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
};
}
function setOffline() {
pcs.listener = {
onServerReady(aPort, aCertFingerprint) {
Assert.notEqual(aPort, 0, "TCPPresentationServer port changed and the port should be valid");
pcs.close();
run_next_test();
},
};
// Let the server socket restart automatically.
Services.io.offline = true;
Services.io.offline = false;
}
function oneMoreLoop() {
try {
pcs.listener = {
onServerReady() {
testPresentationServer();
},
};
// Second run with TLS disabled.
pcs.startServer(false, PRESENTER_CONTROL_CHANNEL_PORT);
} catch (e) {
Assert.ok(false, "TCP presentation init fail:" + e);
run_next_test();
}
}
function shutdown() {
pcs.listener = {
onServerReady(aPort, aCertFingerprint) {
Assert.ok(false, "TCPPresentationServer port changed");
},
};
pcs.close();
Assert.equal(pcs.port, 0, "TCPPresentationServer closed");
run_next_test();
}
// Test manually close control channel with NS_ERROR_FAILURE
function changeCloseReason() {
CLOSE_CONTROL_CHANNEL_REASON = Cr.NS_ERROR_FAILURE;
run_next_test();
}
add_test(loopOfferAnser);
add_test(terminateRequest);
add_test(terminateRequestAbnormal);
add_test(setOffline);
add_test(changeCloseReason);
add_test(oneMoreLoop);
add_test(shutdown);
function run_test() {
// Need profile dir to store the key / cert
do_get_profile();
// Ensure PSM is initialized
Cc["@mozilla.org/psm;1"].getService(Ci.nsISupports);
Services.prefs.setBoolPref("dom.presentation.tcp_server.debug", true);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("dom.presentation.tcp_server.debug");
});
run_next_test();
}