|  | <!doctype html> | 
|  | <!-- | 
|  | This test uses data only, and thus does not require fake media devices. | 
|  | --> | 
|  |  | 
|  | <html> | 
|  | <head> | 
|  | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | 
|  | <title>RTCPeerConnection Data-Only Connection Test with Promises</title> | 
|  | </head> | 
|  | <body> | 
|  | <div id="log"></div> | 
|  | <h2>iceConnectionState info</h2> | 
|  | <div id="stateinfo"> | 
|  | </div> | 
|  |  | 
|  | <!-- These files are in place when executing on W3C. --> | 
|  | <script src="/resources/testharness.js"></script> | 
|  | <script src="/resources/testharnessreport.js"></script> | 
|  | <script type="text/javascript"> | 
|  | var test = async_test('Can set up a basic WebRTC call with only data using promises.'); | 
|  |  | 
|  | var gFirstConnection = null; | 
|  | var gSecondConnection = null; | 
|  |  | 
|  | var onIceCandidateToFirst = test.step_func(function(event) { | 
|  | // If event.candidate is null = no more candidates. | 
|  | if (event.candidate) { | 
|  | gSecondConnection.addIceCandidate(event.candidate); | 
|  | } | 
|  | }); | 
|  |  | 
|  | var onIceCandidateToSecond = test.step_func(function(event) { | 
|  | if (event.candidate) { | 
|  | gFirstConnection.addIceCandidate(event.candidate); | 
|  | } | 
|  | }); | 
|  |  | 
|  | var onRemoteStream = test.step_func(function(event) { | 
|  | assert_unreached('WebRTC received a stream when there was none'); | 
|  | }); | 
|  |  | 
|  | var onIceConnectionStateChange = test.step_func(function(event) { | 
|  | assert_equals(event.type, 'iceconnectionstatechange'); | 
|  | var stateinfo = document.getElementById('stateinfo'); | 
|  | stateinfo.innerHTML = 'First: ' + gFirstConnection.iceConnectionState | 
|  | + '<br>Second: ' + gSecondConnection.iceConnectionState; | 
|  | // Note: All these combinations are legal states indicating that the | 
|  | // call has connected. All browsers should end up in completed/completed, | 
|  | // but as of this moment, we've chosen to terminate the test early. | 
|  | // TODO: Revise test to ensure completed/completed is reached. | 
|  | if (gFirstConnection.iceConnectionState == 'connected' && | 
|  | gSecondConnection.iceConnectionState == 'connected') { | 
|  | test.done() | 
|  | } | 
|  | if (gFirstConnection.iceConnectionState == 'connected' && | 
|  | gSecondConnection.iceConnectionState == 'completed') { | 
|  | test.done() | 
|  | } | 
|  | if (gFirstConnection.iceConnectionState == 'completed' && | 
|  | gSecondConnection.iceConnectionState == 'connected') { | 
|  | test.done() | 
|  | } | 
|  | if (gFirstConnection.iceConnectionState == 'completed' && | 
|  | gSecondConnection.iceConnectionState == 'completed') { | 
|  | test.done() | 
|  | } | 
|  | }); | 
|  |  | 
|  | // This function starts the test. | 
|  | test.step(function() { | 
|  | gFirstConnection = new RTCPeerConnection(null); | 
|  | gFirstConnection.onicecandidate = onIceCandidateToFirst; | 
|  | gFirstConnection.oniceconnectionstatechange = onIceConnectionStateChange; | 
|  |  | 
|  | gSecondConnection = new RTCPeerConnection(null); | 
|  | gSecondConnection.onicecandidate = onIceCandidateToSecond; | 
|  | gSecondConnection.onaddstream = onRemoteStream; | 
|  | gSecondConnection.oniceconnectionstatechange = onIceConnectionStateChange; | 
|  |  | 
|  | // The createDataChannel is necessary and sufficient to make | 
|  | // sure the ICE connection be attempted. | 
|  | gFirstConnection.createDataChannel('channel'); | 
|  |  | 
|  | var atStep = 'Create offer'; | 
|  |  | 
|  | gFirstConnection.createOffer() | 
|  | .then(function(offer) { | 
|  | atStep = 'Set local description at first'; | 
|  | return gFirstConnection.setLocalDescription(offer); | 
|  | }) | 
|  | .then(function() { | 
|  | atStep = 'Set remote description at second'; | 
|  | return gSecondConnection.setRemoteDescription( | 
|  | gFirstConnection.localDescription); | 
|  | }) | 
|  | .then(function() { | 
|  | atStep = 'Create answer'; | 
|  | return gSecondConnection.createAnswer(); | 
|  | }) | 
|  | .then(function(answer) { | 
|  | atStep = 'Set local description at second'; | 
|  | return gSecondConnection.setLocalDescription(answer); | 
|  | }) | 
|  | .then(function() { | 
|  | atStep = 'Set remote description at first'; | 
|  | return gFirstConnection.setRemoteDescription( | 
|  | gSecondConnection.localDescription); | 
|  | }) | 
|  | .then(function() { | 
|  | atStep = 'Negotiation completed'; | 
|  | }) | 
|  | .catch(test.step_func(function(e) { | 
|  | assert_unreached('Error ' + e.name + ': ' + e.message + | 
|  | ' happened at step ' + atStep); | 
|  | })); | 
|  | }); | 
|  | </script> | 
|  |  | 
|  | </body> | 
|  | </html> |