Roll leveldb 3f7758:803d69 (v1.17 -> v1.18)
[chromium-blink-merge.git] / chrome / test / data / webrtc / peerconnection.js
blobfbe76c9d6157e024bfbf7d90034a18605c871da4
1 /**
2  * Copyright 2014 The Chromium Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
7 /**
8  * We need a STUN server for some API calls.
9  * @private
10  */
11 var STUN_SERVER = 'stun.l.google.com:19302';
13 /**
14  * The one and only peer connection in this page.
15  * @private
16  */
17 var gPeerConnection = null;
19 /**
20  * This stores ICE candidates generated on this side.
21  * @private
22  */
23 var gIceCandidates = [];
25 /**
26  * Keeps track of whether we have seen crypto information in the SDP.
27  * @private
28  */
29 var gHasSeenCryptoInSdp = 'no-crypto-seen';
31 // Public interface to tests. These are expected to be called with
32 // ExecuteJavascript invocations from the browser tests and will return answers
33 // through the DOM automation controller.
35 /**
36  * Creates a peer connection. Must be called before most other public functions
37  * in this file.
38  */
39 function preparePeerConnection() {
40   if (gPeerConnection != null)
41     throw failTest('creating peer connection, but we already have one.');
43   gPeerConnection = createPeerConnection_(STUN_SERVER);
44   returnToTest('ok-peerconnection-created');
47 /**
48  * Asks this page to create a local offer.
49  *
50  * Returns a string on the format ok-(JSON encoded session description).
51  *
52  * @param {!Object} constraints Any createOffer constraints.
53  */
54 function createLocalOffer(constraints) {
55   peerConnection_().createOffer(
56       function(localOffer) {
57         success_('createOffer');
58         setLocalDescription(peerConnection, localOffer);
60         returnToTest('ok-' + JSON.stringify(localOffer));
61       },
62       function(error) { failure_('createOffer', error); },
63       constraints);
66 /**
67  * Asks this page to accept an offer and generate an answer.
68  *
69  * Returns a string on the format ok-(JSON encoded session description).
70  *
71  * @param {!string} sessionDescJson A JSON-encoded session description of type
72  *     'offer'.
73  * @param {!Object} constraints Any createAnswer constraints.
74  */
75 function receiveOfferFromPeer(sessionDescJson, constraints) {
76   offer = parseJson_(sessionDescJson);
77   if (!offer.type)
78     failTest('Got invalid session description from peer: ' + sessionDescJson);
79   if (offer.type != 'offer')
80     failTest('Expected to receive offer from peer, got ' + offer.type);
82   var sessionDescription = new RTCSessionDescription(offer);
83   peerConnection_().setRemoteDescription(
84       sessionDescription,
85       function() { success_('setRemoteDescription'); },
86       function(error) { failure_('setRemoteDescription', error); });
88   peerConnection_().createAnswer(
89       function(answer) {
90         success_('createAnswer');
91         setLocalDescription(peerConnection, answer);
92         returnToTest('ok-' + JSON.stringify(answer));
93       },
94       function(error) { failure_('createAnswer', error); },
95       constraints);
98 /**
99  * Asks this page to accept an answer generated by the peer in response to a
100  * previous offer by this page
102  * Returns a string ok-accepted-answer on success.
104  * @param {!string} sessionDescJson A JSON-encoded session description of type
105  *     'answer'.
106  */
107 function receiveAnswerFromPeer(sessionDescJson) {
108   answer = parseJson_(sessionDescJson);
109   if (!answer.type)
110     failTest('Got invalid session description from peer: ' + sessionDescJson);
111   if (answer.type != 'answer')
112     failTest('Expected to receive answer from peer, got ' + answer.type);
114   var sessionDescription = new RTCSessionDescription(answer);
115   peerConnection_().setRemoteDescription(
116       sessionDescription,
117       function() {
118         success_('setRemoteDescription');
119         returnToTest('ok-accepted-answer');
120       },
121       function(error) { failure_('setRemoteDescription', error); });
125  * Adds the local stream to the peer connection. You will have to re-negotiate
126  * the call for this to take effect in the call.
127  */
128 function addLocalStream() {
129   addLocalStreamToPeerConnection(peerConnection_());
130   returnToTest('ok-added');
134  * Loads a file with WebAudio and connects it to the peer connection.
136  * The loadAudioAndAddToPeerConnection will return ok-added to the test when
137  * the sound is loaded and added to the peer connection. The sound will start
138  * playing when you call playAudioFile.
140  * @param url URL pointing to the file to play. You can assume that you can
141  *     serve files from the repository's file system. For instance, to serve a
142  *     file from chrome/test/data/pyauto_private/webrtc/file.wav, pass in a path
143  *     relative to this directory (e.g. ../pyauto_private/webrtc/file.wav).
144  */
145 function addAudioFile(url) {
146   loadAudioAndAddToPeerConnection(url, peerConnection_());
150  * Mixes the local audio stream with an audio file through WebAudio.
152  * You must have successfully requested access to the user's microphone through
153  * getUserMedia before calling this function (see getUserMedia.js).
154  * Additionally, you must have loaded an audio file to mix with.
156  * When playAudioFile is called, WebAudio will effectively mix the user's
157  * microphone input with the previously loaded file and feed that into the
158  * peer connection.
159  */
160 function mixLocalStreamWithPreviouslyLoadedAudioFile() {
161   if (getLocalStream() == null)
162     throw failTest('trying to mix in stream, but we have no stream to mix in.');
164   mixLocalStreamIntoPeerConnection(peerConnection_(), getLocalStream());
168  * Must be called after addAudioFile.
169  */
170 function playAudioFile() {
171   playPreviouslyLoadedAudioFile(peerConnection_());
172   returnToTest('ok-playing');
176  * Hangs up a started call. Returns ok-call-hung-up on success.
177  */
178 function hangUp() {
179   peerConnection_().close();
180   gPeerConnection = null;
181   returnToTest('ok-call-hung-up');
185  * Retrieves all ICE candidates generated on this side. Must be called after
186  * ICE candidate generation is triggered (for instance by running a call
187  * negotiation). This function will wait if necessary if we're not done
188  * generating ICE candidates on this side.
190  * Returns a JSON-encoded array of RTCIceCandidate instances to the test.
191  */
192 function getAllIceCandidates() {
193   if (peerConnection_().iceGatheringState != 'complete') {
194     console.log('Still ICE gathering - waiting...');
195     setTimeout(getAllIceCandidates, 100);
196     return;
197   }
199   returnToTest(JSON.stringify(gIceCandidates));
203  * Receives ICE candidates from the peer.
205  * Returns ok-received-candidates to the test on success.
207  * @param iceCandidatesJson a JSON-encoded array of RTCIceCandidate instances.
208  */
209 function receiveIceCandidates(iceCandidatesJson) {
210   var iceCandidates = parseJson_(iceCandidatesJson);
211   if (!iceCandidates.length)
212     throw failTest('Received invalid ICE candidate list from peer: ' +
213         iceCandidatesJson);
215   iceCandidates.forEach(function(iceCandidate) {
216     if (!iceCandidate.candidate)
217       failTest('Received invalid ICE candidate from peer: ' +
218           iceCandidatesJson);
220     peerConnection_().addIceCandidate(new RTCIceCandidate(iceCandidate,
221         function() { success_('addIceCandidate'); },
222         function(error) { failure_('addIceCandidate', error); }
223     ));
224   });
226   returnToTest('ok-received-candidates');
230  * Returns
231  */
232 function hasSeenCryptoInSdp() {
233   returnToTest(gHasSeenCryptoInSdp);
236 // Internals.
238 /** @private */
239 function createPeerConnection_(stun_server) {
240   servers = {iceServers: [{url: 'stun:' + stun_server}]};
241   try {
242     peerConnection = new RTCPeerConnection(servers, {});
243   } catch (exception) {
244     throw failTest('Failed to create peer connection: ' + exception);
245   }
246   peerConnection.onaddstream = addStreamCallback_;
247   peerConnection.onremovestream = removeStreamCallback_;
248   peerConnection.onicecandidate = iceCallback_;
249   return peerConnection;
252 /** @private */
253 function peerConnection_() {
254   if (gPeerConnection == null)
255     throw failTest('Trying to use peer connection, but none was created.');
256   return gPeerConnection;
259 /** @private */
260 function success_(method) {
261   debug(method + '(): success.');
264 /** @private */
265 function failure_(method, error) {
266   throw failTest(method + '() failed: ' + JSON.stringify(error));
269 /** @private */
270 function iceCallback_(event) {
271   if (event.candidate)
272     gIceCandidates.push(event.candidate);
275 /** @private */
276 function setLocalDescription(peerConnection, sessionDescription) {
277   if (sessionDescription.sdp.search('a=crypto') != -1 ||
278       sessionDescription.sdp.search('a=fingerprint') != -1)
279     gHasSeenCryptoInSdp = 'crypto-seen';
281   peerConnection.setLocalDescription(
282     sessionDescription,
283     function() { success_('setLocalDescription'); },
284     function(error) { failure_('setLocalDescription', error); });
287 /** @private */
288 function addStreamCallback_(event) {
289   debug('Receiving remote stream...');
290   var videoTag = document.getElementById('remote-view');
291   attachMediaStream(videoTag, event.stream);
294 /** @private */
295 function removeStreamCallback_(event) {
296   debug('Call ended.');
297   document.getElementById('remote-view').src = '';
301  * Parses JSON-encoded session descriptions and ICE candidates.
302  * @private
303  */
304 function parseJson_(json) {
305   // Escape since the \r\n in the SDP tend to get unescaped.
306   jsonWithEscapedLineBreaks = json.replace(/\r\n/g, '\\r\\n');
307   try {
308     return JSON.parse(jsonWithEscapedLineBreaks);
309   } catch (exception) {
310     failTest('Failed to parse JSON: ' + jsonWithEscapedLineBreaks + ', got ' +
311              exception);
312   }