diff options
author | jiayl@chromium.org <jiayl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-26 23:42:32 +0000 |
---|---|---|
committer | jiayl@chromium.org <jiayl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-26 23:42:32 +0000 |
commit | 2746df93f815c4d054f2197752879acd5b9327db (patch) | |
tree | 9881d97a056de6148ff1601d41dafe5428ac099b /content/browser/resources | |
parent | 1851802fee34e3f5b4a91770284ff960f09558e8 (diff) | |
download | chromium_src-2746df93f815c4d054f2197752879acd5b9327db.zip chromium_src-2746df93f815c4d054f2197752879acd5b9327db.tar.gz chromium_src-2746df93f815c4d054f2197752879acd5b9327db.tar.bz2 |
Displays stream properties like msid/label with the ssrc for stats table and graphs. Adds the ability to expand/collapse a peerconnection section. Also adds more JS annotation and refactors the global functions into helper classes for better readability and maintainability.
BUG=
Review URL: https://chromiumcodereview.appspot.com/13483014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@196883 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/resources')
-rw-r--r-- | content/browser/resources/media/peer_connection_update_table.js | 128 | ||||
-rw-r--r-- | content/browser/resources/media/ssrc_info_manager.js | 134 | ||||
-rw-r--r-- | content/browser/resources/media/stats_graph_helper.js | 60 | ||||
-rw-r--r-- | content/browser/resources/media/stats_table.js | 139 | ||||
-rw-r--r-- | content/browser/resources/media/webrtc_internals.css | 41 | ||||
-rw-r--r-- | content/browser/resources/media/webrtc_internals.js | 258 |
6 files changed, 559 insertions, 201 deletions
diff --git a/content/browser/resources/media/peer_connection_update_table.js b/content/browser/resources/media/peer_connection_update_table.js new file mode 100644 index 0000000..facbefa --- /dev/null +++ b/content/browser/resources/media/peer_connection_update_table.js @@ -0,0 +1,128 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +/** + * The data of a peer connection update. + * @param {number} pid The id of the renderer. + * @param {number} lid The id of the peer conneciton inside a renderer. + * @param {string} type The type of the update. + * @param {string} value The details of the update. + * @constructor + */ +var PeerConnectionUpdateEntry = function(pid, lid, type, value) { + /** + * @type {number} + */ + this.pid = pid; + + /** + * @type {number} + */ + this.lid = lid; + + /** + * @type {string} + */ + this.type = type; + + /** + * @type {string} + */ + this.value = value; +}; + + +/** + * Maintains the peer connection update log table. + */ +var PeerConnectionUpdateTable = (function() { + 'use strict'; + + /** + * @constructor + */ + function PeerConnectionUpdateTable() { + /** + * @type {string} + * @const + * @private + */ + this.UPDATE_LOG_ID_SUFFIX_ = '-update-log'; + + /** + * @type {string} + * @const + * @private + */ + this.UPDATE_LOG_CONTAINER_CLASS_ = 'update-log-container'; + + /** + * @type {string} + * @const + * @private + */ + this.UPDATE_LOG_TABLE_CLASS_ = 'update-log-table'; + } + + PeerConnectionUpdateTable.prototype = { + /** + * Adds the update to the update table as a new row. The type of the update + * is set to the summary of the cell; clicking the cell will reveal or hide + * the details as the content of a TextArea element. + * + * @param {!Element} peerConnectionElement The root element. + * @param {!PeerConnectionUpdateEntry} update The update to add. + */ + addPeerConnectionUpdate: function(peerConnectionElement, update) { + var tableElement = this.ensureUpdateContainer_(peerConnectionElement); + + var row = document.createElement('tr'); + tableElement.firstChild.appendChild(row); + + row.innerHTML = '<td>' + (new Date()).toLocaleString() + '</td>'; + + if (update.value.length == 0) { + row.innerHTML += '<td>' + update.type + '</td>'; + return; + } + + row.innerHTML += '<td><details><summary>' + update.type + + '</summary></details></td>'; + + var valueContainer = document.createElement('pre'); + var details = row.cells[1].childNodes[0]; + details.appendChild(valueContainer); + valueContainer.textContent = update.value; + }, + + /** + * Makes sure the update log table of the peer connection is created. + * + * @param {!Element} peerConnectionElement The root element. + * @return {!Element} The log table element. + * @private + */ + ensureUpdateContainer_: function(peerConnectionElement) { + var tableId = peerConnectionElement.id + this.UPDATE_LOG_ID_SUFFIX_; + var tableElement = $(tableId); + if (!tableElement) { + var tableContainer = document.createElement('div'); + tableContainer.className = this.UPDATE_LOG_CONTAINER_CLASS_; + peerConnectionElement.appendChild(tableContainer); + + tableElement = document.createElement('table'); + tableElement.className = this.UPDATE_LOG_TABLE_CLASS_; + tableElement.id = tableId; + tableElement.border = 1; + tableContainer.appendChild(tableElement); + tableElement.innerHTML = '<tr><th>Time</th>' + + '<th class="update-log-header-event">Event</th></tr>'; + } + return tableElement; + } + }; + + return PeerConnectionUpdateTable; +})(); diff --git a/content/browser/resources/media/ssrc_info_manager.js b/content/browser/resources/media/ssrc_info_manager.js new file mode 100644 index 0000000..8236e87 --- /dev/null +++ b/content/browser/resources/media/ssrc_info_manager.js @@ -0,0 +1,134 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +/** + * SsrcInfoManager stores the ssrc stream info extracted from SDP. + */ +var SsrcInfoManager = (function() { + 'use strict'; + + /** + * @constructor + */ + function SsrcInfoManager() { + /** + * Map from ssrc id to an object containing all the stream properties. + * @type {!Object.<string, !Object.<string>>} + * @private + */ + this.streamInfoContainer_ = {}; + + /** + * The string separating attibutes in an SDP. + * @type {string} + * @const + * @private + */ + this.ATTRIBUTE_SEPARATOR_ = /[\r,\n]/; + + /** + * The regex separating fields within an ssrc description. + * @type {RegExp} + * @const + * @private + */ + this.FIELD_SEPARATOR_REGEX_ = / .*:/; + + /** + * The prefix string of an ssrc description. + * @type {string} + * @const + * @private + */ + this.SSRC_ATTRIBUTE_PREFIX_ = 'a=ssrc:'; + + /** + * The className of the ssrc info parent element. + * @type {string} + * @const + * @private + */ + this.SSRC_INFO_BLOCK_CLASS_ = 'ssrc-info-block'; + } + + SsrcInfoManager.prototype = { + /** + * Extracts the stream information from |sdp| and saves it. + * For example: + * a=ssrc:1234 msid:abcd + * a=ssrc:1234 label:hello + * + * @param {string} sdp The SDP string. + */ + addSsrcStreamInfo: function(sdp) { + var attributes = sdp.split(this.ATTRIBUTE_SEPARATOR_); + for (var i = 0; i < attributes.length; ++i) { + // Check if this is a ssrc attribute. + if (attributes[i].indexOf(this.SSRC_ATTRIBUTE_PREFIX_) != 0) + continue; + + var nextFieldIndex = attributes[i].search(this.FIELD_SEPARATOR_REGEX_); + + if (nextFieldIndex == -1) + continue; + + var ssrc = attributes[i].substring(this.SSRC_ATTRIBUTE_PREFIX_.length, + nextFieldIndex); + if (!this.streamInfoContainer_[ssrc]) + this.streamInfoContainer_[ssrc] = {}; + + // Make |rest| starting at the next field. + var rest = attributes[i].substring(nextFieldIndex + 1); + var name, value; + while (rest.length > 0) { + nextFieldIndex = rest.search(this.FIELD_SEPARATOR_REGEX_); + if (nextFieldIndex == -1) + nextFieldIndex = rest.length; + + // The field name is the string before the colon. + name = rest.substring(0, rest.indexOf(':')); + // The field value is from after the colon to the next field. + value = rest.substring(rest.indexOf(':') + 1, nextFieldIndex); + this.streamInfoContainer_[ssrc][name] = value; + + // Move |rest| to the start of the next field. + rest = rest.substring(nextFieldIndex + 1); + } + } + }, + + /** + * @param {string} sdp The ssrc id. + * @return {!Object.<string>} The object containing the ssrc infomation. + */ + getStreamInfo: function(ssrc) { + return this.streamInfoContainer_[ssrc]; + }, + + /** + * Populate the ssrc information into |parentElement|, each field as a + * DIV element. + * + * @param {!Element} parentElement The parent element for the ssrc info. + * @param {string} ssrc The ssrc id. + */ + populateSsrcInfo: function(parentElement, ssrc) { + if (!this.streamInfoContainer_[ssrc]) + return; + + parentElement.className = this.SSRC_INFO_BLOCK_CLASS_; + + var fieldElement; + for (var property in this.streamInfoContainer_[ssrc]) { + fieldElement = document.createElement('div'); + parentElement.appendChild(fieldElement); + fieldElement.textContent = + property + ':' + this.streamInfoContainer_[ssrc][property]; + } + } + }; + + return SsrcInfoManager; +})(); diff --git a/content/browser/resources/media/stats_graph_helper.js b/content/browser/resources/media/stats_graph_helper.js index 2fe4114..c252f0a 100644 --- a/content/browser/resources/media/stats_graph_helper.js +++ b/content/browser/resources/media/stats_graph_helper.js @@ -14,6 +14,8 @@ <include src="data_series.js"/> <include src="timeline_graph_view.js"/> +var STATS_GRAPH_CONTAINER_HEADING_CLASS = 'stats-graph-container-heading'; + // Specifies which stats should be drawn on the 'bweCompound' graph and how. var bweCompoundGraphConfig = { googAvailableSendBandwidth: {color: 'red'}, @@ -82,9 +84,12 @@ var dataSeries = {}; // Adds the stats report |singleReport| to the timeline graph for the given // |peerConnectionElement| and |reportName|. -function drawSingleReport(peerConnectionElement, reportName, singleReport) { +function drawSingleReport( + peerConnectionElement, reportType, reportId, singleReport) { if (!singleReport || !singleReport.values) return; + + var reportName = reportType + '-' + reportId; for (var i = 0; i < singleReport.values.length - 1; i = i + 2) { var rawLabel = singleReport.values[i]; var rawValue = parseInt(singleReport.values[i + 1]); @@ -124,7 +129,7 @@ function drawSingleReport(peerConnectionElement, reportName, singleReport) { if (!graphViews[graphViewId]) { graphViews[graphViewId] = createStatsGraphView(peerConnectionElement, - reportName, + reportType, reportId, graphType); var date = new Date(singleReport.timestamp); graphViews[graphViewId].setDateRange(date, date); @@ -150,41 +155,43 @@ function addDataSeriesPoint(dataSeriesId, time, label, value) { dataSeries[dataSeriesId].addPoint(time, value); } -// Ensures a div container to hold all stats graphs for a report type -// is created as a child of |peerConnectionElement|. -function ensureStatsGraphTopContainer(peerConnectionElement, reportName) { +// Ensures a div container to hold all stats graphs for one track is created as +// a child of |peerConnectionElement|. +function ensureStatsGraphTopContainer( + peerConnectionElement, reportType, reportId) { var containerId = peerConnectionElement.id + '-' + - reportName + '-graph-container'; + reportType + '-' + reportId + '-graph-container'; var container = $(containerId); if (!container) { - container = document.createElement('div'); + container = document.createElement('details'); container.id = containerId; - container.className = 'stats-graph-container-collapsed'; + container.className = 'stats-graph-container'; peerConnectionElement.appendChild(container); - container.innerHTML = - '<button>Expand/Collapse Graphs for ' + reportName + '</button>'; - - // Expands or collapses the graphs on click. - container.childNodes[0].addEventListener('click', function(event) { - var element = event.target.parentNode; - if (element.className == 'stats-graph-container-collapsed') - element.className = 'stats-graph-container'; - else - element.className = 'stats-graph-container-collapsed'; - }); + container.innerHTML ='<summary><span></span></summary>'; + container.firstChild.firstChild.className = + STATS_GRAPH_CONTAINER_HEADING_CLASS; + container.firstChild.firstChild.textContent = + 'Stats graphs for ' + reportType + '-' + reportId; + + if (reportType == 'ssrc') { + var ssrcInfoElement = document.createElement('div'); + container.firstChild.appendChild(ssrcInfoElement); + ssrcInfoManager.populateSsrcInfo(ssrcInfoElement, reportId); + } } return container; } // Creates the container elements holding a timeline graph // and the TimelineGraphView object. -function createStatsGraphView(peerConnectionElement, reportName, statsName) { +function createStatsGraphView( + peerConnectionElement, reportType, reportId, statsName) { var topContainer = ensureStatsGraphTopContainer(peerConnectionElement, - reportName); + reportType, reportId); - var graphViewId = - peerConnectionElement.id + '-' + reportName + '-' + statsName; + var graphViewId = peerConnectionElement.id + '-' + + reportType + '-' + reportId + '-' + statsName; var divId = graphViewId + '-div'; var canvasId = graphViewId + '-canvas'; var container = document.createElement("div"); @@ -194,9 +201,10 @@ function createStatsGraphView(peerConnectionElement, reportName, statsName) { container.innerHTML = '<div>' + statsName + '</div>' + '<div id=' + divId + '><canvas id=' + canvasId + '></canvas></div>'; if (statsName == 'bweCompound') { - container.insertBefore(createBweCompoundLegend(peerConnectionElement, - reportName), - $(divId)); + container.insertBefore( + createBweCompoundLegend( + peerConnectionElement, reportType + '-' + reportId), + $(divId)); } return new TimelineGraphView(divId, canvasId); } diff --git a/content/browser/resources/media/stats_table.js b/content/browser/resources/media/stats_table.js new file mode 100644 index 0000000..d31c73a --- /dev/null +++ b/content/browser/resources/media/stats_table.js @@ -0,0 +1,139 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +/** + * Maintains the stats table. + * @param {SsrcInfoManager} ssrcInfoManager The source of the ssrc info. + */ +var StatsTable = (function(ssrcInfoManager) { + 'use strict'; + + /** + * @param {SsrcInfoManager} ssrcInfoManager The source of the ssrc info. + * @constructor + */ + function StatsTable(ssrcInfoManager) { + /** + * @type {SsrcInfoManager} + * @private + */ + this.ssrcInfoManager_ = ssrcInfoManager; + } + + StatsTable.prototype = { + /** + * Adds |report| to the stats table of |peerConnectionElement|. + * + * @param {!Element} peerConnectionElement The root element. + * @param {!Object} report The object containing stats, which is the object + * containing timestamp and values, which is an array of strings, whose + * even index entry is the name of the stat, and the odd index entry is + * the value. + */ + addStatsReport: function(peerConnectionElement, report) { + var statsTable = this.ensureStatsTable_(peerConnectionElement, report); + + if (report.stats) { + this.addStatsToTable_(statsTable, + report.stats.timestamp, report.stats.values); + } + }, + + /** + * Ensure the DIV container for the stats tables is created as a child of + * |peerConnectionElement|. + * + * @param {!Element} peerConnectionElement The root element. + * @return {!Element} The stats table container. + * @private + */ + ensureStatsTableContainer_: function(peerConnectionElement) { + var containerId = peerConnectionElement.id + '-table-container'; + var container = $(containerId); + if (!container) { + container = document.createElement('div'); + container.id = containerId; + container.className = 'stats-table-container'; + peerConnectionElement.appendChild(container); + } + return container; + }, + + /** + * Ensure the stats table for track specified by |report| of PeerConnection + * |peerConnectionElement| is created. + * + * @param {!Element} peerConnectionElement The root element. + * @param {!Object} report The object containing stats, which is the object + * containing timestamp and values, which is an array of strings, whose + * even index entry is the name of the stat, and the odd index entry is + * the value. + * @return {!Element} The stats table element. + * @private + */ + ensureStatsTable_: function(peerConnectionElement, report) { + var tableId = peerConnectionElement.id + '-table-' + + report.type + '-' + report.id; + var table = $(tableId); + if (!table) { + var container = this.ensureStatsTableContainer_(peerConnectionElement); + table = document.createElement('table'); + container.appendChild(table); + table.id = tableId; + table.border = 1; + + table.innerHTML = '<tr><th colspan=2></th></tr>'; + table.rows[0].cells[0].textContent = + 'Statistics ' + report.type + '-' + report.id; + if (report.type == 'ssrc') { + table.insertRow(1); + table.rows[1].innerHTML = '<td colspan=2></td>'; + this.ssrcInfoManager_.populateSsrcInfo( + table.rows[1].cells[0], report.id); + } + } + return table; + }, + + /** + * Update |statsTable| with |time| and |statsData|. + * + * @param {!Element} statsTable Which table to update. + * @param {number} time The number of miliseconds since epoch. + * @param {Array.<string>} statsData An array of stats name and value pairs. + * @private + */ + addStatsToTable_: function(statsTable, time, statsData) { + var date = Date(time); + this.updateStatsTableRow_(statsTable, 'timestamp', date.toLocaleString()); + for (var i = 0; i < statsData.length - 1; i = i + 2) { + this.updateStatsTableRow_(statsTable, statsData[i], statsData[i + 1]); + } + }, + + /** + * Update the value column of the stats row of |rowName| to |value|. + * A new row is created is this is the first report of this stats. + * + * @param {!Element} statsTable Which table to update. + * @param {string} rowName The name of the row to update. + * @param {string} value The new value to set. + * @private + */ + updateStatsTableRow_: function(statsTable, rowName, value) { + var trId = statsTable.id + '-' + rowName; + var trElement = $(trId); + if (!trElement) { + trElement = document.createElement('tr'); + trElement.id = trId; + statsTable.firstChild.appendChild(trElement); + trElement.innerHTML = '<td>' + rowName + '</td><td></td>'; + } + trElement.cells[1].textContent = value; + } + }; + + return StatsTable; +})(); diff --git a/content/browser/resources/media/webrtc_internals.css b/content/browser/resources/media/webrtc_internals.css index 83d1f39..ebf07d5 100644 --- a/content/browser/resources/media/webrtc_internals.css +++ b/content/browser/resources/media/webrtc_internals.css @@ -2,25 +2,28 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -.log-container { + +.peer-connection-hidden > *:not(h3) { + display:none; +} + +.update-log-container { float: left; } -.stats-graph-container, -.stats-graph-container-collapsed { - clear: both; - margin: 0.5em 0 0.5em 0; +.ssrc-info-block { + color: #999; + font-size: 0.8em; } -.stats-graph-container button, -.stats-graph-container-collapsed button { - display: block; - margin: 0; - padding: 0; +.stats-graph-container { + clear: both; + margin: 0.5em 0 0.5em 0; } -.stats-graph-container-collapsed .stats-graph-sub-container { - display: none; +.stats-graph-container-heading { + font-size: 0.8em; + font-weight: bold; } .stats-graph-sub-container { @@ -47,7 +50,7 @@ body { } details { - width: 30em; + min-width: 30em; } h3 + div { @@ -64,9 +67,11 @@ h2 { } h3 { - color: #666; + color: #555; + cursor: pointer; font-size: 0.9em; - margin: 1em 0 0.5em 0; + margin: 2em 0 0.5em 0; + text-decoration: underline; } li { @@ -91,12 +96,6 @@ td:first-child { padding-top: 0.3em; } -textarea { - border: none; - outline: none; - width: 100%; -} - table > tr { vertical-align: top; } diff --git a/content/browser/resources/media/webrtc_internals.js b/content/browser/resources/media/webrtc_internals.js index 1493d56d..05eb60ee 100644 --- a/content/browser/resources/media/webrtc_internals.js +++ b/content/browser/resources/media/webrtc_internals.js @@ -2,209 +2,159 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -<include src="stats_graph_helper.js"/> var peerConnectionsListElem = null; +var ssrcInfoManager = null; +var peerConnectionUpdateTable = null; +var statsTable = null; + +<include src="ssrc_info_manager.js"/> +<include src="stats_graph_helper.js"/> +<include src="stats_table.js"/> +<include src="peer_connection_update_table.js"/> function initialize() { peerConnectionsListElem = $('peer-connections-list'); + ssrcInfoManager = new SsrcInfoManager(); + peerConnectionUpdateTable = new PeerConnectionUpdateTable(); + statsTable = new StatsTable(ssrcInfoManager); + chrome.send('getAllUpdates'); - startGetStats(); -} -// Polls stats from all PeerConnections every second. -function startGetStats() { - if (document.getElementsByTagName('li').length) - chrome.send('getAllStats'); - window.setTimeout(startGetStats, 1000); + // Requests stats from all peer connections every second. + window.setInterval(function() { + if (peerConnectionsListElem.getElementsByTagName('li').length > 0) + chrome.send('getAllStats'); + }, 1000); } +document.addEventListener('DOMContentLoaded', initialize); + +/** + * A helper function for getting a peer connection element id. + * + * @param {!Object.<string, number>} data The object containing the pid and lid + * of the peer connection. + * @return {string} The peer connection element id. + */ function getPeerConnectionId(data) { return data.pid + '-' + data.lid; } -// Makes sure a LI element representing a PeerConnection is created -// and appended to peerConnectionListElem. -function ensurePeerConnectionElement(id) { - var element = $(id); - if (!element) { - element = document.createElement('li'); - peerConnectionsListElem.appendChild(element); - element.id = id; - } - return element; -} - -// Makes sure the table representing the PeerConnection event log is created -// and appended to peerConnectionElement. -function ensurePeerConnectionLog(peerConnectionElement) { - var logId = peerConnectionElement.id + '-log'; - var logElement = $(logId); - if (!logElement) { - var container = document.createElement('div'); - container.className = 'log-container'; - peerConnectionElement.appendChild(container); - - logElement = document.createElement('table'); - logElement.id = logId; - logElement.className = 'log-table'; - logElement.border = 1; - container.appendChild(logElement); - logElement.innerHTML = '<tr><th>Time</th>' + - '<th class="log-header-event">Event</th></tr>'; - } - return logElement; -} - -// Add the update to the log table as a new row. The type of the update is set -// as the text of the cell; clicking the cell will reveal or hide the details -// as the content of a TextArea element. -function addToPeerConnectionLog(logElement, update) { - var row = document.createElement('tr'); - logElement.appendChild(row); - - var expandable = (update.value.length > 0); - // details.open is true initially so that we can get the real scrollHeight - // of the textareas. - row.innerHTML = - '<td>' + (new Date()).toLocaleString() + '</td>' + - (expandable ? - '<td><details open><summary>' + update.type + '</summary>' + - '</details></td>' : - '<td>' + update.type + '</td>'); - if (!expandable) - return; - - var valueContainer = document.createElement('textarea'); - var details = row.cells[1].childNodes[0]; - details.appendChild(valueContainer); - valueContainer.value = update.value; - valueContainer.style.height = valueContainer.scrollHeight + 'px'; - details.open = false; -} - -// Ensure the DIV container for the stats tables is created as a child of -// |peerConnectionElement|. -function ensureStatsTableContainer(peerConnectionElement) { - var containerId = peerConnectionElement.id + '-table-container'; - var container = $(containerId); - if (!container) { - container = document.createElement('div'); - container.id = containerId; - container.className = 'stats-table-container'; - peerConnectionElement.appendChild(container); - } - return container; -} - -// Ensure the stats table for track |statsId| of PeerConnection -// |peerConnectionElement| is created as a child of the stats table container. -function ensureStatsTable(peerConnectionElement, statsId) { - var tableId = peerConnectionElement.id + '-table-' + statsId; - var table = $(tableId); - if (!table) { - var container = ensureStatsTableContainer(peerConnectionElement); - table = document.createElement('table'); - container.appendChild(table); - table.id = tableId; - table.border = 1; - table.innerHTML = '<th>Statistics ' + statsId + '</th>'; - } - return table; -} -// Update the value column of the stats row of |rowName| to |value|. -// A new row is created is this is the first report of this stats. -function updateStatsTableRow(statsTable, rowName, value) { - var trId = statsTable.id + '-' + rowName; - var trElement = $(trId); - if (!trElement) { - trElement = document.createElement('tr'); - trElement.id = trId; - statsTable.appendChild(trElement); - trElement.innerHTML = '<td>' + rowName + '</td><td></td>'; +/** + * Extracts ssrc info from a setLocal/setRemoteDescription update. + * + * @param {!PeerConnectionUpdateEntry} data The peer connection update data. + */ +function extractSsrcInfo(data) { + if (data.type == 'setLocalDescription' || + data.type == 'setRemoteDescription') { + ssrcInfoManager.addSsrcStreamInfo(data.value); } - trElement.cells[1].textContent = value; } -// Add |singleReport| to the stats table. -function addSingleReportToTable(statsTable, singleReport) { - if (!singleReport || !singleReport.values || singleReport.values.length == 0) - return; - var date = Date(singleReport.timestamp); - updateStatsTableRow(statsTable, 'timestamp', date.toLocaleString()); - for (var i = 0; i < singleReport.values.length - 1; i = i + 2) { - updateStatsTableRow(statsTable, singleReport.values[i], - singleReport.values[i + 1]); - } -} +/** + * Browser message handlers. + */ -// -// Browser message handlers. -// -// data = {pid:|integer|, lid:|integer|}. +/** + * Removes all information about a peer connection. + * + * @param {!Object.<string, number>} data The object containing the pid and lid + * of a peer connection. + */ function removePeerConnection(data) { var element = $(getPeerConnectionId(data)); if (element) peerConnectionsListElem.removeChild(element); } -// data = {pid:|integer|, lid:|integer|, -// url:|string|, servers:|string|, constraints:|string|}. + +/** + * Adds a peer connection. + * + * @param {!Object} data The object containing the pid, lid, url, servers, and + * constraints of a peer connection. + */ function addPeerConnection(data) { - var peerConnectionElement = ensurePeerConnectionElement( - getPeerConnectionId(data)); + var peerConnectionElement = $(getPeerConnectionId(data)); + if (!peerConnectionElement) { + peerConnectionElement = document.createElement('li'); + peerConnectionsListElem.appendChild(peerConnectionElement); + peerConnectionElement.id = getPeerConnectionId(data); + } peerConnectionElement.innerHTML = '<h3>PeerConnection ' + peerConnectionElement.id + '</h3>' + '<div>' + data.url + ' ' + data.servers + ' ' + data.constraints + '</div>'; + + // Clicking the heading can expand or collapse the peer connection item. + peerConnectionElement.firstChild.title = 'Click to collapse or expand'; + peerConnectionElement.firstChild.addEventListener('click', function(e) { + if (e.target.parentElement.className == '') + e.target.parentElement.className = 'peer-connection-hidden'; + else + e.target.parentElement.className = ''; + }); return peerConnectionElement; } -// data = {pid:|integer|, lid:|integer|, type:|string|, value:|string|}. + +/** + * Adds a peer connection update. + * + * @param {!PeerConnectionUpdateEntry} data The peer connection update data. + */ function updatePeerConnection(data) { - var peerConnectionElement = ensurePeerConnectionElement( - getPeerConnectionId(data)); - var logElement = ensurePeerConnectionLog(peerConnectionElement); - addToPeerConnectionLog(logElement, data); + var peerConnectionElement = $(getPeerConnectionId(data)); + peerConnectionUpdateTable.addPeerConnectionUpdate( + peerConnectionElement, data); + extractSsrcInfo(data); } -// data is an array and each entry is -// {pid:|integer|, lid:|integer|, -// url:|string|, servers:|string|, constraints:|string|, log:|array|}, -// each entry of log is {type:|string|, value:|string|}. + +/** + * Adds the information of all peer connections created so far. + * + * @param {Array.<!Object>} data An array of the information of all peer + * connections. Each array item contains pid, lid, url, servers, + * constraints, and an array of updates as the log. + */ function updateAllPeerConnections(data) { for (var i = 0; i < data.length; ++i) { var peerConnection = addPeerConnection(data[i]); - var logElement = ensurePeerConnectionLog(peerConnection); var log = data[i].log; for (var j = 0; j < log.length; ++j) { - addToPeerConnectionLog(logElement, log[j]); + peerConnectionUpdateTable.addPeerConnectionUpdate( + peerConnection, log[j]); + extractSsrcInfo(log[j]); } } } -// data = {pid:|integer|, lid:|integer|, reports:|array|}. -// Each entry of reports = -// {id:|string|, type:|string|, stats:|object|}, -// where |stats| = {timestamp: |double|, values: |array|}, -// where |values| is an array of strings, whose even index entry represents -// the name of the stat, and the odd index entry represents the value of -// the stat. + +/** + * Handles the report of stats. + * + * @param {!Object} data The object containing pid, lid, and reports, where + * reports is an array of stats reports. Each report contains id, type, + * and stats, where stats is the object containing timestamp and values, + * which is an array of strings, whose even index entry is the name of the + * stat, and the odd index entry is the value. + */ function addStats(data) { - var peerConnectionElement = ensurePeerConnectionElement( - getPeerConnectionId(data)); + var peerConnectionElement = $(getPeerConnectionId(data)); + if (!peerConnectionElement) + return; + for (var i = 0; i < data.reports.length; ++i) { var report = data.reports[i]; - var reportName = report.type + '-' + report.id; - var statsTable = ensureStatsTable(peerConnectionElement, reportName); - - addSingleReportToTable(statsTable, report.stats); - drawSingleReport(peerConnectionElement, reportName, report.stats); + statsTable.addStatsReport(peerConnectionElement, report); + drawSingleReport(peerConnectionElement, + report.type, report.id, report.stats); } } - -document.addEventListener('DOMContentLoaded', initialize); |