Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / resources / media / webrtc_internals.js
blob3becab1509257504448413274df8e543d9d7a29e
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 var USER_MEDIA_TAB_ID = 'user-media-tab-id';
7 var tabView = null;
8 var ssrcInfoManager = null;
9 var peerConnectionUpdateTable = null;
10 var statsTable = null;
11 var dumpCreator = null;
12 /** A map from peer connection id to the PeerConnectionRecord. */
13 var peerConnectionDataStore = {};
14 /** A list of getUserMedia requests. */
15 var userMediaRequests = [];
17 /** A simple class to store the updates and stats data for a peer connection. */
18 var PeerConnectionRecord = (function() {
19   /** @constructor */
20   function PeerConnectionRecord() {
21     /** @private */
22     this.record_ = {
23       constraints: {},
24       rtcConfiguration: [],
25       stats: {},
26       updateLog: [],
27       url: '',
28     };
29   };
31   PeerConnectionRecord.prototype = {
32     /** @override */
33     toJSON: function() {
34       return this.record_;
35     },
37     /**
38      * Adds the initilization info of the peer connection.
39      * @param {string} url The URL of the web page owning the peer connection.
40      * @param {Array} rtcConfiguration
41      * @param {!Object} constraints Media constraints.
42      */
43     initialize: function(url, rtcConfiguration, constraints) {
44       this.record_.url = url;
45       this.record_.rtcConfiguration = rtcConfiguration;
46       this.record_.constraints = constraints;
47     },
49     /**
50      * @param {string} dataSeriesId The TimelineDataSeries identifier.
51      * @return {!TimelineDataSeries}
52      */
53     getDataSeries: function(dataSeriesId) {
54       return this.record_.stats[dataSeriesId];
55     },
57     /**
58      * @param {string} dataSeriesId The TimelineDataSeries identifier.
59      * @param {!TimelineDataSeries} dataSeries The TimelineDataSeries to set to.
60      */
61     setDataSeries: function(dataSeriesId, dataSeries) {
62       this.record_.stats[dataSeriesId] = dataSeries;
63     },
65     /**
66      * @param {!Object} update The object contains keys "time", "type", and
67      *   "value".
68      */
69     addUpdate: function(update) {
70       var time = new Date(parseFloat(update.time));
71       this.record_.updateLog.push({
72         time: time.toLocaleString(),
73         type: update.type,
74         value: update.value,
75       });
76     },
77   };
79   return PeerConnectionRecord;
80 })();
82 // The maximum number of data points bufferred for each stats. Old data points
83 // will be shifted out when the buffer is full.
84 var MAX_STATS_DATA_POINT_BUFFER_SIZE = 1000;
86 <include src="tab_view.js"/>
87 <include src="data_series.js"/>
88 <include src="ssrc_info_manager.js"/>
89 <include src="stats_graph_helper.js"/>
90 <include src="stats_table.js"/>
91 <include src="peer_connection_update_table.js"/>
92 <include src="dump_creator.js"/>
95 function initialize() {
96   dumpCreator = new DumpCreator($('content-root'));
97   tabView = new TabView($('content-root'));
98   ssrcInfoManager = new SsrcInfoManager();
99   peerConnectionUpdateTable = new PeerConnectionUpdateTable();
100   statsTable = new StatsTable(ssrcInfoManager);
102   chrome.send('finishedDOMLoad');
104   // Requests stats from all peer connections every second.
105   window.setInterval(requestStats, 1000);
107 document.addEventListener('DOMContentLoaded', initialize);
110 /** Sends a request to the browser to get peer connection statistics. */
111 function requestStats() {
112   if (Object.keys(peerConnectionDataStore).length > 0)
113     chrome.send('getAllStats');
118  * A helper function for getting a peer connection element id.
120  * @param {!Object<string, number>} data The object containing the pid and lid
121  *     of the peer connection.
122  * @return {string} The peer connection element id.
123  */
124 function getPeerConnectionId(data) {
125   return data.pid + '-' + data.lid;
130  * Extracts ssrc info from a setLocal/setRemoteDescription update.
132  * @param {!PeerConnectionUpdateEntry} data The peer connection update data.
133  */
134 function extractSsrcInfo(data) {
135   if (data.type == 'setLocalDescription' ||
136       data.type == 'setRemoteDescription') {
137     ssrcInfoManager.addSsrcStreamInfo(data.value);
138   }
143  * A helper function for appending a child element to |parent|.
145  * @param {!Element} parent The parent element.
146  * @param {string} tag The child element tag.
147  * @param {string} text The textContent of the new DIV.
148  * @return {!Element} the new DIV element.
149  */
150 function appendChildWithText(parent, tag, text) {
151   var child = document.createElement(tag);
152   child.textContent = text;
153   parent.appendChild(child);
154   return child;
158  * Helper for adding a peer connection update.
160  * @param {Element} peerConnectionElement
161  * @param {!PeerConnectionUpdateEntry} update The peer connection update data.
162  */
163 function addPeerConnectionUpdate(peerConnectionElement, update) {
164   peerConnectionUpdateTable.addPeerConnectionUpdate(peerConnectionElement,
165                                                     update);
166   extractSsrcInfo(update);
167   peerConnectionDataStore[peerConnectionElement.id].addUpdate(update);
171 /** Browser message handlers. */
175  * Removes all information about a peer connection.
177  * @param {!Object<string, number>} data The object containing the pid and lid
178  *     of a peer connection.
179  */
180 function removePeerConnection(data) {
181   var element = $(getPeerConnectionId(data));
182   if (element) {
183     delete peerConnectionDataStore[element.id];
184     tabView.removeTab(element.id);
185   }
190  * Adds a peer connection.
192  * @param {!Object} data The object containing the pid, lid, url,
193  *     rtcConfiguration, and constraints of a peer connection.
194  */
195 function addPeerConnection(data) {
196   var id = getPeerConnectionId(data);
198   if (!peerConnectionDataStore[id]) {
199     peerConnectionDataStore[id] = new PeerConnectionRecord();
200   }
201   peerConnectionDataStore[id].initialize(
202       data.url, data.rtcConfiguration, data.constraints);
204   var peerConnectionElement = $(id);
205   if (!peerConnectionElement) {
206     peerConnectionElement = tabView.addTab(id, data.url + ' [' + id + ']');
207   }
209   var p = document.createElement('p');
210   p.textContent = data.url + ', ' + data.rtcConfiguration + ', ' +
211       data.constraints;
212   peerConnectionElement.appendChild(p);
214   return peerConnectionElement;
219  * Adds a peer connection update.
221  * @param {!PeerConnectionUpdateEntry} data The peer connection update data.
222  */
223 function updatePeerConnection(data) {
224   var peerConnectionElement = $(getPeerConnectionId(data));
225   addPeerConnectionUpdate(peerConnectionElement, data);
230  * Adds the information of all peer connections created so far.
232  * @param {Array<!Object>} data An array of the information of all peer
233  *     connections. Each array item contains pid, lid, url, rtcConfiguration,
234  *     constraints, and an array of updates as the log.
235  */
236 function updateAllPeerConnections(data) {
237   for (var i = 0; i < data.length; ++i) {
238     var peerConnection = addPeerConnection(data[i]);
240     var log = data[i].log;
241     if (!log)
242       continue;
243     for (var j = 0; j < log.length; ++j) {
244       addPeerConnectionUpdate(peerConnection, log[j]);
245     }
246   }
247   requestStats();
252  * Handles the report of stats.
254  * @param {!Object} data The object containing pid, lid, and reports, where
255  *     reports is an array of stats reports. Each report contains id, type,
256  *     and stats, where stats is the object containing timestamp and values,
257  *     which is an array of strings, whose even index entry is the name of the
258  *     stat, and the odd index entry is the value.
259  */
260 function addStats(data) {
261   var peerConnectionElement = $(getPeerConnectionId(data));
262   if (!peerConnectionElement)
263     return;
265   for (var i = 0; i < data.reports.length; ++i) {
266     var report = data.reports[i];
267     statsTable.addStatsReport(peerConnectionElement, report);
268     drawSingleReport(peerConnectionElement, report);
269   }
274  * Adds a getUserMedia request.
276  * @param {!Object} data The object containing rid {number}, pid {number},
277  *     origin {string}, audio {string}, video {string}.
278  */
279 function addGetUserMedia(data) {
280   userMediaRequests.push(data);
282   if (!$(USER_MEDIA_TAB_ID)) {
283     tabView.addTab(USER_MEDIA_TAB_ID, 'GetUserMedia Requests');
284   }
286   var requestDiv = document.createElement('div');
287   requestDiv.className = 'user-media-request-div-class';
288   requestDiv.rid = data.rid;
289   $(USER_MEDIA_TAB_ID).appendChild(requestDiv);
291   appendChildWithText(requestDiv, 'div', 'Caller origin: ' + data.origin);
292   appendChildWithText(requestDiv, 'div', 'Caller process id: ' + data.pid);
293   appendChildWithText(requestDiv, 'span', 'Audio Constraints').style.fontWeight
294       = 'bold';
295   appendChildWithText(requestDiv, 'div', data.audio);
297   appendChildWithText(requestDiv, 'span', 'Video Constraints').style.fontWeight
298       = 'bold';
299   appendChildWithText(requestDiv, 'div', data.video);
304  * Removes the getUserMedia requests from the specified |rid|.
306  * @param {!Object} data The object containing rid {number}, the render id.
307  */
308 function removeGetUserMediaForRenderer(data) {
309   for (var i = userMediaRequests.length - 1; i >= 0; --i) {
310     if (userMediaRequests[i].rid == data.rid)
311       userMediaRequests.splice(i, 1);
312   }
314   var requests = $(USER_MEDIA_TAB_ID).childNodes;
315   for (var i = 0; i < requests.length; ++i) {
316     if (requests[i].rid == data.rid)
317       $(USER_MEDIA_TAB_ID).removeChild(requests[i]);
319   }
320   if ($(USER_MEDIA_TAB_ID).childNodes.length == 0)
321     tabView.removeTab(USER_MEDIA_TAB_ID);
326  * Notification that the AEC recording file selection dialog was cancelled,
327  * i.e. AEC has not been enabled.
328  */
329 function aecRecordingFileSelectionCancelled() {
330   dumpCreator.disableAecRecording();
335  * Set
336  */
337 function enableAecRecording() {
338   dumpCreator.enableAecRecording();