blob: 2a244bde1d823fa8b1835f068d20e75932e780c2 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2013 The Chromium Authors
[email protected]d4655fa2013-01-11 05:41:392// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Rebekah Potter952290e2022-11-18 09:07:285import {addWebUiListener, sendWithPromise} from 'chrome://resources/js/cr.js';
dpapad303c92812023-10-31 02:08:356import {$} from 'chrome://resources/js/util.js';
rbpotter5796b002021-03-10 18:49:217
dpapad303c92812023-10-31 02:08:358import {createIceCandidateGrid, updateIceCandidateGrid} from './candidate_grid.js';
rbpotter5796b002021-03-10 18:49:219import {MAX_STATS_DATA_POINT_BUFFER_SIZE} from './data_series.js';
10import {DumpCreator, peerConnectionDataStore, userMediaRequests} from './dump_creator.js';
11import {PeerConnectionUpdateTable} from './peer_connection_update_table.js';
rbpotter5796b002021-03-10 18:49:2112import {drawSingleReport, removeStatsReportGraphs} from './stats_graph_helper.js';
13import {StatsRatesCalculator, StatsReport} from './stats_rates_calculator.js';
14import {StatsTable} from './stats_table.js';
15import {TabView} from './tab_view.js';
Philipp Hancke6f8193b32023-09-19 08:05:3716import {UserMediaTable} from './user_media_table.js';
[email protected]8cb570c2014-07-22 00:07:3217
Philipp Hancke0635d3142021-03-16 20:02:0918let tabView = null;
Philipp Hancke0635d3142021-03-16 20:02:0919let peerConnectionUpdateTable = null;
20let statsTable = null;
[email protected]deb232b2022-11-28 11:22:1621let userMediaTable = null;
Philipp Hancke0635d3142021-03-16 20:02:0922let dumpCreator = null;
rbpotter5796b002021-03-10 18:49:2123
Philipp Hancke788150142023-09-21 07:19:5424const searchParameters = new URLSearchParams(window.location.search);
25
Henrik Boströmb6d732af2019-04-23 11:32:2926/** Maps from id (see getPeerConnectionId) to StatsRatesCalculator. */
rbpotter5796b002021-03-10 18:49:2127const statsRatesCalculatorById = new Map();
Henrik Boströmb6d732af2019-04-23 11:32:2928
[email protected]4d41b802013-05-15 18:38:2329/** A simple class to store the updates and stats data for a peer connection. */
[email protected]4d41b802013-05-15 18:38:2330 /** @constructor */
rbpotter5796b002021-03-10 18:49:2131class PeerConnectionRecord {
32 constructor() {
[email protected]4d41b802013-05-15 18:38:2333 /** @private */
34 this.record_ = {
Patrick Monettece1ee722021-03-30 18:41:0535 pid: -1,
[email protected]4d41b802013-05-15 18:38:2336 constraints: {},
[email protected]c13db2d2014-07-25 20:24:5437 rtcConfiguration: [],
[email protected]4d41b802013-05-15 18:38:2338 stats: {},
39 updateLog: [],
40 url: '',
41 };
Philipp Hancke949b72f2018-05-07 18:11:3542 }
[email protected]4d41b802013-05-15 18:38:2343
rbpotter5796b002021-03-10 18:49:2144 /** @override */
45 toJSON() {
46 return this.record_;
47 }
[email protected]4d41b802013-05-15 18:38:2348
rbpotter5796b002021-03-10 18:49:2149 /**
50 * Adds the initialization info of the peer connection.
Patrick Monettece1ee722021-03-30 18:41:0551 * @param {number} pid The pid of the process hosting the peer connection.
rbpotter5796b002021-03-10 18:49:2152 * @param {string} url The URL of the web page owning the peer connection.
53 * @param {Array} rtcConfiguration
54 * @param {!Object} constraints Media constraints.
55 */
Patrick Monettece1ee722021-03-30 18:41:0556 initialize(pid, url, rtcConfiguration, constraints) {
57 this.record_.pid = pid;
rbpotter5796b002021-03-10 18:49:2158 this.record_.url = url;
59 this.record_.rtcConfiguration = rtcConfiguration;
60 this.record_.constraints = constraints;
61 }
[email protected]4d41b802013-05-15 18:38:2362
rbpotter5796b002021-03-10 18:49:2163 resetStats() {
64 this.record_.stats = {};
65 }
Henrik Boströmb6d732af2019-04-23 11:32:2966
rbpotter5796b002021-03-10 18:49:2167 /**
68 * @param {string} dataSeriesId The TimelineDataSeries identifier.
69 * @return {!TimelineDataSeries}
70 */
71 getDataSeries(dataSeriesId) {
72 return this.record_.stats[dataSeriesId];
73 }
[email protected]4d41b802013-05-15 18:38:2374
rbpotter5796b002021-03-10 18:49:2175 /**
76 * @param {string} dataSeriesId The TimelineDataSeries identifier.
77 * @param {!TimelineDataSeries} dataSeries The TimelineDataSeries to set to.
78 */
79 setDataSeries(dataSeriesId, dataSeries) {
80 this.record_.stats[dataSeriesId] = dataSeries;
81 }
[email protected]4d41b802013-05-15 18:38:2382
rbpotter5796b002021-03-10 18:49:2183 /**
84 * @param {!Object} update The object contains keys "time", "type", and
85 * "value".
86 */
87 addUpdate(update) {
Philipp Hancke0635d3142021-03-16 20:02:0988 const time = new Date(parseFloat(update.time));
rbpotter5796b002021-03-10 18:49:2189 this.record_.updateLog.push({
Philipp Hancke59d6e9a52025-07-22 12:09:0190 timestamp: parseFloat(update.time),
91 time: time.toLocaleString(), // deprecated, prefer timestamp.
rbpotter5796b002021-03-10 18:49:2192 type: update.type,
93 value: update.value,
94 });
95 }
96}
[email protected]4d41b802013-05-15 18:38:2397
[email protected]d4655fa2013-01-11 05:41:3998function initialize() {
[email protected]31e91842013-11-08 19:06:1599 dumpCreator = new DumpCreator($('content-root'));
Philipp Hancke015dac82023-04-14 07:47:50100
[email protected]31e91842013-11-08 19:06:15101 tabView = new TabView($('content-root'));
[email protected]2746df92013-04-26 23:42:32102 peerConnectionUpdateTable = new PeerConnectionUpdateTable();
Philipp Hanckeba4adef2023-12-20 14:43:13103 statsTable = new StatsTable();
[email protected]deb232b2022-11-28 11:22:16104 userMediaTable = new UserMediaTable(tabView, userMediaRequests);
[email protected]2746df92013-04-26 23:42:32105
rbpotter5796b002021-03-10 18:49:21106 // Add listeners for all the updates that get sent from webrtc_internals.cc.
Rebekah Potter952290e2022-11-18 09:07:28107 addWebUiListener('add-peer-connection', addPeerConnection);
108 addWebUiListener('update-peer-connection', updatePeerConnection);
109 addWebUiListener('update-all-peer-connections', updateAllPeerConnections);
110 addWebUiListener('remove-peer-connection', removePeerConnection);
111 addWebUiListener('add-standard-stats', addStandardStats);
[email protected]deb232b2022-11-28 11:22:16112 addWebUiListener('add-media', (data) => {
113 userMediaRequests.push(data);
114 userMediaTable.addMedia(data)
115 });
116 addWebUiListener('update-media', (data) => {
117 userMediaRequests.push(data);
118 userMediaTable.updateMedia(data);
119 });
120 addWebUiListener('remove-media-for-renderer', (data) => {
121 for (let i = userMediaRequests.length - 1; i >= 0; --i) {
122 if (userMediaRequests[i].rid === data.rid) {
123 userMediaRequests.splice(i, 1);
124 }
125 }
126 userMediaTable.removeMediaForRenderer(data);
127 });
Rebekah Potter952290e2022-11-18 09:07:28128 addWebUiListener(
rbpotter5796b002021-03-10 18:49:21129 'event-log-recordings-file-selection-cancelled',
130 eventLogRecordingsFileSelectionCancelled);
Rebekah Potter952290e2022-11-18 09:07:28131 addWebUiListener(
rbpotter5796b002021-03-10 18:49:21132 'audio-debug-recordings-file-selection-cancelled',
133 audioDebugRecordingsFileSelectionCancelled);
Philip Eliasson9b5072d42025-05-13 13:13:49134 addWebUiListener(
135 'data-channel-recordings-file-selection-cancelled',
136 dataChannelRecordingsFileSelectionCancelled);
rbpotter5796b002021-03-10 18:49:21137
138 // Request initial startup parameters.
139 sendWithPromise('finishedDOMLoad').then(params => {
140 if (params.audioDebugRecordingsEnabled) {
141 dumpCreator.setAudioDebugRecordingsCheckbox();
142 }
143 if (params.eventLogRecordingsEnabled) {
144 dumpCreator.setEventLogRecordingsCheckbox();
145 }
Philip Eliasson9b5072d42025-05-13 13:13:49146 if (params.dataChannelRecordingsEnabled) {
147 dumpCreator.setDataChannelRecordingsCheckbox();
148 }
rbpotter5796b002021-03-10 18:49:21149 dumpCreator.setEventLogRecordingsCheckboxMutability(
150 params.eventLogRecordingsToggleable);
151 });
[email protected]6efd5f22013-02-06 19:20:37152
Philipp Hanckef212a842022-08-19 08:03:03153 // Requests stats from all peer connections every second unless specified via
154 // ?statsInterval=(milliseconds >= 100ms)
Philipp Hanckef212a842022-08-19 08:03:03155 let statsInterval = 1000;
156 if (searchParameters.has('statsInterval')) {
157 statsInterval = Math.max(
158 parseInt(searchParameters.get('statsInterval'), 10),
159 100);
160 if (!isFinite(statsInterval)) {
161 statsInterval = 1000;
162 }
163 }
164 window.setInterval(requestStats, statsInterval);
[email protected]94fb5102013-01-23 09:00:47165}
[email protected]2746df92013-04-26 23:42:32166document.addEventListener('DOMContentLoaded', initialize);
[email protected]94fb5102013-01-23 09:00:47167
Henrik Boströmb6d732af2019-04-23 11:32:29168/**
169 * Sends a request to the browser to get peer connection statistics from the
170 * standard getStats() API (promise-based).
171 */
Henrik Boström80fb1ff32023-12-07 18:58:22172function requestStats() {
Henrik Boströmb6d732af2019-04-23 11:32:29173 if (Object.keys(peerConnectionDataStore).length > 0) {
174 chrome.send('getStandardStats');
175 }
176}
177
178/**
[email protected]2746df92013-04-26 23:42:32179 * A helper function for getting a peer connection element id.
180 *
Patrick Monettece1ee722021-03-30 18:41:05181 * @param {!Object<number>} data The object containing the rid and lid of the
thestig7779e7d2015-05-30 07:48:30182 * peer connection.
[email protected]2746df92013-04-26 23:42:32183 * @return {string} The peer connection element id.
184 */
[email protected]94fb5102013-01-23 09:00:47185function getPeerConnectionId(data) {
Patrick Monettece1ee722021-03-30 18:41:05186 return data.rid + '-' + data.lid;
[email protected]94fb5102013-01-23 09:00:47187}
188
[email protected]2746df92013-04-26 23:42:32189/**
[email protected]8cb570c2014-07-22 00:07:32190 * A helper function for appending a child element to |parent|.
191 *
192 * @param {!Element} parent The parent element.
193 * @param {string} tag The child element tag.
194 * @param {string} text The textContent of the new DIV.
195 * @return {!Element} the new DIV element.
196 */
197function appendChildWithText(parent, tag, text) {
Philipp Hancke0635d3142021-03-16 20:02:09198 const child = document.createElement(tag);
[email protected]8cb570c2014-07-22 00:07:32199 child.textContent = text;
200 parent.appendChild(child);
201 return child;
202}
203
204/**
[email protected]4d41b802013-05-15 18:38:23205 * Helper for adding a peer connection update.
206 *
207 * @param {Element} peerConnectionElement
208 * @param {!PeerConnectionUpdateEntry} update The peer connection update data.
[email protected]2746df92013-04-26 23:42:32209 */
[email protected]4d41b802013-05-15 18:38:23210function addPeerConnectionUpdate(peerConnectionElement, update) {
Nasko Oskov9303a0662018-10-15 18:03:44211 peerConnectionUpdateTable.addPeerConnectionUpdate(
212 peerConnectionElement, update);
[email protected]84e83b32014-07-01 23:10:15213 peerConnectionDataStore[peerConnectionElement.id].addUpdate(update);
[email protected]4d41b802013-05-15 18:38:23214}
215
216
217/** Browser message handlers. */
[email protected]2746df92013-04-26 23:42:32218
219
220/**
221 * Removes all information about a peer connection.
Philipp Hancke788150142023-09-21 07:19:54222 * Use ?keepRemovedConnections url parameter to prevent the removal.
[email protected]2746df92013-04-26 23:42:32223 *
Patrick Monettece1ee722021-03-30 18:41:05224 * @param {!Object<number>} data The object containing the rid and lid of a peer
thestig7779e7d2015-05-30 07:48:30225 * connection.
[email protected]2746df92013-04-26 23:42:32226 */
[email protected]94fb5102013-01-23 09:00:47227function removePeerConnection(data) {
Rebekah Potter8148f852022-11-29 18:04:37228 // Disable getElementById restriction here, since |getPeerConnectionId| does
229 // not return valid selectors.
230 // eslint-disable-next-line no-restricted-properties
Philipp Hancke788150142023-09-21 07:19:54231
Rebekah Potter8148f852022-11-29 18:04:37232 const element = document.getElementById(getPeerConnectionId(data));
Philipp Hancke788150142023-09-21 07:19:54233 if (element && !searchParameters.has('keepRemovedConnections')) {
Philipp Hancke43e64b172024-04-17 13:41:58234 removeStatsReportGraphs(element);
[email protected]4d41b802013-05-15 18:38:23235 delete peerConnectionDataStore[element.id];
fserb3c1769f2017-03-09 16:27:03236 tabView.removeTab(element.id);
[email protected]4d41b802013-05-15 18:38:23237 }
[email protected]94fb5102013-01-23 09:00:47238}
239
[email protected]2746df92013-04-26 23:42:32240/**
241 * Adds a peer connection.
242 *
Patrick Monettece1ee722021-03-30 18:41:05243 * @param {!Object} data The object containing the rid, lid, pid, url,
[email protected]c13db2d2014-07-25 20:24:54244 * rtcConfiguration, and constraints of a peer connection.
[email protected]2746df92013-04-26 23:42:32245 */
[email protected]94fb5102013-01-23 09:00:47246function addPeerConnection(data) {
Philipp Hancke0635d3142021-03-16 20:02:09247 const id = getPeerConnectionId(data);
[email protected]4d41b802013-05-15 18:38:23248
249 if (!peerConnectionDataStore[id]) {
250 peerConnectionDataStore[id] = new PeerConnectionRecord();
251 }
252 peerConnectionDataStore[id].initialize(
Patrick Monettece1ee722021-03-30 18:41:05253 data.pid, data.url, data.rtcConfiguration, data.constraints);
[email protected]4d41b802013-05-15 18:38:23254
Rebekah Potter8148f852022-11-29 18:04:37255 // Disable getElementById restriction here, since |id| is not always
256 // a valid selector.
257 // eslint-disable-next-line no-restricted-properties
258 let peerConnectionElement = document.getElementById(id);
[email protected]2746df92013-04-26 23:42:32259 if (!peerConnectionElement) {
Patrick Monettece1ee722021-03-30 18:41:05260 const details = `[ rid: ${data.rid}, lid: ${data.lid}, pid: ${data.pid} ]`;
261 peerConnectionElement = tabView.addTab(id, data.url + " " + details);
[email protected]2746df92013-04-26 23:42:32262 }
jiayl857722c82015-02-24 18:27:39263
Philipp Hancke0635d3142021-03-16 20:02:09264 const p = document.createElement('p');
Philipp Hancke33980972021-03-25 07:48:12265 appendChildWithText(p, 'span', data.url);
266 appendChildWithText(p, 'span', ', ');
267 appendChildWithText(p, 'span', data.rtcConfiguration);
268 if (data.constraints !== '') {
269 appendChildWithText(p, 'span', ', ');
270 appendChildWithText(p, 'span', data.constraints);
271 }
jiayl857722c82015-02-24 18:27:39272 peerConnectionElement.appendChild(p);
[email protected]4d41b802013-05-15 18:38:23273
Philipp Hancke6cd40792021-04-29 07:55:52274 // Show deprecation notices as a list.
275 // Note: data.rtcConfiguration is not in JSON format and may
276 // not be defined in tests.
Philipp Hanckeb20fd032021-09-08 07:32:43277 const deprecationNotices = document.createElement('ul');
Philipp Hancke6cd40792021-04-29 07:55:52278 if (data.rtcConfiguration) {
Philipp Hancke6cd40792021-04-29 07:55:52279 deprecationNotices.className = 'peerconnection-deprecations';
Philipp Hancke6cd40792021-04-29 07:55:52280 }
Philipp Hanckeb20fd032021-09-08 07:32:43281 peerConnectionElement.appendChild(deprecationNotices);
Philipp Hancke6cd40792021-04-29 07:55:52282
Philipp Hancke9b812b5d2021-10-12 18:06:16283 const iceConnectionStates = document.createElement('div');
284 iceConnectionStates.textContent = 'ICE connection state: new';
285 iceConnectionStates.className = 'iceconnectionstate';
286 peerConnectionElement.appendChild(iceConnectionStates);
287
288 const connectionStates = document.createElement('div');
289 connectionStates.textContent = 'Connection state: new';
290 connectionStates.className = 'connectionstate';
291 peerConnectionElement.appendChild(connectionStates);
292
293 const signalingStates = document.createElement('div');
294 signalingStates.textContent = 'Signaling state: new';
295 signalingStates.className = 'signalingstate';
296 peerConnectionElement.appendChild(signalingStates);
297
Philipp Hancke1d84f9c2021-10-27 08:55:22298 const candidatePair = document.createElement('div');
299 candidatePair.textContent = 'ICE Candidate pair: ';
300 candidatePair.className = 'candidatepair';
301 candidatePair.appendChild(document.createElement('span'));
302 peerConnectionElement.appendChild(candidatePair);
303
Philipp Hanckecd79cbf2021-11-17 14:11:52304 createIceCandidateGrid(peerConnectionElement);
[email protected]c054f092013-01-27 08:12:49305 return peerConnectionElement;
306}
307
[email protected]2746df92013-04-26 23:42:32308
309/**
310 * Adds a peer connection update.
311 *
312 * @param {!PeerConnectionUpdateEntry} data The peer connection update data.
313 */
[email protected]c054f092013-01-27 08:12:49314function updatePeerConnection(data) {
Rebekah Potter8148f852022-11-29 18:04:37315 // Disable getElementById restriction here, since |getPeerConnectionId| does
316 // not return valid selectors.
317 const peerConnectionElement =
318 // eslint-disable-next-line no-restricted-properties
319 document.getElementById(getPeerConnectionId(data));
[email protected]4d41b802013-05-15 18:38:23320 addPeerConnectionUpdate(peerConnectionElement, data);
[email protected]c054f092013-01-27 08:12:49321}
322
[email protected]2746df92013-04-26 23:42:32323
324/**
325 * Adds the information of all peer connections created so far.
326 *
Dan Beamb9749f412015-02-14 02:42:50327 * @param {Array<!Object>} data An array of the information of all peer
Patrick Monettece1ee722021-03-30 18:41:05328 * connections. Each array item contains rid, lid, pid, url,
329 * rtcConfiguration, constraints, and an array of updates as the log.
[email protected]2746df92013-04-26 23:42:32330 */
[email protected]c054f092013-01-27 08:12:49331function updateAllPeerConnections(data) {
Philipp Hancke0635d3142021-03-16 20:02:09332 for (let i = 0; i < data.length; ++i) {
333 const peerConnection = addPeerConnection(data[i]);
[email protected]c054f092013-01-27 08:12:49334
Philipp Hancke0635d3142021-03-16 20:02:09335 const log = data[i].log;
Dan Beambdd7d822019-01-05 00:59:42336 if (!log) {
[email protected]21384632013-09-20 21:18:15337 continue;
Dan Beambdd7d822019-01-05 00:59:42338 }
Philipp Hancke0635d3142021-03-16 20:02:09339 for (let j = 0; j < log.length; ++j) {
[email protected]4d41b802013-05-15 18:38:23340 addPeerConnectionUpdate(peerConnection, log[j]);
[email protected]c054f092013-01-27 08:12:49341 }
342 }
[email protected]0a681b42014-02-19 01:56:32343 requestStats();
[email protected]d4655fa2013-01-11 05:41:39344}
345
[email protected]2746df92013-04-26 23:42:32346/**
Henrik Boström33ece3e92019-04-23 10:08:53347 * Handles the report of stats originating from the standard getStats() API.
[email protected]2746df92013-04-26 23:42:32348 *
Patrick Monettece1ee722021-03-30 18:41:05349 * @param {!Object} data The object containing rid, lid, and reports, where
[email protected]2746df92013-04-26 23:42:32350 * reports is an array of stats reports. Each report contains id, type,
351 * and stats, where stats is the object containing timestamp and values,
352 * which is an array of strings, whose even index entry is the name of the
353 * stat, and the odd index entry is the value.
354 */
Henrik Boström33ece3e92019-04-23 10:08:53355function addStandardStats(data) {
Rebekah Potter8148f852022-11-29 18:04:37356 // Disable getElementById restriction here, since |getPeerConnectionId| does
357 // not return valid selectors.
358 // eslint-disable-next-line no-restricted-properties
359 const peerConnectionElement =
360 // eslint-disable-next-line no-restricted-properties
361 document.getElementById(getPeerConnectionId(data));
Henrik Boströmb6d732af2019-04-23 11:32:29362 if (!peerConnectionElement) {
363 return;
364 }
365 const pcId = getPeerConnectionId(data);
366 let statsRatesCalculator = statsRatesCalculatorById.get(pcId);
367 if (!statsRatesCalculator) {
368 statsRatesCalculator = new StatsRatesCalculator();
369 statsRatesCalculatorById.set(pcId, statsRatesCalculator);
370 }
371 const r = StatsReport.fromInternalsReportList(data.reports);
372 statsRatesCalculator.addStatsReport(r);
373 data.reports = statsRatesCalculator.currentReport.toInternalsReportList();
Philipp Hancke0635d3142021-03-16 20:02:09374 for (let i = 0; i < data.reports.length; ++i) {
375 const report = data.reports[i];
Henrik Boströmb6d732af2019-04-23 11:32:29376 statsTable.addStatsReport(peerConnectionElement, report);
Philipp Hanckeba4adef2023-12-20 14:43:13377 drawSingleReport(peerConnectionElement, report);
Henrik Boströmb6d732af2019-04-23 11:32:29378 }
Philipp Hancke1d84f9c2021-10-27 08:55:22379 // Determine currently connected candidate pair.
380 const stats = r.statsById;
381
Philipp Hancke9edd62d32025-07-25 15:04:42382 let ids = [];
Philipp Hancke1d84f9c2021-10-27 08:55:22383 stats.forEach(report => {
Philipp Hancke9edd62d32025-07-25 15:04:42384 if (!(report.type === 'transport' && report.selectedCandidatePairId)) {
385 return;
386 }
387 const activeCandidatePair = stats.get(report.selectedCandidatePairId);
388 const remoteCandidate = stats.get(activeCandidatePair.remoteCandidateId);
389 const localCandidate = stats.get(activeCandidatePair.localCandidateId);
390
391 const candidateElement = peerConnectionElement
392 .getElementsByClassName('candidatepair')[0].firstElementChild;
393 candidateElement.innerText = '';
394 if (!(localCandidate && remoteCandidate)) {
395 return;
396 candidateElement.innerText = '(not connected)';
397 }
398
399 if (localCandidate.address &&
400 localCandidate.address.indexOf(':') !== -1) {
401 // Show IPv6 in []
402 candidateElement.innerText +='[' + localCandidate.address + ']';
403 } else {
404 candidateElement.innerText += localCandidate.address || '(not set)';
405 }
406 candidateElement.innerText += ':' + localCandidate.port + ' <=> ';
407
408 if (remoteCandidate.address &&
409 remoteCandidate.address.indexOf(':') !== -1) {
410 // Show IPv6 in []
411 candidateElement.innerText +='[' + remoteCandidate.address + ']';
412 } else {
413 candidateElement.innerText += remoteCandidate.address || '(not set)';
414 }
415 candidateElement.innerText += ':' + remoteCandidate.port;
416 ids = ids.concat([
417 peerConnectionElement.id + '-table-' + activeCandidatePair.id,
418 peerConnectionElement.id + '-table-' + localCandidate.id,
419 peerConnectionElement.id + '-table-' + remoteCandidate.id,
420 ]);
421 });
422 console.log('IDS', ids);
423 // Mark active local-candidate, remote candidate and candidate pair
424 // bold in the table.
425 // Disable getElementById restriction here, since |peerConnectionElement|
426 // doesn't always have a valid selector ID.
427 // First remove bold from each, then re-add for each active pair..
428 const statsContainer =
429 // eslint-disable-next-line no-restricted-properties
430 document.getElementById(peerConnectionElement.id + '-table-container');
431 const activeConnectionClass = 'stats-table-active-connection';
432 statsContainer.childNodes.forEach(node => {
433 if (node.nodeName !== 'DETAILS' || !node.children[1]) {
434 return;
435 }
436 if (ids.includes(node.children[1].id)) {
437 node.firstElementChild.classList.add(activeConnectionClass);
438 } else {
439 node.firstElementChild.classList.remove(activeConnectionClass);
Philipp Hancke1d84f9c2021-10-27 08:55:22440 }
441 });
442
Philipp Hancke9edd62d32025-07-25 15:04:42443 // Mark active candidate-pair graph bold.
444 const statsGraphContainers = peerConnectionElement
445 .getElementsByClassName('stats-graph-container');
446 for (let i = 0; i < statsGraphContainers.length; i++) {
447 const node = statsGraphContainers[i];
448 if (node.nodeName !== 'DETAILS') {
449 continue;
Philipp Hancke1d84f9c2021-10-27 08:55:22450 }
Philipp Hancke9edd62d32025-07-25 15:04:42451 if (ids.includes(node.children[1].id)) {
452 node.firstElementChild.classList.add(activeConnectionClass);
453 } else {
454 node.firstElementChild.classList.remove(activeConnectionClass);
Philipp Hancke1d84f9c2021-10-27 08:55:22455 }
Philipp Hancke1d84f9c2021-10-27 08:55:22456 }
Philipp Hanckecd79cbf2021-11-17 14:11:52457
458 updateIceCandidateGrid(peerConnectionElement, r.statsById);
Henrik Boström33ece3e92019-04-23 10:08:53459}
460
461/**
grunell7566ffc2015-09-07 07:39:44462 * Notification that the audio debug recordings file selection dialog was
463 * cancelled, i.e. recordings have not been enabled.
[email protected]09f12a02014-03-28 16:54:08464 */
grunell7566ffc2015-09-07 07:39:44465function audioDebugRecordingsFileSelectionCancelled() {
Henrik Grunell878f94272017-08-24 13:08:57466 dumpCreator.clearAudioDebugRecordingsCheckbox();
[email protected]09f12a02014-03-28 16:54:08467}
468
469
[email protected]bf3657b2013-12-17 12:36:17470/**
ivocadd54f0d2015-12-18 23:17:05471 * Notification that the event log recordings file selection dialog was
472 * cancelled, i.e. recordings have not been enabled.
473 */
474function eventLogRecordingsFileSelectionCancelled() {
Henrik Grunell878f94272017-08-24 13:08:57475 dumpCreator.clearEventLogRecordingsCheckbox();
ivocadd54f0d2015-12-18 23:17:05476}
Philip Eliasson9b5072d42025-05-13 13:13:49477
478
479function dataChannelRecordingsFileSelectionCancelled() {
480 dumpCreator.clearDataChannelRecordingsCheckbox();
481}