Bug 1069230 - Presentation API implementation. Part 9 - Tests. r=kikuo

This commit is contained in:
Sean Lin 2015-04-23 11:44:01 +08:00
Родитель 1efa4382a3
Коммит 5eda6c5cc4
13 изменённых файлов: 1604 добавлений и 1 удалений

Просмотреть файл

@ -518,6 +518,10 @@ PresentationRequesterInfo::OnStopListening(nsIServerSocket* aServerSocket,
{
MOZ_ASSERT(NS_IsMainThread());
if (aStatus == NS_BINDING_ABORTED) { // The server socket was manually closed.
return NS_OK;
}
Shutdown(aStatus);
if (!IsSessionReady()) {
@ -795,7 +799,7 @@ PresentationResponderInfo::RejectedCallback(JSContext* aCx,
JS::Handle<JS::Value> aValue)
{
MOZ_ASSERT(NS_IsMainThread());
NS_WARNING("The receiver page fails to become ready before timeout.");
NS_WARNING("Launching the receiver page has been rejected.");
if (mTimer) {
mTimer->Cancel();

Просмотреть файл

@ -0,0 +1,359 @@
/* -*- 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 { classes: Cc, interfaces: Ci, manager: Cm, utils: Cu, results: Cr } = Components;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
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) {
registrar.unregisterFactory(mockedClassId, mockedFactory);
registrar.registerFactory(originalClassId, "", contractId, originalFactory);
}
}
const sessionId = 'test-session-id';
const address = Cc["@mozilla.org/supports-cstring;1"]
.createInstance(Ci.nsISupportsCString);
address.data = "127.0.0.1";
const addresses = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
addresses.appendElement(address, false);
const mockedChannelDescription = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationChannelDescription]),
type: 1,
tcpAddress: addresses,
tcpPort: 1234,
};
const mockedServerSocket = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIServerSocket,
Ci.nsIFactory]),
createInstance: function(aOuter, aIID) {
if (aOuter) {
throw Components.results.NS_ERROR_NO_AGGREGATION;
}
return this.QueryInterface(aIID);
},
get port() {
return this._port;
},
set listener(listener) {
this._listener = listener;
},
init: function(port, loopbackOnly, backLog) {
if (port != -1) {
this._port = port;
} else {
this._port = 5678;
}
},
asyncListen: function(listener) {
this._listener = listener;
},
close: function() {
this._listener.onStopListening(this, Cr.NS_BINDING_ABORTED);
},
simulateOnSocketAccepted: function(serverSocket, socketTransport) {
this._listener.onSocketAccepted(serverSocket, socketTransport);
}
};
const mockedSocketTransport = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsISocketTransport]),
};
const mockedControlChannel = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
set listener(listener) {
this._listener = listener;
},
get listener() {
return this._listener;
},
sendOffer: function(offer) {
sendAsyncMessage('offer-sent');
},
sendAnswer: function(answer) {
this._listener.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportReady();
},
close: function(reason) {
sendAsyncMessage('control-channel-closed', reason);
this._listener.QueryInterface(Ci.nsIPresentationControlChannelListener).notifyClosed(reason);
},
simulateReceiverReady: function() {
this._listener.QueryInterface(Ci.nsIPresentationControlChannelListener).notifyReceiverReady();
},
simulateOnOffer: function() {
sendAsyncMessage('offer-received');
this._listener.QueryInterface(Ci.nsIPresentationControlChannelListener).onOffer(mockedChannelDescription);
},
simulateOnAnswer: function() {
sendAsyncMessage('answer-received');
this._listener.QueryInterface(Ci.nsIPresentationControlChannelListener).onAnswer(mockedChannelDescription);
},
};
const mockedDevice = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevice]),
id: 'id',
name: 'name',
type: 'type',
establishControlChannel: function(url, presentationId) {
sendAsyncMessage('control-channel-established');
return mockedControlChannel;
},
set listener(listener) {
this._listener = listener;
},
get listener() {
return this._listener;
},
simulateSessionRequest: function(url, presentationId, controlChannel) {
this._listener.onSessionRequest(this, url, presentationId, controlChannel);
},
};
const mockedDevicePrompt = {
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(mockedDevice);
},
simulateCancel: function() {
this._request.cancel();
}
};
const mockedSessionTransport = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationSessionTransport,
Ci.nsIFactory]),
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;
},
get selfAddress() {
return this._selfAddress;
},
initWithSocketTransport: function(transport, callback) {
sendAsyncMessage('data-transport-initialized');
this._callback = callback;
this.simulateTransportReady();
},
initWithChannelDescription: function(description, callback) {
this._callback = callback;
var addresses = description.QueryInterface(Ci.nsIPresentationChannelDescription).tcpAddress;
this._selfAddress = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsINetAddr]),
address: (addresses.length > 0) ?
addresses.queryElementAt(0, Ci.nsISupportsCString).data : "",
port: description.QueryInterface(Ci.nsIPresentationChannelDescription).tcpPort,
};
},
send: function(data) {
var binaryStream = Cc["@mozilla.org/binaryinputstream;1"].
createInstance(Ci.nsIBinaryInputStream);
binaryStream.setInputStream(data);
var message = binaryStream.readBytes(binaryStream.available());
sendAsyncMessage('message-sent', message);
},
close: function(reason) {
sendAsyncMessage('data-transport-closed', reason);
this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportClosed(reason);
},
simulateTransportReady: function() {
this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportReady();
},
simulateIncomingMessage: function(message) {
this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyData(message);
},
};
const mockedNetworkInfo = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo]),
getAddresses: function(ips, prefixLengths) {
ips.value = ["127.0.0.1"];
prefixLengths.value = [0];
return 1;
},
};
const mockedNetworkManager = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkManager,
Ci.nsIFactory]),
createInstance: function(aOuter, aIID) {
if (aOuter) {
throw Components.results.NS_ERROR_NO_AGGREGATION;
}
return this.QueryInterface(aIID);
},
get activeNetworkInfo() {
return mockedNetworkInfo;
},
};
var requestPromise = null;
const mockedRequestUIGlue = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationRequestUIGlue,
Ci.nsIFactory]),
createInstance: function(aOuter, aIID) {
if (aOuter) {
throw Components.results.NS_ERROR_NO_AGGREGATION;
}
return this.QueryInterface(aIID);
},
sendRequest: function(aUrl, aSessionId) {
sendAsyncMessage('receiver-launching', aSessionId);
return requestPromise;
},
};
// Register mocked factories.
const uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator);
const originalFactoryData = [];
originalFactoryData.push(registerMockedFactory("@mozilla.org/presentation-device/prompt;1",
uuidGenerator.generateUUID(),
mockedDevicePrompt));
originalFactoryData.push(registerMockedFactory("@mozilla.org/network/server-socket;1",
uuidGenerator.generateUUID(),
mockedServerSocket));
originalFactoryData.push(registerMockedFactory("@mozilla.org/presentation/presentationsessiontransport;1",
uuidGenerator.generateUUID(),
mockedSessionTransport));
originalFactoryData.push(registerMockedFactory("@mozilla.org/network/manager;1",
uuidGenerator.generateUUID(),
mockedNetworkManager));
originalFactoryData.push(registerMockedFactory("@mozilla.org/presentation/requestuiglue;1",
uuidGenerator.generateUUID(),
mockedRequestUIGlue));
function tearDown() {
requestPromise = null;
mockedServerSocket.listener = null;
mockedControlChannel.listener = null;
mockedDevice.listener = null;
mockedDevicePrompt.request = null;
mockedSessionTransport.callback = null;
var deviceManager = Cc['@mozilla.org/presentation-device/manager;1']
.getService(Ci.nsIPresentationDeviceManager);
deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener).removeDevice(mockedDevice);
// Register original factories.
for (var data in originalFactoryData) {
registerOriginalFactory(data.contractId, data.mockedClassId,
data.mockedFactory, data.originalClassId,
data.originalFactory);
}
sendAsyncMessage('teardown-complete');
}
addMessageListener('trigger-device-add', function() {
var deviceManager = Cc['@mozilla.org/presentation-device/manager;1']
.getService(Ci.nsIPresentationDeviceManager);
deviceManager.QueryInterface(Ci.nsIPresentationDeviceListener).addDevice(mockedDevice);
});
addMessageListener('trigger-device-prompt-select', function() {
mockedDevicePrompt.simulateSelect();
});
addMessageListener('trigger-device-prompt-cancel', function() {
mockedDevicePrompt.simulateCancel();
});
addMessageListener('trigger-incoming-session-request', function(url) {
mockedDevice.simulateSessionRequest(url, sessionId, mockedControlChannel);
});
addMessageListener('trigger-incoming-offer', function() {
mockedControlChannel.simulateOnOffer();
});
addMessageListener('trigger-incoming-answer', function() {
mockedControlChannel.simulateOnAnswer();
});
addMessageListener('trigger-incoming-transport', function() {
mockedServerSocket.simulateOnSocketAccepted(mockedServerSocket, mockedSocketTransport);
});
addMessageListener('trigger-control-channel-close', function(reason) {
mockedControlChannel.close(reason);
});
addMessageListener('trigger-data-transport-close', function(reason) {
mockedSessionTransport.close(reason);
});
addMessageListener('trigger-incoming-message', function(message) {
mockedSessionTransport.simulateIncomingMessage(message);
});
addMessageListener('teardown', function() {
tearDown();
});
var obs = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
obs.addObserver(function observer(aSubject, aTopic, aData) {
obs.removeObserver(observer, aTopic);
requestPromise = aSubject;
}, 'setup-request-promise', false);

Просмотреть файл

@ -0,0 +1,77 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for B2G Presentation Session API at receiver side</title>
</head>
<body>
<div id="content"></div>
<script type="application/javascript;version=1.7">
"use strict";
function is(a, b, msg) {
window.parent.postMessage((a === b ? 'OK ' : 'KO ') + msg, '*');
}
function ok(a, msg) {
window.parent.postMessage((a ? 'OK ' : 'KO ') + msg, '*');
}
function info(msg) {
window.parent.postMessage('INFO ' + msg, '*');
}
function command(msg) {
window.parent.postMessage('COMMAND ' + JSON.stringify(msg), '*');
}
function finish() {
window.parent.postMessage('DONE', '*');
}
var session;
function testSessionAvailable() {
return new Promise(function(aResolve, aReject) {
ok(navigator.presentation, "navigator.presentation should be available.");
session = navigator.presentation.session;
ok(session.id, "Session ID should be set: " + session.id);
is(session.state, "disconnected", "Session state at receiver side should be disconnected by default.");
aResolve();
});
}
function testSessionReady() {
return new Promise(function(aResolve, aReject) {
session.onstatechange = function() {
session.onstatechange = null;
is(session.state, "connected", "Session state should become connected.");
aResolve();
};
command({ name: 'trigger-incoming-offer' });
});
}
function testCloseSession() {
return new Promise(function(aResolve, aReject) {
session.onstatechange = function() {
session.onstatechange = null;
is(session.state, "terminated", "Session should be terminated.");
aResolve();
};
session.close();
});
}
testSessionAvailable().
then(testSessionReady).
then(testCloseSession).
then(finish);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,77 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for B2G Presentation Session API at receiver side (OOP)</title>
</head>
<body>
<div id="content"></div>
<script type="application/javascript;version=1.7">
"use strict";
function is(a, b, msg) {
alert((a === b ? 'OK ' : 'KO ') + msg);
}
function ok(a, msg) {
alert((a ? 'OK ' : 'KO ') + msg);
}
function info(msg) {
alert('INFO ' + msg);
}
function command(msg) {
alert('COMMAND ' + JSON.stringify(msg));
}
function finish() {
alert('DONE');
}
var session;
function testSessionAvailable() {
return new Promise(function(aResolve, aReject) {
ok(navigator.presentation, "navigator.presentation should be available.");
session = navigator.presentation.session;
ok(session.id, "Session ID should be set: " + session.id);
is(session.state, "disconnected", "Session state at receiver side should be disconnected by default.");
aResolve();
});
}
function testSessionReady() {
return new Promise(function(aResolve, aReject) {
session.onstatechange = function() {
session.onstatechange = null;
is(session.state, "connected", "Session state should become connected.");
aResolve();
};
command({ name: 'trigger-incoming-offer' });
});
}
function testCloseSession() {
return new Promise(function(aResolve, aReject) {
session.onstatechange = function() {
session.onstatechange = null;
is(session.state, "terminated", "Session should be terminated.");
aResolve();
};
session.close();
});
}
testSessionAvailable().
then(testSessionReady).
then(testCloseSession).
then(finish);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,65 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for startSession errors of B2G Presentation API at receiver side</title>
</head>
<body>
<div id="content"></div>
<script type="application/javascript;version=1.7">
"use strict";
function is(a, b, msg) {
window.parent.postMessage((a === b ? 'OK ' : 'KO ') + msg, '*');
}
function ok(a, msg) {
window.parent.postMessage((a ? 'OK ' : 'KO ') + msg, '*');
}
function info(msg) {
window.parent.postMessage('INFO ' + msg, '*');
}
function command(msg) {
window.parent.postMessage('COMMAND ' + JSON.stringify(msg), '*');
}
function finish() {
window.parent.postMessage('DONE', '*');
}
var session;
function testSessionAvailable() {
return new Promise(function(aResolve, aReject) {
ok(navigator.presentation, "navigator.presentation should be available.");
session = navigator.presentation.session;
ok(session.id, "Session ID should be set: " + session.id);
is(session.state, "disconnected", "Session state at receiver side should be disconnected by default.");
aResolve();
});
}
function testUnexpectedControlChannelClose() {
return new Promise(function(aResolve, aReject) {
session.onstatechange = function() {
session.onstatechange = null;
is(session.state, "terminated", "Session state should become terminated.");
aResolve();
};
// Trigger the control channel to be closed with error code.
command({ name: 'trigger-control-channel-close', data: 0x80004004 /* NS_ERROR_ABORT */ });
});
}
testSessionAvailable().
then(testUnexpectedControlChannelClose).
then(finish);
</script>
</body>
</html>

Просмотреть файл

@ -1,6 +1,24 @@
[DEFAULT]
support-files =
PresentationDeviceInfoChromeScript.js
PresentationSessionChromeScript.js
file_presentation_receiver.html
file_presentation_receiver_oop.html
file_presentation_receiver_start_session_error.html
[test_presentation_device_info.html]
[test_presentation_device_info_permission.html]
[test_presentation_sender_disconnect.html]
skip-if = toolkit == 'android' # Bug 1129785
[test_presentation_sender_start_session_error.html]
skip-if = toolkit == 'android' # Bug 1129785
[test_presentation_sender.html]
skip-if = toolkit == 'android' # Bug 1129785
[test_presentation_receiver_start_session_error.html]
skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785
[test_presentation_receiver_start_session_timeout.html]
skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785
[test_presentation_receiver.html]
skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785
[test_presentation_receiver_oop.html]
skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android') # Bug 1129785

Просмотреть файл

@ -0,0 +1,122 @@
<!DOCTYPE HTML>
<html>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<head>
<meta charset="utf-8">
<title>Test for B2G Presentation Session API at receiver side</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1069230">Test for B2G Presentation Session API at receiver side</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script type="application/javascript">
'use strict';
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript.js'));
var receiverUrl = SimpleTest.getTestFileURL('file_presentation_receiver.html');
var obs = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
.getService(SpecialPowers.Ci.nsIObserverService);
function setup() {
return new Promise(function(aResolve, aReject) {
gScript.sendAsyncMessage('trigger-device-add');
var iframe = document.createElement('iframe');
iframe.setAttribute('src', receiverUrl);
// This event is triggered when the iframe calls "postMessage".
window.addEventListener('message', function listener(aEvent) {
var message = aEvent.data;
if (/^OK /.exec(message)) {
ok(true, "Message from iframe: " + message);
} else if (/^KO /.exec(message)) {
ok(false, "Message from iframe: " + message);
} else if (/^INFO /.exec(message)) {
info("Message from iframe: " + message);
} else if (/^COMMAND /.exec(message)) {
var command = JSON.parse(message.replace(/^COMMAND /, ''));
gScript.sendAsyncMessage(command.name, command.data);
} else if (/^DONE$/.exec(message)) {
ok(true, "Messaging from iframe complete.");
window.removeEventListener('message', listener);
teardown();
}
}, false);
var promise = new Promise(function(aResolve, aReject) {
document.body.appendChild(iframe);
aResolve(iframe);
});
obs.notifyObservers(promise, 'setup-request-promise', null);
gScript.addMessageListener('offer-received', function offerReceivedHandler() {
gScript.removeMessageListener('offer-received', offerReceivedHandler);
info("An offer is received.");
});
gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
is(aReason, SpecialPowers.Cr.NS_OK, "The control channel is closed normally.");
});
gScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
gScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
is(aReason, SpecialPowers.Cr.NS_OK, "The data transport should be closed normally.");
});
aResolve();
});
}
function testIncomingSessionRequest() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('receiver-launching', function launchReceiverHandler(aSessionId) {
gScript.removeMessageListener('receiver-launching', launchReceiverHandler);
info("Trying to launch receiver page.");
aResolve();
});
gScript.sendAsyncMessage('trigger-incoming-session-request', receiverUrl);
});
}
function teardown() {
gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
gScript.destroy();
SimpleTest.finish();
});
gScript.sendAsyncMessage('teardown');
}
function runTests() {
setup().
then(testIncomingSessionRequest);
}
SimpleTest.expectAssertions(0, 5);
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: false, context: document},
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0]]},
runTests);
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,131 @@
<!DOCTYPE HTML>
<html>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<head>
<meta charset="utf-8">
<title>Test for B2G Presentation Session API at receiver side (OOP)</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1069230">Test B2G Presentation Session API at receiver side (OOP)</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script type="application/javascript">
'use strict';
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript.js'));
var receiverUrl = SimpleTest.getTestFileURL('file_presentation_receiver_oop.html');
var obs = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
.getService(SpecialPowers.Ci.nsIObserverService);
function setup() {
return new Promise(function(aResolve, aReject) {
gScript.sendAsyncMessage('trigger-device-add');
SpecialPowers.addPermission('presentation', true, { url: receiverUrl,
appId: SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID,
isInBrowserElement: true });
var iframe = document.createElement('iframe');
iframe.setAttribute('remote', 'true');
iframe.setAttribute('mozbrowser', 'true');
iframe.setAttribute('src', receiverUrl);
// This event is triggered when the iframe calls "alert".
iframe.addEventListener('mozbrowsershowmodalprompt', function listener(aEvent) {
var message = aEvent.detail.message;
if (/^OK /.exec(message)) {
ok(true, "Message from iframe: " + message);
} else if (/^KO /.exec(message)) {
ok(false, "Message from iframe: " + message);
} else if (/^INFO /.exec(message)) {
info("Message from iframe: " + message);
} else if (/^COMMAND /.exec(message)) {
var command = JSON.parse(message.replace(/^COMMAND /, ''));
gScript.sendAsyncMessage(command.name, command.data);
} else if (/^DONE$/.exec(message)) {
ok(true, "Messaging from iframe complete.");
iframe.removeEventListener('mozbrowsershowmodalprompt', listener);
teardown();
}
}, false);
var promise = new Promise(function(aResolve, aReject) {
document.body.appendChild(iframe);
aResolve(iframe);
});
obs.notifyObservers(promise, 'setup-request-promise', null);
gScript.addMessageListener('offer-received', function offerReceivedHandler() {
gScript.removeMessageListener('offer-received', offerReceivedHandler);
info("An offer is received.");
});
gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
is(aReason, SpecialPowers.Cr.NS_OK, "The control channel is closed normally.");
});
gScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
gScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
is(aReason, SpecialPowers.Cr.NS_OK, "The data transport should be closed normally.");
});
aResolve();
});
}
function testIncomingSessionRequest() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('receiver-launching', function launchReceiverHandler(aSessionId) {
gScript.removeMessageListener('receiver-launching', launchReceiverHandler);
info("Trying to launch receiver page.");
aResolve();
});
gScript.sendAsyncMessage('trigger-incoming-session-request', receiverUrl);
});
}
function teardown() {
gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
gScript.destroy();
SimpleTest.finish();
});
gScript.sendAsyncMessage('teardown');
}
function runTests() {
setup().
then(testIncomingSessionRequest);
}
SimpleTest.expectAssertions(0, 5);
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: false, context: document},
{type: 'presentation', allow: true, context: document},
{type: 'browser', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0],
["dom.mozBrowserFramesEnabled", true],
["dom.ipc.browser_frames.oop_by_default", true]]},
runTests);
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,110 @@
<!DOCTYPE HTML>
<html>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<head>
<meta charset="utf-8">
<title>Test for startSession errors of B2G Presentation API at receiver side</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1069230">Test for startSession errors of B2G Presentation API at receiver side</a>
<script type="application/javascript;version=1.8">
'use strict';
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript.js'));
var receiverUrl = SimpleTest.getTestFileURL('file_presentation_receiver_start_session_error.html');
var obs = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
.getService(SpecialPowers.Ci.nsIObserverService);
var session;
function setup() {
return new Promise(function(aResolve, aReject) {
gScript.sendAsyncMessage('trigger-device-add');
var iframe = document.createElement('iframe');
iframe.setAttribute('src', receiverUrl);
// This event is triggered when the iframe calls "postMessage".
window.addEventListener('message', function listener(aEvent) {
var message = aEvent.data;
if (/^OK /.exec(message)) {
ok(true, "Message from iframe: " + message);
} else if (/^KO /.exec(message)) {
ok(false, "Message from iframe: " + message);
} else if (/^INFO /.exec(message)) {
info("Message from iframe: " + message);
} else if (/^COMMAND /.exec(message)) {
var command = JSON.parse(message.replace(/^COMMAND /, ''));
gScript.sendAsyncMessage(command.name, command.data);
} else if (/^DONE$/.exec(message)) {
ok(true, "Messaging from iframe complete.");
window.removeEventListener('message', listener);
teardown();
}
}, false);
var promise = new Promise(function(aResolve, aReject) {
document.body.appendChild(iframe);
aResolve(iframe);
});
obs.notifyObservers(promise, 'setup-request-promise', null);
gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
is(aReason, 0x80004004 /* NS_ERROR_ABORT */, "The control channel is closed abnormally.");
});
aResolve();
});
}
function testIncomingSessionRequest() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('receiver-launching', function launchReceiverHandler(aSessionId) {
gScript.removeMessageListener('receiver-launching', launchReceiverHandler);
info("Trying to launch receiver page.");
aResolve();
});
gScript.sendAsyncMessage('trigger-incoming-session-request', receiverUrl);
});
}
function teardown() {
gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
gScript.destroy();
SimpleTest.finish();
});
gScript.sendAsyncMessage('teardown');
}
function runTests() {
setup().
then(testIncomingSessionRequest);
}
SimpleTest.expectAssertions(0, 5);
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: false, context: document},
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0]]},
runTests);
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,84 @@
<!DOCTYPE HTML>
<html>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<head>
<meta charset="utf-8">
<title>Test for startSession timeout of B2G Presentation API at receiver side</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1069230">Test for startSession timeout of B2G Presentation API at receiver side</a>
<script type="application/javascript;version=1.8">
'use strict';
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript.js'));
var obs = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
.getService(SpecialPowers.Ci.nsIObserverService);
function setup() {
return new Promise(function(aResolve, aReject) {
gScript.sendAsyncMessage('trigger-device-add');
var promise = new Promise(function(aResolve, aReject) {
// In order to trigger timeout, do not resolve the promise.
});
obs.notifyObservers(promise, 'setup-request-promise', null);
aResolve();
});
}
function testIncomingSessionRequestReceiverLaunchTimeout() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('receiver-launching', function launchReceiverHandler(aSessionId) {
gScript.removeMessageListener('receiver-launching', launchReceiverHandler);
info("Trying to launch receiver page.");
});
gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
is(aReason, 0x80530017 /* NS_ERROR_DOM_TIMEOUT_ERR */, "The control channel is closed due to timeout.");
aResolve();
});
gScript.sendAsyncMessage('trigger-incoming-session-request', 'http://example.com');
});
}
function teardown() {
gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
gScript.destroy();
SimpleTest.finish();
});
gScript.sendAsyncMessage('teardown');
}
function runTests() {
setup().
then(testIncomingSessionRequestReceiverLaunchTimeout).
then(teardown);
}
SimpleTest.expectAssertions(0, 5);
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: false, context: document},
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0],
["presentation.receiver.loading.timeout", 10]]},
runTests);
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,167 @@
<!DOCTYPE HTML>
<html>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<head>
<meta charset="utf-8">
<title>Test for B2G Presentation API at sender side</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1069230">Test for B2G Presentation API at sender side</a>
<script type="application/javascript;version=1.8">
'use strict';
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript.js'));
var presentation;
var session;
function testSetup() {
return new Promise(function(aResolve, aReject) {
presentation.onavailablechange = function(aIsAvailable) {
presentation.onavailablechange = null;
ok(aIsAvailable, "Device should be available.");
aResolve();
};
gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartSession() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
info("Device prompt is triggered.");
gScript.sendAsyncMessage('trigger-device-prompt-select');
});
gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
info("A control channel is established.");
});
gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
info("The control channel is closed. " + aReason);
});
gScript.addMessageListener('offer-sent', function offerSentHandler() {
gScript.removeMessageListener('offer-sent', offerSentHandler);
info("An offer is sent out.");
gScript.sendAsyncMessage('trigger-incoming-transport');
});
gScript.addMessageListener('answer-received', function answerReceivedHandler() {
gScript.removeMessageListener('answer-received', answerReceivedHandler);
info("An answer is received.");
});
gScript.addMessageListener('data-transport-initialized', function dataTransportInitializedHandler() {
gScript.removeMessageListener('data-transport-initialized', dataTransportInitializedHandler);
info("Data transport channel is initialized.");
gScript.sendAsyncMessage('trigger-incoming-answer');
});
presentation.startSession("http://example.com").then(
function(aSession) {
session = aSession;
ok(session, "Session should be availlable.");
ok(session.id, "Session ID should be set.");
is(session.state, "connected", "Session state at sender side should be connected by default.");
aResolve();
},
function(aError) {
ok(false, "Error occurred when starting session: " + aError);
teardown();
aReject();
}
);
});
}
function testSend() {
return new Promise(function(aResolve, aReject) {
const outgoingMessage = "test outgoing message";
gScript.addMessageListener('message-sent', function messageSentHandler(aMessage) {
gScript.removeMessageListener('message-sent', messageSentHandler);
is(aMessage, outgoingMessage, "The message is sent out.");
aResolve();
});
session.send(outgoingMessage);
});
}
function testIncomingMessage() {
return new Promise(function(aResolve, aReject) {
const incomingMessage = "test incoming message";
session.addEventListener('message', function messageHandler(aEvent) {
session.removeEventListener('message', messageHandler);
is(aEvent.data, incomingMessage, "An incoming message should be received.");
aResolve();
});
gScript.sendAsyncMessage('trigger-incoming-message', incomingMessage);
});
}
function testCloseSession() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
gScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
info("The data transport is closed. " + aReason);
});
session.onstatechange = function() {
session.onstatechange = null;
is(session.state, "terminated", "Session should be terminated.");
aResolve();
};
session.close();
});
}
function teardown() {
gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
gScript.destroy();
SimpleTest.finish();
});
gScript.sendAsyncMessage('teardown');
}
function runTests() {
ok(navigator.presentation, "navigator.presentation should be available.");
presentation = navigator.presentation;
testSetup().
then(testStartSession).
then(testSend).
then(testIncomingMessage).
then(testCloseSession).
then(teardown);
}
SimpleTest.expectAssertions(0, 5);
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: false, context: document},
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0]]},
runTests);
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,150 @@
<!DOCTYPE HTML>
<html>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<head>
<meta charset="utf-8">
<title>Test for session disconnection of B2G Presentation API at sender side</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1069230">Test for session disconnection of B2G Presentation API at sender side</a>
<script type="application/javascript;version=1.8">
'use strict';
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript.js'));
var presentation;
var session;
function testSetup() {
return new Promise(function(aResolve, aReject) {
presentation.onavailablechange = function(aIsAvailable) {
presentation.onavailablechange = null;
ok(aIsAvailable, "Device should be available.");
aResolve();
};
gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartSession() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
info("Device prompt is triggered.");
gScript.sendAsyncMessage('trigger-device-prompt-select');
});
gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
info("A control channel is established.");
});
gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
info("The control channel is closed. " + aReason);
});
gScript.addMessageListener('offer-sent', function offerSentHandler() {
gScript.removeMessageListener('offer-sent', offerSentHandler);
info("An offer is sent out.");
gScript.sendAsyncMessage('trigger-incoming-answer');
});
gScript.addMessageListener('answer-received', function answerReceivedHandler() {
gScript.removeMessageListener('answer-received', answerReceivedHandler);
info("An answer is received.");
gScript.sendAsyncMessage('trigger-incoming-transport');
});
gScript.addMessageListener('data-transport-initialized', function dataTransportInitializedHandler() {
gScript.removeMessageListener('data-transport-initialized', dataTransportInitializedHandler);
info("Data transport channel is initialized.");
});
presentation.startSession("http://example.com").then(
function(aSession) {
session = aSession;
ok(session, "Session should be availlable.");
ok(session.id, "Session ID should be set.");
is(session.state, "connected", "Session state at sender side should be connected by default.");
aResolve();
},
function(aError) {
ok(false, "Error occurred when starting session: " + aError);
teardown();
aReject();
}
);
});
}
function testSessionDisconnection() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
gScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
info("The data transport is closed. " + aReason);
});
session.onstatechange = function() {
session.onstatechange = null;
is(session.state, "disconnected", "Session should be disconnected.");
aResolve();
};
gScript.sendAsyncMessage('trigger-data-transport-close', SpecialPowers.Cr.NS_ERROR_FAILURE);
});
}
function testCloseSession() {
return new Promise(function(aResolve, aReject) {
session.onstatechange = function() {
session.onstatechange = null;
is(session.state, "terminated", "Session should be terminated.");
aResolve();
};
session.close();
});
}
function teardown() {
gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
gScript.destroy();
SimpleTest.finish();
});
gScript.sendAsyncMessage('teardown');
}
function runTests() {
ok(navigator.presentation, "navigator.presentation should be available.");
presentation = navigator.presentation;
testSetup().
then(testStartSession).
then(testSessionDisconnection).
then(testCloseSession).
then(teardown);
}
SimpleTest.expectAssertions(0, 5);
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: false, context: document},
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0]]},
runTests);
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,239 @@
<!DOCTYPE HTML>
<html>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<head>
<meta charset="utf-8">
<title>Test for startSession errors of B2G Presentation API at sender side</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1069230">Test for startSession errors of B2G Presentation API at sender side</a>
<script type="application/javascript;version=1.8">
'use strict';
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationSessionChromeScript.js'));
var presentation;
function setup() {
return new Promise(function(aResolve, aReject) {
presentation.onavailablechange = function(aIsAvailable) {
presentation.onavailablechange = null;
ok(aIsAvailable, "Device should be available.");
aResolve();
};
gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartSessionNoAvailableDevice() {
return new Promise(function(aResolve, aReject) {
presentation.startSession("http://example.com").then(
function(aSession) {
ok(false, "startSession shouldn't succeed in this case.");
aReject();
},
function(aError) {
is(aError.name, "InvalidStateError", "InvalidStateError is expected when starting session.");
aResolve();
}
);
});
}
function testStartSessionCancelPrompt() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
info("Device prompt is triggered.");
gScript.sendAsyncMessage('trigger-device-prompt-cancel');
});
presentation.startSession("http://example.com").then(
function(aSession) {
ok(false, "startSession shouldn't succeed in this case.");
aReject();
},
function(aError) {
is(aError.name, "NS_ERROR_DOM_PROP_ACCESS_DENIED", "NS_ERROR_DOM_PROP_ACCESS_DENIED is expected when starting session.");
aResolve();
}
);
});
}
function testStartSessionUnexpectedControlChannelCloseBeforeDataTransportInit() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
info("Device prompt is triggered.");
gScript.sendAsyncMessage('trigger-device-prompt-select');
});
gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
info("A control channel is established.");
});
gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
info("The control channel is closed. " + aReason);
});
gScript.addMessageListener('offer-sent', function offerSentHandler() {
gScript.removeMessageListener('offer-sent', offerSentHandler);
info("An offer is sent out.");
gScript.sendAsyncMessage('trigger-control-channel-close', SpecialPowers.Cr.NS_ERROR_FAILURE);
});
presentation.startSession("http://example.com").then(
function(aSession) {
ok(false, "startSession shouldn't succeed in this case.");
aReject();
},
function(aError) {
is(aError.name, "NS_ERROR_FAILURE", "NS_ERROR_FAILURE is expected when starting session.");
aResolve();
}
);
});
}
function testStartSessionUnexpectedControlChannelCloseBeforeDataTransportReady() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
info("Device prompt is triggered.");
gScript.sendAsyncMessage('trigger-device-prompt-select');
});
gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
info("A control channel is established.");
});
gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
info("The control channel is closed. " + aReason);
});
gScript.addMessageListener('offer-sent', function offerSentHandler() {
gScript.removeMessageListener('offer-sent', offerSentHandler);
info("An offer is sent out.");
gScript.sendAsyncMessage('trigger-incoming-transport');
});
gScript.addMessageListener('data-transport-initialized', function dataTransportInitializedHandler() {
gScript.removeMessageListener('data-transport-initialized', dataTransportInitializedHandler);
info("Data transport channel is initialized.");
gScript.sendAsyncMessage('trigger-control-channel-close', SpecialPowers.Cr.NS_ERROR_ABORT);
});
gScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
gScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
info("The data transport is closed. " + aReason);
});
presentation.startSession("http://example.com").then(
function(aSession) {
ok(false, "startSession shouldn't succeed in this case.");
aReject();
},
function(aError) {
is(aError.name, "NS_ERROR_ABORT", "NS_ERROR_ABORT is expected when starting session.");
aResolve();
}
);
});
}
function testStartSessionUnexpectedDataTransportClose() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
info("Device prompt is triggered.");
gScript.sendAsyncMessage('trigger-device-prompt-select');
});
gScript.addMessageListener('control-channel-established', function controlChannelEstablishedHandler() {
gScript.removeMessageListener('control-channel-established', controlChannelEstablishedHandler);
info("A control channel is established.");
});
gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
info("The control channel is closed. " + aReason);
});
gScript.addMessageListener('offer-sent', function offerSentHandler() {
gScript.removeMessageListener('offer-sent', offerSentHandler);
info("An offer is sent out.");
gScript.sendAsyncMessage('trigger-incoming-transport');
});
gScript.addMessageListener('data-transport-initialized', function dataTransportInitializedHandler() {
gScript.removeMessageListener('data-transport-initialized', dataTransportInitializedHandler);
info("Data transport channel is initialized.");
gScript.sendAsyncMessage('trigger-data-transport-close', SpecialPowers.Cr.NS_ERROR_UNEXPECTED);
});
gScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
gScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
info("The data transport is closed. " + aReason);
});
presentation.startSession("http://example.com").then(
function(aSession) {
ok(false, "startSession shouldn't succeed in this case.");
aReject();
},
function(aError) {
is(aError.name, "NS_ERROR_UNEXPECTED", "NS_ERROR_UNEXPECTED is expected when starting session.");
aResolve();
}
);
});
}
function teardown() {
gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
gScript.destroy();
SimpleTest.finish();
});
gScript.sendAsyncMessage('teardown');
}
function runTests() {
ok(navigator.presentation, "navigator.presentation should be available.");
presentation = navigator.presentation;
testStartSessionNoAvailableDevice().
then(setup).
then(testStartSessionCancelPrompt).
then(testStartSessionUnexpectedControlChannelCloseBeforeDataTransportInit).
then(testStartSessionUnexpectedControlChannelCloseBeforeDataTransportReady).
then(testStartSessionUnexpectedDataTransportClose).
then(teardown);
}
SimpleTest.expectAssertions(0, 5);
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: false, context: document},
{type: 'presentation', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.presentation.test.enabled", true],
["dom.presentation.test.stage", 0]]},
runTests);
});
</script>
</body>
</html>