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';
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() {
20 function PeerConnectionRecord() {
31 PeerConnectionRecord.prototype = {
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.
43 initialize: function(url, rtcConfiguration, constraints) {
44 this.record_.url = url;
45 this.record_.rtcConfiguration = rtcConfiguration;
46 this.record_.constraints = constraints;
50 * @param {string} dataSeriesId The TimelineDataSeries identifier.
51 * @return {!TimelineDataSeries}
53 getDataSeries: function(dataSeriesId) {
54 return this.record_.stats[dataSeriesId];
58 * @param {string} dataSeriesId The TimelineDataSeries identifier.
59 * @param {!TimelineDataSeries} dataSeries The TimelineDataSeries to set to.
61 setDataSeries: function(dataSeriesId, dataSeries) {
62 this.record_.stats[dataSeriesId] = dataSeries;
66 * @param {!Object} update The object contains keys "time", "type", and
69 addUpdate: function(update) {
70 var time = new Date(parseFloat(update.time));
71 this.record_.updateLog.push({
72 time: time.toLocaleString(),
79 return PeerConnectionRecord;
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.
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.
134 function extractSsrcInfo(data) {
135 if (data.type == 'setLocalDescription' ||
136 data.type == 'setRemoteDescription') {
137 ssrcInfoManager.addSsrcStreamInfo(data.value);
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.
150 function appendChildWithText(parent, tag, text) {
151 var child = document.createElement(tag);
152 child.textContent = text;
153 parent.appendChild(child);
158 * Helper for adding a peer connection update.
160 * @param {Element} peerConnectionElement
161 * @param {!PeerConnectionUpdateEntry} update The peer connection update data.
163 function addPeerConnectionUpdate(peerConnectionElement, update) {
164 peerConnectionUpdateTable.addPeerConnectionUpdate(peerConnectionElement,
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.
180 function removePeerConnection(data) {
181 var element = $(getPeerConnectionId(data));
183 delete peerConnectionDataStore[element.id];
184 tabView.removeTab(element.id);
190 * Adds a peer connection.
192 * @param {!Object} data The object containing the pid, lid, url,
193 * rtcConfiguration, and constraints of a peer connection.
195 function addPeerConnection(data) {
196 var id = getPeerConnectionId(data);
198 if (!peerConnectionDataStore[id]) {
199 peerConnectionDataStore[id] = new PeerConnectionRecord();
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 + ']');
208 peerConnectionElement.innerHTML =
209 '<p>' + data.url + ' ' + data.rtcConfiguration + ' ' + data.constraints +
212 return peerConnectionElement;
217 * Adds a peer connection update.
219 * @param {!PeerConnectionUpdateEntry} data The peer connection update data.
221 function updatePeerConnection(data) {
222 var peerConnectionElement = $(getPeerConnectionId(data));
223 addPeerConnectionUpdate(peerConnectionElement, data);
228 * Adds the information of all peer connections created so far.
230 * @param {Array.<!Object>} data An array of the information of all peer
231 * connections. Each array item contains pid, lid, url, rtcConfiguration,
232 * constraints, and an array of updates as the log.
234 function updateAllPeerConnections(data) {
235 for (var i = 0; i < data.length; ++i) {
236 var peerConnection = addPeerConnection(data[i]);
238 var log = data[i].log;
241 for (var j = 0; j < log.length; ++j) {
242 addPeerConnectionUpdate(peerConnection, log[j]);
250 * Handles the report of stats.
252 * @param {!Object} data The object containing pid, lid, and reports, where
253 * reports is an array of stats reports. Each report contains id, type,
254 * and stats, where stats is the object containing timestamp and values,
255 * which is an array of strings, whose even index entry is the name of the
256 * stat, and the odd index entry is the value.
258 function addStats(data) {
259 var peerConnectionElement = $(getPeerConnectionId(data));
260 if (!peerConnectionElement)
263 for (var i = 0; i < data.reports.length; ++i) {
264 var report = data.reports[i];
265 statsTable.addStatsReport(peerConnectionElement, report);
266 drawSingleReport(peerConnectionElement, report);
272 * Adds a getUserMedia request.
274 * @param {!Object} data The object containing rid {number}, pid {number},
275 * origin {string}, audio {string}, video {string}.
277 function addGetUserMedia(data) {
278 userMediaRequests.push(data);
280 if (!$(USER_MEDIA_TAB_ID)) {
281 tabView.addTab(USER_MEDIA_TAB_ID, 'GetUserMedia Requests');
284 var requestDiv = document.createElement('div');
285 requestDiv.className = 'user-media-request-div-class';
286 requestDiv.rid = data.rid;
287 $(USER_MEDIA_TAB_ID).appendChild(requestDiv);
289 appendChildWithText(requestDiv, 'div', 'Caller origin: ' + data.origin);
290 appendChildWithText(requestDiv, 'div', 'Caller process id: ' + data.pid);
291 appendChildWithText(requestDiv, 'span', 'Audio Constraints').style.fontWeight
293 appendChildWithText(requestDiv, 'div', data.audio);
295 appendChildWithText(requestDiv, 'span', 'Video Constraints').style.fontWeight
297 appendChildWithText(requestDiv, 'div', data.video);
302 * Removes the getUserMedia requests from the specified |rid|.
304 * @param {!Object} data The object containing rid {number}, the render id.
306 function removeGetUserMediaForRenderer(data) {
307 for (var i = userMediaRequests.length - 1; i >= 0; --i) {
308 if (userMediaRequests[i].rid == data.rid)
309 userMediaRequests.splice(i, 1);
312 var requests = $(USER_MEDIA_TAB_ID).childNodes;
313 for (var i = 0; i < requests.length; ++i) {
314 if (requests[i].rid == data.rid)
315 $(USER_MEDIA_TAB_ID).removeChild(requests[i]);
318 if ($(USER_MEDIA_TAB_ID).childNodes.length == 0)
319 tabView.removeTab(USER_MEDIA_TAB_ID);
324 * Notification that the AEC recording file selection dialog was cancelled,
325 * i.e. AEC has not been enabled.
327 function aecRecordingFileSelectionCancelled() {
328 dumpCreator.disableAecRecording();
335 function enableAecRecording() {
336 dumpCreator.enableAecRecording();