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. 4 5var tabView = null; 6var ssrcInfoManager = null; 7var peerConnectionUpdateTable = null; 8var statsTable = null; 9var dumpCreator = null; 10/** A map from peer connection id to the PeerConnectionRecord. */ 11var peerConnectionDataStore = {}; 12/** A list of getUserMedia requests. */ 13var userMediaRequests = []; 14 15/** A simple class to store the updates and stats data for a peer connection. */ 16var PeerConnectionRecord = (function() { 17 /** @constructor */ 18 function PeerConnectionRecord() { 19 /** @private */ 20 this.record_ = { 21 constraints: {}, 22 servers: [], 23 stats: {}, 24 updateLog: [], 25 url: '', 26 }; 27 }; 28 29 PeerConnectionRecord.prototype = { 30 /** @override */ 31 toJSON: function() { 32 return this.record_; 33 }, 34 35 /** 36 * Adds the initilization info of the peer connection. 37 * @param {string} url The URL of the web page owning the peer connection. 38 * @param {Array} servers STUN servers used by the peer connection. 39 * @param {!Object} constraints Media constraints. 40 */ 41 initialize: function(url, servers, constraints) { 42 this.record_.url = url; 43 this.record_.servers = servers; 44 this.record_.constraints = constraints; 45 }, 46 47 /** 48 * @param {string} dataSeriesId The TimelineDataSeries identifier. 49 * @return {!TimelineDataSeries} 50 */ 51 getDataSeries: function(dataSeriesId) { 52 return this.record_.stats[dataSeriesId]; 53 }, 54 55 /** 56 * @param {string} dataSeriesId The TimelineDataSeries identifier. 57 * @param {!TimelineDataSeries} dataSeries The TimelineDataSeries to set to. 58 */ 59 setDataSeries: function(dataSeriesId, dataSeries) { 60 this.record_.stats[dataSeriesId] = dataSeries; 61 }, 62 63 /** 64 * @param {string} type The type of the update. 65 * @param {string} value The value of the update. 66 */ 67 addUpdate: function(type, value) { 68 this.record_.updateLog.push({ 69 time: (new Date()).toLocaleString(), 70 type: type, 71 value: value, 72 }); 73 }, 74 }; 75 76 return PeerConnectionRecord; 77})(); 78 79// The maximum number of data points bufferred for each stats. Old data points 80// will be shifted out when the buffer is full. 81var MAX_STATS_DATA_POINT_BUFFER_SIZE = 1000; 82 83<include src="tab_view.js"/> 84<include src="data_series.js"/> 85<include src="ssrc_info_manager.js"/> 86<include src="stats_graph_helper.js"/> 87<include src="stats_table.js"/> 88<include src="peer_connection_update_table.js"/> 89<include src="dump_creator.js"/> 90 91 92function initialize() { 93 dumpCreator = new DumpCreator($('content-root')); 94 tabView = new TabView($('content-root')); 95 ssrcInfoManager = new SsrcInfoManager(); 96 peerConnectionUpdateTable = new PeerConnectionUpdateTable(); 97 statsTable = new StatsTable(ssrcInfoManager); 98 99 chrome.send('finishedDOMLoad'); 100 101 // Requests stats from all peer connections every second. 102 window.setInterval(requestStats, 1000); 103} 104document.addEventListener('DOMContentLoaded', initialize); 105 106 107/** Sends a request to the browser to get peer connection statistics. */ 108function requestStats() { 109 if (Object.keys(peerConnectionDataStore).length > 0) 110 chrome.send('getAllStats'); 111} 112 113 114/** 115 * A helper function for getting a peer connection element id. 116 * 117 * @param {!Object.<string, number>} data The object containing the pid and lid 118 * of the peer connection. 119 * @return {string} The peer connection element id. 120 */ 121function getPeerConnectionId(data) { 122 return data.pid + '-' + data.lid; 123} 124 125 126/** 127 * Extracts ssrc info from a setLocal/setRemoteDescription update. 128 * 129 * @param {!PeerConnectionUpdateEntry} data The peer connection update data. 130 */ 131function extractSsrcInfo(data) { 132 if (data.type == 'setLocalDescription' || 133 data.type == 'setRemoteDescription') { 134 ssrcInfoManager.addSsrcStreamInfo(data.value); 135 } 136} 137 138 139/** 140 * Helper for adding a peer connection update. 141 * 142 * @param {Element} peerConnectionElement 143 * @param {!PeerConnectionUpdateEntry} update The peer connection update data. 144 */ 145function addPeerConnectionUpdate(peerConnectionElement, update) { 146 peerConnectionUpdateTable.addPeerConnectionUpdate(peerConnectionElement, 147 update); 148 extractSsrcInfo(update); 149 peerConnectionDataStore[peerConnectionElement.id].addUpdate( 150 update.type, update.value); 151} 152 153 154/** Browser message handlers. */ 155 156 157/** 158 * Removes all information about a peer connection. 159 * 160 * @param {!Object.<string, number>} data The object containing the pid and lid 161 * of a peer connection. 162 */ 163function removePeerConnection(data) { 164 var element = $(getPeerConnectionId(data)); 165 if (element) { 166 delete peerConnectionDataStore[element.id]; 167 tabView.removeTab(element.id); 168 } 169} 170 171 172/** 173 * Adds a peer connection. 174 * 175 * @param {!Object} data The object containing the pid, lid, url, servers, and 176 * constraints of a peer connection. 177 */ 178function addPeerConnection(data) { 179 var id = getPeerConnectionId(data); 180 181 if (!peerConnectionDataStore[id]) { 182 peerConnectionDataStore[id] = new PeerConnectionRecord(); 183 } 184 peerConnectionDataStore[id].initialize( 185 data.url, data.servers, data.constraints); 186 187 var peerConnectionElement = $(id); 188 if (!peerConnectionElement) { 189 peerConnectionElement = tabView.addTab(id, data.url); 190 } 191 peerConnectionElement.innerHTML = 192 '<p>' + data.url + ' ' + data.servers + ' ' + data.constraints + 193 '</p>'; 194 195 return peerConnectionElement; 196} 197 198 199/** 200 * Adds a peer connection update. 201 * 202 * @param {!PeerConnectionUpdateEntry} data The peer connection update data. 203 */ 204function updatePeerConnection(data) { 205 var peerConnectionElement = $(getPeerConnectionId(data)); 206 addPeerConnectionUpdate(peerConnectionElement, data); 207} 208 209 210/** 211 * Adds the information of all peer connections created so far. 212 * 213 * @param {Array.<!Object>} data An array of the information of all peer 214 * connections. Each array item contains pid, lid, url, servers, 215 * constraints, and an array of updates as the log. 216 */ 217function updateAllPeerConnections(data) { 218 for (var i = 0; i < data.length; ++i) { 219 var peerConnection = addPeerConnection(data[i]); 220 221 var log = data[i].log; 222 if (!log) 223 continue; 224 for (var j = 0; j < log.length; ++j) { 225 addPeerConnectionUpdate(peerConnection, log[j]); 226 } 227 } 228 requestStats(); 229} 230 231 232/** 233 * Handles the report of stats. 234 * 235 * @param {!Object} data The object containing pid, lid, and reports, where 236 * reports is an array of stats reports. Each report contains id, type, 237 * and stats, where stats is the object containing timestamp and values, 238 * which is an array of strings, whose even index entry is the name of the 239 * stat, and the odd index entry is the value. 240 */ 241function addStats(data) { 242 var peerConnectionElement = $(getPeerConnectionId(data)); 243 if (!peerConnectionElement) 244 return; 245 246 for (var i = 0; i < data.reports.length; ++i) { 247 var report = data.reports[i]; 248 statsTable.addStatsReport(peerConnectionElement, report); 249 drawSingleReport(peerConnectionElement, report); 250 } 251} 252 253 254/** 255 * Adds a getUserMedia request. 256 * 257 * @param {!Object} data The object containing rid {number}, pid {number}, 258 * origin {string}, audio {string}, video {string}. 259 */ 260function addGetUserMedia(data) { 261 // TODO(jiayl): add the getUserMedia info to the tabbed UI. 262 userMediaRequests.push(data); 263} 264 265 266/** 267 * Removes the getUserMedia requests from the specified |rid|. 268 * 269 * @param {!Object} data The object containing rid {number}, the render id. 270 */ 271function removeGetUserMediaForRenderer(data) { 272 // TODO(jiayl): remove the getUserMedia info from the tabbed UI. 273 for (var i = userMediaRequests.length - 1; i >= 0; --i) { 274 if (userMediaRequests[i].rid == data.rid) 275 userMediaRequests.splice(i, 1); 276 } 277} 278 279 280/** 281 * Notification that the AEC recording file selection dialog was cancelled, 282 * i.e. AEC has not been enabled. 283 */ 284function aecRecordingFileSelectionCancelled() { 285 dumpCreator.disableAecRecording(); 286} 287 288 289/** 290 * Set 291 */ 292function enableAecRecording() { 293 dumpCreator.enableAecRecording(); 294} 295