|  | <!doctype html> | 
|  | <!-- | 
|  | This test creates a data channel between two local PeerConnection instances | 
|  | and ensures that an empty string sent by one is received by the second. | 
|  | --> | 
|  |  | 
|  | <html> | 
|  | <head> | 
|  | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | 
|  | <title>RTCPeerConnection Data Channel Empty String Test</title> | 
|  | </head> | 
|  | <body> | 
|  | <div id="log"></div> | 
|  | <h2>Messages exchanged</h2> | 
|  | <div id="msg"></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 send empty strings across a WebRTC data channel.'); | 
|  |  | 
|  | var gFirstConnection = null; | 
|  | var gSecondConnection = null; | 
|  | var sendChannel = null; | 
|  | var receiveChannel = null; | 
|  |  | 
|  | var onReceiveChannel = function (event) { | 
|  | receiveChannel = event.channel; | 
|  | receiveChannel.onmessage = onReceiveMessage; | 
|  | }; | 
|  |  | 
|  |  | 
|  | // When the data channel is open, send an empty string message | 
|  | // followed by a message that contains the string "done". | 
|  | var onSendChannelOpen = test.step_func(function (event) { | 
|  | var msgEl = document.getElementById('msg'); | 
|  | sendChannel.send(''); | 
|  | msgEl.innerHTML += 'Sent: [empty string]<br>'; | 
|  | sendChannel.send('done'); | 
|  | msgEl.innerHTML += 'Sent: "done"<br>'; | 
|  | }); | 
|  |  | 
|  | // Check the messages received on the other side. | 
|  | // There should be an empty string message followed by a message that | 
|  | // contains the string "done". | 
|  | // Pass/Fail the test according to the messages received | 
|  | var emptyMessageReceived = false; | 
|  | var onReceiveMessage = test.step_func(function (event) { | 
|  | var msgEl = document.getElementById('msg'); | 
|  | msgEl.innerHTML += 'Received: ' + | 
|  | (event.data ? '"' + event.data + '"' : '[empty string]') + '<br>'; | 
|  | if (emptyMessageReceived) { | 
|  | assert_equals(event.data, 'done', 'The "done" message was not received'); | 
|  | test.done(); | 
|  | } | 
|  | else { | 
|  | assert_equals(event.data, '', 'Empty message not received'); | 
|  | emptyMessageReceived = true; | 
|  | } | 
|  | }); | 
|  |  | 
|  | function exchangeIce(pc) { | 
|  | return function(e) { | 
|  | if (e.candidate) { | 
|  | pc.addIceCandidate(e.candidate); | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | function exchangeDescription(pc1, pc2) { | 
|  | return function() { | 
|  | return pc1.setRemoteDescription(pc2.localDescription); | 
|  | }; | 
|  | } | 
|  |  | 
|  | test.step(function() { | 
|  | gFirstConnection = new RTCPeerConnection(null); | 
|  |  | 
|  | gSecondConnection = new RTCPeerConnection(null); | 
|  |  | 
|  | gFirstConnection.onicecandidate = exchangeIce(gSecondConnection); | 
|  | gSecondConnection.onicecandidate = exchangeIce(gFirstConnection); | 
|  |  | 
|  | gSecondConnection.ondatachannel = onReceiveChannel; | 
|  |  | 
|  | // Note the data channel will preserve the order of messages | 
|  | // exchanged over it by default. | 
|  | sendChannel = gFirstConnection.createDataChannel('sendDataChannel'); | 
|  | sendChannel.onopen = onSendChannelOpen; | 
|  |  | 
|  | gFirstConnection.createOffer() | 
|  | .then(gFirstConnection.setLocalDescription.bind(gFirstConnection)) | 
|  | .then(exchangeDescription(gSecondConnection, gFirstConnection)) | 
|  | .then(function() { | 
|  | return gSecondConnection.createAnswer(); | 
|  | }) | 
|  | .then(gSecondConnection.setLocalDescription.bind(gSecondConnection)) | 
|  | .then(exchangeDescription(gFirstConnection, gSecondConnection)) | 
|  | .catch(test.step_func(function(e) { | 
|  | assert_unreached('Error ' + e.name + ': ' + e.message); | 
|  | })); | 
|  | }); | 
|  | </script> | 
|  |  | 
|  | </body> | 
|  | </html> | 
|  |  |