Chromium Code Reviews| Index: chrome/test/data/webrtc/message_handling.js |
| diff --git a/chrome/test/data/webrtc/message_handling.js b/chrome/test/data/webrtc/message_handling.js |
| index 377f95f1aa63298f77b5e8e95334f55ba27f5a14..6329ed303480e5863dcfbecbe23664f2becfa87b 100644 |
| --- a/chrome/test/data/webrtc/message_handling.js |
| +++ b/chrome/test/data/webrtc/message_handling.js |
| @@ -5,162 +5,117 @@ |
| */ |
| // This file requires these functions to be defined globally by someone else: |
| -// function handleMessage(peerConnection, message) |
| // function createPeerConnection(stun_server, useRtpDataChannel) |
| -// function setupCall(peerConnection) |
| -// function answerCall(peerConnection, message) |
| +// function createOffer(peerConnection, constraints, callback) |
| +// function receiveOffer(peerConnection, offer, constraints, callback) |
| +// function receiveAnswer(peerConnection, answer, callback) |
| // Currently these functions are supplied by jsep01_call.js. |
| /** |
| - * This object represents the call. |
| - * @private |
| - */ |
| -var gPeerConnection = null; |
| - |
| -/** |
| - * True if we are accepting incoming calls. |
| - * @private |
| - */ |
| -var gAcceptsIncomingCalls = true; |
| - |
| -/** |
| - * Our peer id as assigned by the peerconnection_server. |
| - * @private |
| - */ |
| -var gOurPeerId = null; |
| - |
| -/** |
| - * The client id we use to identify to peerconnection_server. |
| - * @private |
| - */ |
| -var gOurClientName = null; |
| - |
| -/** |
| - * The URL to the peerconnection_server. |
| - * @private |
| - */ |
| -var gServerUrl = null; |
| - |
| -/** |
| - * The remote peer's id. We receive this one either when we connect (in the case |
| - * our peer connects before us) or in a notification later. |
| + * We need a STUN server for some API calls. |
| * @private |
| */ |
| -var gRemotePeerId = null; |
| +var STUN_SERVER = 'stun.l.google.com:19302'; |
| /** |
| - * Whether or not to auto-respond by adding our local stream when we are called. |
| + * This object represents the call. |
| * @private |
| */ |
| -var gAutoAddLocalToPeerConnectionStreamWhenCalled = true; |
| +var gPeerConnection = null; |
| /** |
| - * The one and only data channel. |
| - * @private |
| + * If true, any created peer connection will use RTP data |
| + * channels. Otherwise it will use SCTP data channels. |
| */ |
| -var gDataChannel = null; |
| +var gUseRtpDataChannels = true; |
| /** |
| - * The DTMF sender. |
| + * This stores ICE candidates generated on this side. |
| * @private |
| */ |
| -var gDtmfSender = null; |
| +var gIceCandidates = []; |
| -/** |
| - * We need a STUN server for some API calls. |
| - * @private |
| - */ |
| -var STUN_SERVER = 'stun.l.google.com:19302'; |
| +// Public interface to tests. These are expected to be called with |
| +// ExecuteJavascript invocations from the browser tests and will return answers |
| +// through the DOM automation controller. |
| /** |
| - * If true, any created peer connection will use RTP data |
| - * channels. Otherwise it will use SCTP data channels. |
| + * Creates a peer connection. Must be called before most other public functions |
| + * in this file. |
| */ |
| -var gUseRtpDataChannels = true; |
| - |
| -// Public interface to tests. |
| +function preparePeerConnection() { |
| + if (gPeerConnection != null) |
| + throw failTest('creating peer connection, but we already have one.'); |
| + gPeerConnection = createPeerConnection(STUN_SERVER, gUseRtpDataChannels); |
| + returnToTest('ok-peerconnection-created'); |
| +} |
| /** |
| - * Connects to the provided peerconnection_server. |
| + * Asks this page to create a local offer. |
| * |
| - * @param{string} serverUrl The server URL in string form without an ending |
| - * slash, something like http://localhost:8888. |
| - * @param{string} clientName The name to use when connecting to the server. |
| + * Returns a string on the format ok-(JSON encoded session description). |
| + * |
| + * @param {!object} constraints Any createOffer constraints. |
| */ |
| -function connect(serverUrl, clientName) { |
| - if (gOurPeerId != null) |
| - throw failTest('connecting, but is already connected.'); |
| - |
| - debug('Connecting to ' + serverUrl + ' as ' + clientName); |
| - gServerUrl = serverUrl; |
| - gOurClientName = clientName; |
| - |
| - request = new XMLHttpRequest(); |
| - request.open('GET', serverUrl + '/sign_in?' + clientName, true); |
| - debug(serverUrl + '/sign_in?' + clientName); |
| - request.onreadystatechange = function() { |
| - connectCallback_(request); |
| - } |
| - request.send(); |
| -} |
| +function createLocalOffer(constraints) { |
| + if (gPeerConnection == null) |
| + throw failTest('Negotiating call, but we have no peer connection.'); |
| -/** |
| - * Checks if the remote peer has connected. Returns peer-connected if that is |
| - * the case, otherwise no-peer-connected. |
| - */ |
| -function remotePeerIsConnected() { |
| - if (gRemotePeerId == null) |
| - returnToTest('no-peer-connected'); |
| - else |
| - returnToTest('peer-connected'); |
| + // TODO(phoglund): move jsep01.call stuff into this file and remove need |
| + // of the createOffer method, etc. |
| + createOffer(gPeerConnection, constraints, function(localOffer) { |
| + returnToTest('ok-' + JSON.stringify(localOffer)); |
| + }); |
| } |
| /** |
| - * Set if RTP data channels should be used for peerconnections. |
| - * @param{boolean} useRtpDataChannel |
| + * Asks this page to accept an offer and generate an answer. |
| + * |
| + * Returns a string on the format ok-(JSON encoded session description). |
|
kjellander_chromium
2014/05/08 09:11:50
nit: use @return {!string} instead (more below)
phoglund_chromium
2014/05/08 13:27:42
The function doesn't really return on the javascri
|
| + * |
| + * @param {!string} sessionDescJson A JSON-encoded session description of type |
| + * 'offer'. |
| + * @param {!object} constraints Any createAnswer constraints. |
|
kjellander_chromium
2014/05/08 09:11:50
nit: {!Object} (more below)
phoglund_chromium
2014/05/08 13:27:42
Done.
|
| */ |
| -function useRtpDataChannelsForNewPeerConnections(useRtpDataChannels) { |
| - gUseRtpDataChannels = useRtpDataChannels; |
| -} |
| +function receiveOfferFromPeer(sessionDescJson, constraints) { |
| + if (gPeerConnection == null) |
| + throw failTest('Receiving offer, but we have no peer connection.'); |
| -/** |
| - * Creates a peer connection. Must be called before most other public functions |
| - * in this file. |
| - */ |
| -function preparePeerConnection() { |
| - if (gPeerConnection != null) |
| - throw failTest('creating peer connection, but we already have one.'); |
| + offer = parseJson_(sessionDescJson); |
| + if (!offer.type) |
| + failTest('Got invalid session description from peer: ' + sessionDescJson); |
| + if (offer.type != 'offer') |
| + failTest('Expected to receive offer from peer, got ' + offer.type); |
| - gPeerConnection = createPeerConnection(STUN_SERVER, gUseRtpDataChannels); |
| - returnToTest('ok-peerconnection-created'); |
| + receiveOffer(gPeerConnection, offer , constraints, function(answer) { |
| + returnToTest('ok-' + JSON.stringify(answer)); |
| + }); |
| } |
| /** |
| - * Negotiates a call with the other side. This will create a peer connection on |
| - * the other side if there isn't one. The other side will automatically add any |
| - * stream it has unless doNotAutoAddLocalStreamWhenCalled() has been called. |
| + * Asks this page to accept an answer generated by the peer in response to a |
| + * previous offer by this page |
|
kjellander_chromium
2014/05/08 09:11:50
nit: end with punctuation.
phoglund_chromium
2014/05/08 13:27:42
Done.
|
| * |
| - * To call this method we need to be aware of the other side, e.g. we must be |
| - * connected to peerconnection_server and we must have exactly one peer on that |
| - * server. |
| + * Returns a string ok-accepted-answer on success. |
| * |
| - * This method may be called any number of times. If you haven't added any |
| - * streams to the call, an "empty" call will result. The method will return |
| - * ok-negotiating immediately to the test if the negotiation was successfully |
| - * sent. |
| + * @param {!string} sessionDescJson A JSON-encoded session description of type |
| + * 'answer'. |
| */ |
| -function negotiateCall() { |
| +function receiveAnswerFromPeer(sessionDescJson) { |
| if (gPeerConnection == null) |
| - throw failTest('negotiating call, but we have no peer connection.'); |
| - if (gOurPeerId == null) |
| - throw failTest('negotiating call, but not connected.'); |
| - if (gRemotePeerId == null) |
| - throw failTest('negotiating call, but missing remote peer.'); |
| - |
| - setupCall(gPeerConnection); |
| - returnToTest('ok-negotiating'); |
| + throw failTest('Receiving offer, but we have no peer connection.'); |
| + |
| + answer = parseJson_(sessionDescJson); |
| + if (!answer.type) |
| + failTest('Got invalid session description from peer: ' + sessionDescJson); |
| + if (answer.type != 'answer') |
| + failTest('Expected to receive answer from peer, got ' + answer.type); |
| + |
| + receiveAnswer(gPeerConnection, answer, function() { |
| + returnToTest('ok-accepted-answer'); |
| + }); |
| } |
| /** |
| @@ -226,374 +181,86 @@ function playAudioFile() { |
| } |
| /** |
| - * Removes the local stream from the peer connection. You will have to |
| - * re-negotiate the call for this to take effect in the call. |
| - */ |
| -function removeLocalStream() { |
| - if (gPeerConnection == null) |
| - throw failTest('attempting to remove local stream, but no call is up'); |
| - |
| - removeLocalStreamFromPeerConnection(gPeerConnection); |
| - returnToTest('ok-local-stream-removed'); |
| -} |
| - |
| -/** |
| - * (see getReadyState) |
| - */ |
| -function getPeerConnectionReadyState() { |
| - returnToTest(getReadyState()); |
| -} |
| - |
| -/** |
| - * Toggles the remote audio stream's enabled state on the peer connection, given |
| - * that a call is active. Returns ok-[typeToToggle]-toggled-to-[true/false] |
| - * on success. |
| - * |
| - * @param selectAudioOrVideoTrack: A function that takes a remote stream as |
| - * argument and returns a track (e.g. either the video or audio track). |
| - * @param typeToToggle: Either "audio" or "video" depending on what the selector |
| - * function selects. |
| - */ |
| -function toggleRemoteStream(selectAudioOrVideoTrack, typeToToggle) { |
| - if (gPeerConnection == null) |
| - throw failTest('Tried to toggle remote stream, ' + |
| - 'but have no peer connection.'); |
| - if (gPeerConnection.getRemoteStreams().length == 0) |
| - throw failTest('Tried to toggle remote stream, ' + |
| - 'but not receiving any stream.'); |
| - |
| - var track = selectAudioOrVideoTrack(gPeerConnection.getRemoteStreams()[0]); |
| - toggle_(track, 'remote', typeToToggle); |
| -} |
| - |
| -/** |
| - * See documentation on toggleRemoteStream (this function is the same except |
| - * we are looking at local streams). |
| - */ |
| -function toggleLocalStream(selectAudioOrVideoTrack, typeToToggle) { |
| - if (gPeerConnection == null) |
| - throw failTest('Tried to toggle local stream, ' + |
| - 'but have no peer connection.'); |
| - if (gPeerConnection.getLocalStreams().length == 0) |
| - throw failTest('Tried to toggle local stream, but there is no local ' + |
| - 'stream in the call.'); |
| - |
| - var track = selectAudioOrVideoTrack(gPeerConnection.getLocalStreams()[0]); |
| - toggle_(track, 'local', typeToToggle); |
| -} |
| - |
| -/** |
| - * Hangs up a started call. Returns ok-call-hung-up on success. This tab will |
| - * not accept any incoming calls after this call. |
| + * Hangs up a started call. Returns ok-call-hung-up on success. |
| */ |
| function hangUp() { |
| if (gPeerConnection == null) |
| throw failTest('hanging up, but has no peer connection'); |
| - if (getReadyState() != 'active') |
| - throw failTest('hanging up, but ready state is not active (no call up).'); |
| - sendToPeer(gRemotePeerId, 'BYE'); |
| - closeCall_(); |
| - gAcceptsIncomingCalls = false; |
| + gPeerConnection.close(); |
| + gPeerConnection = null; |
| returnToTest('ok-call-hung-up'); |
| } |
| /** |
| - * Start accepting incoming calls again after a hangup. |
| - */ |
| -function acceptIncomingCallsAgain() { |
| - gAcceptsIncomingCalls = true; |
| -} |
| - |
| -/** |
| - * Do not auto-add the local stream when called. |
| - */ |
| -function doNotAutoAddLocalStreamWhenCalled() { |
| - gAutoAddLocalToPeerConnectionStreamWhenCalled = false; |
| -} |
| - |
| -/** |
| - * Disconnects from the peerconnection server. Returns ok-disconnected on |
| - * success. |
| - */ |
| -function disconnect() { |
| - if (gOurPeerId == null) |
| - throw failTest('Disconnecting, but we are not connected.'); |
| - |
| - request = new XMLHttpRequest(); |
| - request.open('GET', gServerUrl + '/sign_out?peer_id=' + gOurPeerId, false); |
| - request.send(); |
| - gOurPeerId = null; |
| - returnToTest('ok-disconnected'); |
| -} |
| - |
| -/** |
| - * Creates a DataChannel on the current PeerConnection. Only one DataChannel can |
| - * be created on each PeerConnection. |
| - * Returns ok-datachannel-created on success. |
| + * Retrieves all ICE candidates generated on this side. Must be called after |
| + * ICE candidate generation is triggered (for instance by running a call |
| + * negotiation). This function will wait if necessary if we're not done |
| + * generating ICE candidates on this side. |
| + * |
| + * Returns a JSON-encoded array of RTCIceCandidate instances to the test. |
| */ |
| -function createDataChannelOnPeerConnection() { |
| +function getAllIceCandidates() { |
| if (gPeerConnection == null) |
| - throw failTest('Tried to create data channel, ' + |
| - 'but have no peer connection.'); |
| + throw failTest('Trying to get ICE candidates, but has no peer connection.'); |
| - createDataChannel(gPeerConnection, gOurClientName); |
| - returnToTest('ok-datachannel-created'); |
| -} |
| - |
| -/** |
| - * Close the DataChannel on the current PeerConnection. |
| - * Returns ok-datachannel-close on success. |
| - */ |
| -function closeDataChannelOnPeerConnection() { |
| - if (gPeerConnection == null) |
| - throw failTest('Tried to close data channel, ' + |
| - 'but have no peer connection.'); |
| + if (gPeerConnection.iceGatheringState != 'complete') { |
| + console.log('Still ICE gathering - waiting...'); |
| + setTimeout(getAllIceCandidates, 100); |
| + return; |
| + } |
| - closeDataChannel(gPeerConnection); |
| - returnToTest('ok-datachannel-close'); |
| + returnToTest(JSON.stringify(gIceCandidates)); |
| } |
| /** |
| - * Creates a DTMF sender on the current PeerConnection. |
| - * Returns ok-dtmfsender-created on success. |
| + * Receives ICE candidates from the peer. |
| + * |
| + * Returns ok-received-candidates to the test on success. |
| + * |
| + * @param iceCandidatesJson a JSON-encoded array of RTCIceCandidate instances. |
| */ |
| -function createDtmfSenderOnPeerConnection() { |
| +function receiveIceCandidates(iceCandidatesJson) { |
| if (gPeerConnection == null) |
| - throw failTest('Tried to create DTMF sender, ' + |
| - 'but have no peer connection.'); |
| + throw failTest('Received ICE candidate, but has no peer connection'); |
| - createDtmfSender(gPeerConnection); |
| - returnToTest('ok-dtmfsender-created'); |
| -} |
| + var iceCandidates = parseJson_(iceCandidatesJson); |
| + if (!iceCandidates.length) |
| + throw failTest('Received invalid ICE candidate list from peer: ' + |
| + iceCandidatesJson); |
|
kjellander_chromium
2014/05/08 09:11:50
nit: indent.
phoglund_chromium
2014/05/08 13:27:42
Done.
|
| -/** |
| - * Send DTMF tones on the gDtmfSender. |
| - * Returns ok-dtmf-sent on success. |
| - */ |
| -function insertDtmfOnSender(tones, duration, interToneGap) { |
| - if (gDtmfSender == null) |
| - throw failTest('Tried to insert DTMF tones, ' + |
| - 'but have no DTMF sender.'); |
| + iceCandidates.forEach(function(iceCandidate) { |
| + if (!iceCandidate.candidate) |
| + failTest('Received invalid ICE candidate from peer: ' + |
| + iceCandidatesJson); |
| + |
| + gPeerConnection.addIceCandidate(new RTCIceCandidate(iceCandidate)); |
| + }); |
| - insertDtmf(tones, duration, interToneGap); |
| - returnToTest('ok-dtmf-sent'); |
| + returnToTest('ok-received-candidates'); |
| } |
| // Public interface to signaling implementations, such as JSEP. |
| /** |
| - * Sends a message to a peer through the peerconnection_server. |
| - */ |
| -function sendToPeer(peer, message) { |
| - var messageToLog = message.sdp ? message.sdp : message; |
| - debug('Sending message ' + messageToLog + ' to peer ' + peer + '.'); |
| - |
| - var request = new XMLHttpRequest(); |
| - var url = gServerUrl + '/message?peer_id=' + gOurPeerId + '&to=' + peer; |
| - request.open('POST', url, false); |
| - request.setRequestHeader('Content-Type', 'text/plain'); |
| - request.send(message); |
| -} |
| - |
| -/** |
| - * Returns true if we are disconnected from peerconnection_server. |
| + * Enqueues an ICE candidate for sending to the peer. |
| + * |
| + * @param {!RTCIceCandidate} The ICE candidate to send. |
|
kjellander_chromium
2014/05/08 09:11:50
@param {!RTCIceCandidate} message The ICE candidat
phoglund_chromium
2014/05/08 13:27:42
Done.
|
| */ |
| -function isDisconnected() { |
| - return gOurPeerId == null; |
| +function sendIceCandidate(message) { |
| + gIceCandidates.push(message); |
| } |
| /** |
| - * @return {!string} The current peer connection's ready state, or |
| - * 'no-peer-connection' if there is no peer connection up. |
| - * |
| - * NOTE: The PeerConnection states are changing and until chromium has |
| - * implemented the new states we have to use this interim solution of |
| - * always assuming that the PeerConnection is 'active'. |
| + * Parses JSON-encoded session descriptions and ICE candidates. |
| + * @private |
| */ |
| -function getReadyState() { |
| - if (gPeerConnection == null) |
| - return 'no-peer-connection'; |
| - |
| - return 'active'; |
| -} |
| - |
| -// Internals. |
| - |
| -/** @private */ |
| -function toggle_(track, localOrRemote, audioOrVideo) { |
| - if (!track) |
| - throw failTest('Tried to toggle ' + localOrRemote + ' ' + audioOrVideo + |
| - ' stream, but has no such stream.'); |
| - |
| - track.enabled = !track.enabled; |
| - returnToTest('ok-' + audioOrVideo + '-toggled-to-' + track.enabled); |
| -} |
| - |
| -/** @private */ |
| -function connectCallback_(request) { |
| - debug('Connect callback: ' + request.status + ', ' + request.readyState); |
| - if (request.status == 0) { |
| - debug('peerconnection_server doesn\'t seem to be up.'); |
| - returnToTest('failed-to-connect'); |
| - } |
| - if (request.readyState == 4 && request.status == 200) { |
| - gOurPeerId = parseOurPeerId_(request.responseText); |
| - gRemotePeerId = parseRemotePeerIdIfConnected_(request.responseText); |
| - startHangingGet_(gServerUrl, gOurPeerId); |
| - returnToTest('ok-connected'); |
| - } |
| -} |
| - |
| -/** @private */ |
| -function parseOurPeerId_(responseText) { |
| - // According to peerconnection_server's protocol. |
| - var peerList = responseText.split('\n'); |
| - return parseInt(peerList[0].split(',')[1]); |
| -} |
| - |
| -/** @private */ |
| -function parseRemotePeerIdIfConnected_(responseText) { |
| - var peerList = responseText.split('\n'); |
| - if (peerList.length == 1) { |
| - // No peers have connected yet - we'll get their id later in a notification. |
| - return null; |
| - } |
| - var remotePeerId = null; |
| - for (var i = 0; i < peerList.length; i++) { |
| - if (peerList[i].length == 0) |
| - continue; |
| - |
| - var parsed = peerList[i].split(','); |
| - var name = parsed[0]; |
| - var id = parsed[1]; |
| - |
| - if (id != gOurPeerId) { |
| - debug('Found remote peer with name ' + name + ', id ' + |
| - id + ' when connecting.'); |
| - |
| - // There should be at most one remote peer in this test. |
| - if (remotePeerId != null) |
| - throw failTest('Expected just one remote peer in this test: ' + |
| - 'found several.'); |
| - |
| - // Found a remote peer. |
| - remotePeerId = id; |
| - } |
| - } |
| - return remotePeerId; |
| -} |
| - |
| -/** @private */ |
| -function startHangingGet_(server, ourId) { |
| - if (isDisconnected()) |
| - return; |
| - hangingGetRequest = new XMLHttpRequest(); |
| - hangingGetRequest.onreadystatechange = function() { |
| - hangingGetCallback_(hangingGetRequest, server, ourId); |
| - } |
| - hangingGetRequest.ontimeout = function() { |
| - hangingGetTimeoutCallback_(hangingGetRequest, server, ourId); |
| - } |
| - callUrl = server + '/wait?peer_id=' + ourId; |
| - debug('Sending ' + callUrl); |
| - hangingGetRequest.open('GET', callUrl, true); |
| - hangingGetRequest.send(); |
| -} |
| - |
| -/** @private */ |
| -function hangingGetCallback_(hangingGetRequest, server, ourId) { |
| - if (hangingGetRequest.readyState != 4 || hangingGetRequest.status == 0) { |
| - // Code 0 is not possible if the server actually responded. Ignore. |
| - return; |
| - } |
| - if (hangingGetRequest.status != 200) { |
| - throw failTest('Error ' + hangingGetRequest.status + ' from server: ' + |
| - hangingGetRequest.statusText); |
| - } |
| - var targetId = readResponseHeader_(hangingGetRequest, 'Pragma'); |
| - if (targetId == ourId) |
| - handleServerNotification_(hangingGetRequest.responseText); |
| - else |
| - handlePeerMessage_(targetId, hangingGetRequest.responseText); |
| - |
| - hangingGetRequest.abort(); |
| - restartHangingGet_(server, ourId); |
| -} |
| - |
| -/** @private */ |
| -function hangingGetTimeoutCallback_(hangingGetRequest, server, ourId) { |
| - debug('Hanging GET times out, re-issuing...'); |
| - hangingGetRequest.abort(); |
| - restartHangingGet_(server, ourId); |
| -} |
| - |
| -/** @private */ |
| -function handleServerNotification_(message) { |
| - var parsed = message.split(','); |
| - if (parseInt(parsed[2]) == 1) { |
| - // Peer connected - this must be our remote peer, and it must mean we |
| - // connected before them (except if we happened to connect to the server |
| - // at precisely the same moment). |
| - debug('Found remote peer with name ' + parsed[0] + ', id ' + |
| - parsed[1] + ' when connecting.'); |
| - gRemotePeerId = parseInt(parsed[1]); |
| - } |
| -} |
| - |
| -/** @private */ |
| -function closeCall_() { |
| - if (gPeerConnection == null) |
| - throw failTest('Closing call, but no call active.'); |
| - gPeerConnection.close(); |
| - gPeerConnection = null; |
| -} |
| - |
| -/** @private */ |
| -function handlePeerMessage_(peerId, message) { |
| - debug('Received message from peer ' + peerId + ': ' + message); |
| - if (peerId != gRemotePeerId) { |
| - throw failTest('Received notification from unknown peer ' + peerId + |
| - ' (only know about ' + gRemotePeerId + '.'); |
| - } |
| - if (message.search('BYE') == 0) { |
| - debug('Received BYE from peer: closing call'); |
| - closeCall_(); |
| - return; |
| - } |
| - if (gPeerConnection == null && gAcceptsIncomingCalls) { |
| - // The other side is calling us. |
| - debug('We are being called: answer...'); |
| - |
| - gPeerConnection = createPeerConnection(STUN_SERVER, gUseRtpDataChannels); |
| - if (gAutoAddLocalToPeerConnectionStreamWhenCalled && |
| - obtainGetUserMediaResult() == 'ok-got-stream') { |
| - debug('We have a local stream, so hook it up automatically.'); |
| - addLocalStreamToPeerConnection(gPeerConnection); |
| - } |
| - answerCall(gPeerConnection, message); |
| - return; |
| - } |
| - if (gPeerConnection == null) { |
| - debug('Discarding message ' + message + '; already disconnected.'); |
| - return; |
| - } |
| - |
| - handleMessage(gPeerConnection, message); |
| -} |
| - |
| -/** @private */ |
| -function restartHangingGet_(server, ourId) { |
| - window.setTimeout(function() { |
| - startHangingGet_(server, ourId); |
| - }, 0); |
| -} |
| - |
| -/** @private */ |
| -function readResponseHeader_(request, key) { |
| - var value = request.getResponseHeader(key) |
| - if (value == null || value.length == 0) { |
| - throw failTest('Received empty value ' + value + |
| - ' for response header key ' + key + '.'); |
| +function parseJson_(json) { |
| + // Escape since the \r\n in the SDP tend to get unescaped. |
| + jsonWithEscapedLineBreaks = json.replace(/\r\n/g, '\\r\\n'); |
| + try { |
| + return JSON.parse(jsonWithEscapedLineBreaks); |
| + } catch (exception) { |
| + failTest('Failed to parse JSON: ' + jsonWithEscapedLineBreaks + ', got ' + |
| + exception); |
| } |
| - return parseInt(value); |
| } |