508 lines
		
	
	
	
		
			17 KiB
			
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			508 lines
		
	
	
	
		
			17 KiB
			
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
// Derived from Chromium WebRTC Internals Dashboard - see Acknowledgements for full license details
 | 
						|
 | 
						|
import {$} from './util.js';
 | 
						|
 | 
						|
import {createIceCandidateGrid, updateIceCandidateGrid} from './candidate_grid.js';
 | 
						|
import {MAX_STATS_DATA_POINT_BUFFER_SIZE} from './data_series.js';
 | 
						|
import {DumpCreator, peerConnectionDataStore, userMediaRequests} from './dump_creator.js';
 | 
						|
import {PeerConnectionUpdateTable} from './peer_connection_update_table.js';
 | 
						|
import {drawSingleReport, removeStatsReportGraphs} from './stats_graph_helper.js';
 | 
						|
import {StatsRatesCalculator, StatsReport} from './stats_rates_calculator.js';
 | 
						|
import {StatsTable} from './stats_table.js';
 | 
						|
import {TabView} from './tab_view.js';
 | 
						|
import {UserMediaTable} from './user_media_table.js';
 | 
						|
import { i18n } from '../../ts/windows/sandboxedInit.js';
 | 
						|
 | 
						|
let tabView = null;
 | 
						|
let peerConnectionUpdateTable = null;
 | 
						|
let statsTable = null;
 | 
						|
let userMediaTable = null;
 | 
						|
let dumpCreator = null;
 | 
						|
let requestedStatsInterval = 2000;
 | 
						|
 | 
						|
// Start Signal Change
 | 
						|
let stats_queue = [];
 | 
						|
 | 
						|
function onRtcStatsReport(event, report) {
 | 
						|
  const rs = JSON.parse(report.reportJson);
 | 
						|
  const mungedReports = rs.map(r => ({
 | 
						|
    id: r.id,
 | 
						|
    type: r.type,
 | 
						|
    stats: {
 | 
						|
      timestamp: r.timestamp / 1000,
 | 
						|
      values: Object
 | 
						|
        .keys(r)
 | 
						|
        .filter(k => !['id', 'type', 'timestamp'].includes(k))
 | 
						|
        .reduce((acc, k) => { 
 | 
						|
          acc.push(k, r[k]); 
 | 
						|
          return acc; 
 | 
						|
        }, []),
 | 
						|
    },
 | 
						|
  }));
 | 
						|
 | 
						|
  // fake since we can only have 1 call going at a time
 | 
						|
  // pid should be related to call ID
 | 
						|
  // lid is only one peer connection  per call currently
 | 
						|
  stats_queue.push(
 | 
						|
    {
 | 
						|
      pid: 100,
 | 
						|
      rid: report.conversationId,
 | 
						|
      lid: report.callId,
 | 
						|
      reports: mungedReports,
 | 
						|
    }
 | 
						|
  )
 | 
						|
}
 | 
						|
window.Signal.CallingToolsProps.onRtcStatsReport(onRtcStatsReport);
 | 
						|
// End Signal Change
 | 
						|
 | 
						|
const searchParameters = new URLSearchParams(window.location.search);
 | 
						|
 | 
						|
/** Maps from id (see getPeerConnectionId) to StatsRatesCalculator. */
 | 
						|
const statsRatesCalculatorById = new Map();
 | 
						|
 | 
						|
/** A simple class to store the updates and stats data for a peer connection. */
 | 
						|
  /** @constructor */
 | 
						|
class PeerConnectionRecord {
 | 
						|
  constructor() {
 | 
						|
    /** @private */
 | 
						|
    this.record_ = {
 | 
						|
      pid: -1,
 | 
						|
      constraints: {},
 | 
						|
      rtcConfiguration: [],
 | 
						|
      stats: {},
 | 
						|
      updateLog: [],
 | 
						|
      url: '',
 | 
						|
    };
 | 
						|
  }
 | 
						|
 | 
						|
  /** @override */
 | 
						|
  toJSON() {
 | 
						|
    return this.record_;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Adds the initialization info of the peer connection.
 | 
						|
   * @param {number} pid The pid of the process hosting the peer connection.
 | 
						|
   * @param {string} url The URL of the web page owning the peer connection.
 | 
						|
   * @param {Array} rtcConfiguration
 | 
						|
   * @param {!Object} constraints Media constraints.
 | 
						|
   */
 | 
						|
  initialize(pid, url, rtcConfiguration, constraints) {
 | 
						|
    this.record_.pid = pid;
 | 
						|
    this.record_.url = url;
 | 
						|
    this.record_.rtcConfiguration = rtcConfiguration;
 | 
						|
    this.record_.constraints = constraints;
 | 
						|
  }
 | 
						|
 | 
						|
  resetStats() {
 | 
						|
    this.record_.stats = {};
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * @param {string} dataSeriesId The TimelineDataSeries identifier.
 | 
						|
   * @return {!TimelineDataSeries}
 | 
						|
   */
 | 
						|
  getDataSeries(dataSeriesId) {
 | 
						|
    return this.record_.stats[dataSeriesId];
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * @param {string} dataSeriesId The TimelineDataSeries identifier.
 | 
						|
   * @param {!TimelineDataSeries} dataSeries The TimelineDataSeries to set to.
 | 
						|
   */
 | 
						|
  setDataSeries(dataSeriesId, dataSeries) {
 | 
						|
    this.record_.stats[dataSeriesId] = dataSeries;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * @param {!Object} update The object contains keys "time", "type", and
 | 
						|
   *   "value".
 | 
						|
   */
 | 
						|
  addUpdate(update) {
 | 
						|
    const time = new Date(parseFloat(update.time));
 | 
						|
    this.record_.updateLog.push({
 | 
						|
      time: time.toLocaleString(),
 | 
						|
      type: update.type,
 | 
						|
      value: update.value,
 | 
						|
    });
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function addMedia(data) {
 | 
						|
  userMediaRequests.push(data);
 | 
						|
  userMediaTable.addMedia(data)
 | 
						|
}
 | 
						|
 | 
						|
function updateMedia(data) {
 | 
						|
    userMediaRequests.push(data);
 | 
						|
    userMediaTable.updateMedia(data);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
function removeMediaForRenderer(data) {
 | 
						|
  for (let i = userMediaRequests.length - 1; i >= 0; --i) {
 | 
						|
    if (userMediaRequests[i].rid === data.rid) {
 | 
						|
      userMediaRequests.splice(i, 1);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  userMediaTable.removeMediaForRenderer(data);
 | 
						|
}
 | 
						|
 | 
						|
function setRtcStatsInterval() {
 | 
						|
  window.Signal.CallingToolsProps.setRtcStatsInterval(requestedStatsInterval);
 | 
						|
}
 | 
						|
 | 
						|
function initialize() {
 | 
						|
  let placeholderTitle = i18n('icu:callingDeveloperTools');
 | 
						|
  let placeholderDescription = i18n('icu:callingDeveloperToolsDescription');
 | 
						|
  $('placeholder-title').innerText = placeholderTitle;
 | 
						|
  $('placeholder-description').innerText = placeholderDescription;
 | 
						|
 | 
						|
  dumpCreator = new DumpCreator($('content-root'));
 | 
						|
 | 
						|
  tabView = new TabView($('content-root'));
 | 
						|
  peerConnectionUpdateTable = new PeerConnectionUpdateTable();
 | 
						|
  statsTable = new StatsTable();
 | 
						|
  userMediaTable = new UserMediaTable(tabView, userMediaRequests);
 | 
						|
 | 
						|
  let processStatsInterval = 1000;
 | 
						|
  window.setInterval(processStats, processStatsInterval);
 | 
						|
  setRtcStatsInterval(2000);
 | 
						|
}
 | 
						|
document.addEventListener('DOMContentLoaded', initialize);
 | 
						|
 | 
						|
/**
 | 
						|
 * Sends a request to the browser to get peer connection statistics from the
 | 
						|
 * standard getStats() API (promise-based).
 | 
						|
 */
 | 
						|
function processStats() {
 | 
						|
  // Start Signal Change
 | 
						|
  for(let i = 0; i < 10 && stats_queue.length > 0; i++) {
 | 
						|
    addStandardStats(stats_queue.shift());
 | 
						|
  }
 | 
						|
  // End Signal Change
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * A helper function for getting a peer connection element id.
 | 
						|
 *
 | 
						|
 * @param {!Object<number>} data The object containing the rid and lid of the
 | 
						|
 *     peer connection.
 | 
						|
 * @return {string} The peer connection element id.
 | 
						|
 */
 | 
						|
function getPeerConnectionId(data) {
 | 
						|
  return data.rid + '-' + data.lid;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * A helper function for appending a child element to |parent|.
 | 
						|
 *
 | 
						|
 * @param {!Element} parent The parent element.
 | 
						|
 * @param {string} tag The child element tag.
 | 
						|
 * @param {string} text The textContent of the new DIV.
 | 
						|
 * @return {!Element} the new DIV element.
 | 
						|
 */
 | 
						|
function appendChildWithText(parent, tag, text) {
 | 
						|
  const child = document.createElement(tag);
 | 
						|
  child.textContent = text;
 | 
						|
  parent.appendChild(child);
 | 
						|
  return child;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Helper for adding a peer connection update.
 | 
						|
 *
 | 
						|
 * @param {Element} peerConnectionElement
 | 
						|
 * @param {!PeerConnectionUpdateEntry} update The peer connection update data.
 | 
						|
 */
 | 
						|
function addPeerConnectionUpdate(peerConnectionElement, update) {
 | 
						|
 | 
						|
  peerConnectionUpdateTable.addPeerConnectionUpdate(
 | 
						|
      peerConnectionElement, update);
 | 
						|
  peerConnectionDataStore[peerConnectionElement.id].addUpdate(update);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/** Browser message handlers. */
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Removes all information about a peer connection.
 | 
						|
 * Use ?keepRemovedConnections url parameter to prevent the removal.
 | 
						|
 *
 | 
						|
 * @param {!Object<number>} data The object containing the rid and lid of a peer
 | 
						|
 *     connection.
 | 
						|
 */
 | 
						|
function removePeerConnection(data) {
 | 
						|
  // Disable getElementById restriction here, since |getPeerConnectionId| does
 | 
						|
  // not return valid selectors.
 | 
						|
  // eslint-disable-next-line no-restricted-properties
 | 
						|
 | 
						|
  const element = document.getElementById(getPeerConnectionId(data));
 | 
						|
  if (element && !searchParameters.has('keepRemovedConnections')) {
 | 
						|
    delete peerConnectionDataStore[element.id];
 | 
						|
    tabView.removeTab(element.id);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Adds a peer connection.
 | 
						|
 *
 | 
						|
 * @param {!Object} data The object containing the rid, lid, pid, url,
 | 
						|
 *     rtcConfiguration, and constraints of a peer connection.
 | 
						|
 */
 | 
						|
function addPeerConnection(data) {
 | 
						|
  const id = getPeerConnectionId(data);
 | 
						|
 | 
						|
  if (!peerConnectionDataStore[id]) {
 | 
						|
    peerConnectionDataStore[id] = new PeerConnectionRecord();
 | 
						|
  }
 | 
						|
  peerConnectionDataStore[id].initialize(
 | 
						|
      data.pid, data.url, data.rtcConfiguration, data.constraints);
 | 
						|
 | 
						|
  // Disable getElementById restriction here, since |id| is not always
 | 
						|
  // a valid selector.
 | 
						|
  // eslint-disable-next-line no-restricted-properties
 | 
						|
  let peerConnectionElement = document.getElementById(id);
 | 
						|
  if (!peerConnectionElement) {
 | 
						|
    const details = `[ rid: ${data.rid}, lid: ${data.lid}, pid: ${data.pid} ]`;
 | 
						|
    peerConnectionElement = tabView.addTab(id, data.url + " " + details);
 | 
						|
  }
 | 
						|
 | 
						|
  const p = document.createElement('p');
 | 
						|
  appendChildWithText(p, 'span', data.url);
 | 
						|
  appendChildWithText(p, 'span', ', ');
 | 
						|
  appendChildWithText(p, 'span', data.rtcConfiguration);
 | 
						|
  if (data.constraints !== '') {
 | 
						|
    appendChildWithText(p, 'span', ', ');
 | 
						|
    appendChildWithText(p, 'span', data.constraints);
 | 
						|
  }
 | 
						|
  peerConnectionElement.appendChild(p);
 | 
						|
 | 
						|
  // Show deprecation notices as a list.
 | 
						|
  // Note: data.rtcConfiguration is not in JSON format and may
 | 
						|
  // not be defined in tests.
 | 
						|
  const deprecationNotices = document.createElement('ul');
 | 
						|
  if (data.rtcConfiguration) {
 | 
						|
    deprecationNotices.className = 'peerconnection-deprecations';
 | 
						|
  }
 | 
						|
  peerConnectionElement.appendChild(deprecationNotices);
 | 
						|
 | 
						|
  const iceConnectionStates = document.createElement('div');
 | 
						|
  iceConnectionStates.textContent = 'ICE connection state: new';
 | 
						|
  iceConnectionStates.className = 'iceconnectionstate';
 | 
						|
  peerConnectionElement.appendChild(iceConnectionStates);
 | 
						|
 | 
						|
  const connectionStates = document.createElement('div');
 | 
						|
  connectionStates.textContent = 'Connection state: new';
 | 
						|
  connectionStates.className = 'connectionstate';
 | 
						|
  peerConnectionElement.appendChild(connectionStates);
 | 
						|
 | 
						|
  const signalingStates = document.createElement('div');
 | 
						|
  signalingStates.textContent = 'Signaling state: new';
 | 
						|
  signalingStates.className = 'signalingstate';
 | 
						|
  peerConnectionElement.appendChild(signalingStates);
 | 
						|
 | 
						|
  const candidatePair = document.createElement('div');
 | 
						|
  candidatePair.textContent = 'ICE Candidate pair: ';
 | 
						|
  candidatePair.className = 'candidatepair';
 | 
						|
  candidatePair.appendChild(document.createElement('span'));
 | 
						|
  peerConnectionElement.appendChild(candidatePair);
 | 
						|
 | 
						|
  createIceCandidateGrid(peerConnectionElement);
 | 
						|
  return peerConnectionElement;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Adds a peer connection update.
 | 
						|
 *
 | 
						|
 * @param {!PeerConnectionUpdateEntry} data The peer connection update data.
 | 
						|
 */
 | 
						|
function updatePeerConnection(data) {
 | 
						|
  // Disable getElementById restriction here, since |getPeerConnectionId| does
 | 
						|
  // not return valid selectors.
 | 
						|
  const peerConnectionElement =
 | 
						|
  // eslint-disable-next-line no-restricted-properties
 | 
						|
      document.getElementById(getPeerConnectionId(data));
 | 
						|
  addPeerConnectionUpdate(peerConnectionElement, data);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * 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 rid, lid, pid, url,
 | 
						|
 *     rtcConfiguration, constraints, and an array of updates as the log.
 | 
						|
 */
 | 
						|
function updateAllPeerConnections(data) {
 | 
						|
  for (let i = 0; i < data.length; ++i) {
 | 
						|
    const peerConnection = addPeerConnection(data[i]);
 | 
						|
 | 
						|
    const log = data[i].log;
 | 
						|
    if (!log) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    for (let j = 0; j < log.length; ++j) {
 | 
						|
      addPeerConnectionUpdate(peerConnection, log[j]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  processStats();
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Handles the report of stats originating from the standard getStats() API.
 | 
						|
 *
 | 
						|
 * @param {!Object} data The object containing rid, 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 addStandardStats(data) {
 | 
						|
  // Disable getElementById restriction here, since |getPeerConnectionId| does
 | 
						|
  // not return valid selectors.
 | 
						|
  // eslint-disable-next-line no-restricted-properties
 | 
						|
  let peerConnectionElement =
 | 
						|
      // eslint-disable-next-line no-restricted-properties
 | 
						|
      document.getElementById(getPeerConnectionId(data));
 | 
						|
  if (!peerConnectionElement) {
 | 
						|
    // fake the add peer event
 | 
						|
    peerConnectionElement = addPeerConnection({
 | 
						|
      connected: false,
 | 
						|
      isOpen: true,
 | 
						|
      lid: data.lid,
 | 
						|
      rid: data.rid,
 | 
						|
      rtcConfiguration: "{ iceServers: [], iceTransportPolicy: all, bundlePolicy: balanced, rtcpMuxPolicy: require, iceCandidatePoolSize: 0 }",
 | 
						|
      url: "groupcall"
 | 
						|
    });
 | 
						|
    // eslint-disable-next-line no-restricted-properties
 | 
						|
    if(!peerConnectionElement) {
 | 
						|
      console.error("Failed to create peerConnection Element");
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  const pcId = getPeerConnectionId(data);
 | 
						|
  let statsRatesCalculator = statsRatesCalculatorById.get(pcId);
 | 
						|
  if (!statsRatesCalculator) {
 | 
						|
    statsRatesCalculator = new StatsRatesCalculator();
 | 
						|
    statsRatesCalculatorById.set(pcId, statsRatesCalculator);
 | 
						|
  }
 | 
						|
  // This just changes the reports from their array format into an object format, then adds it to statsByAdd
 | 
						|
  const r = StatsReport.fromInternalsReportList(data.reports);
 | 
						|
  statsRatesCalculator.addStatsReport(r);
 | 
						|
  data.reports = statsRatesCalculator.currentReport.toInternalsReportList();
 | 
						|
  for (let i = 0; i < data.reports.length; ++i) {
 | 
						|
    const report = data.reports[i];
 | 
						|
    statsTable.addStatsReport(peerConnectionElement, report);
 | 
						|
    drawSingleReport(peerConnectionElement, report);
 | 
						|
  }
 | 
						|
  // Determine currently connected candidate pair.
 | 
						|
  const stats = r.statsById;
 | 
						|
 | 
						|
  let activeCandidatePair = null;
 | 
						|
  let remoteCandidate = null;
 | 
						|
  let localCandidate = null;
 | 
						|
 | 
						|
  // Get the first active candidate pair. This ignores the rare case of
 | 
						|
  // non-bundled connections.
 | 
						|
  stats.forEach(report => {
 | 
						|
    if (report.type === 'transport' && !activeCandidatePair) {
 | 
						|
      activeCandidatePair = stats.get(report.selectedCandidatePairId);
 | 
						|
    }
 | 
						|
  });
 | 
						|
 | 
						|
  const candidateElement = peerConnectionElement
 | 
						|
    .getElementsByClassName('candidatepair')[0].firstElementChild;
 | 
						|
  if (activeCandidatePair) {
 | 
						|
    if (activeCandidatePair.remoteCandidateId) {
 | 
						|
      remoteCandidate = stats.get(activeCandidatePair.remoteCandidateId);
 | 
						|
    }
 | 
						|
    if (activeCandidatePair.localCandidateId) {
 | 
						|
      localCandidate = stats.get(activeCandidatePair.localCandidateId);
 | 
						|
    }
 | 
						|
    candidateElement.innerText = '';
 | 
						|
    if (localCandidate && remoteCandidate) {
 | 
						|
      if (localCandidate.address &&
 | 
						|
          localCandidate.address.indexOf(':') !== -1) {
 | 
						|
        // Show IPv6 in []
 | 
						|
        candidateElement.innerText +='[' + localCandidate.address + ']';
 | 
						|
      } else {
 | 
						|
        candidateElement.innerText += localCandidate.address || '(not set)';
 | 
						|
      }
 | 
						|
      candidateElement.innerText += ':' + localCandidate.port + ' <=> ';
 | 
						|
 | 
						|
      if (remoteCandidate.address &&
 | 
						|
          remoteCandidate.address.indexOf(':') !== -1) {
 | 
						|
        // Show IPv6 in []
 | 
						|
        candidateElement.innerText +='[' + remoteCandidate.address + ']';
 | 
						|
      } else {
 | 
						|
        candidateElement.innerText += remoteCandidate.address || '(not set)';
 | 
						|
      }
 | 
						|
      candidateElement.innerText += ':' + remoteCandidate.port;
 | 
						|
    }
 | 
						|
    // Mark active local-candidate, remote candidate and candidate pair
 | 
						|
    // bold in the table.
 | 
						|
    // Disable getElementById restriction here, since |peerConnectionElement|
 | 
						|
    // doesn't always have a valid selector ID.
 | 
						|
    const statsContainer =
 | 
						|
      // eslint-disable-next-line no-restricted-properties
 | 
						|
        document.getElementById(peerConnectionElement.id + '-table-container');
 | 
						|
    const activeConnectionClass = 'stats-table-active-connection';
 | 
						|
    statsContainer.childNodes.forEach(node => {
 | 
						|
      if (node.nodeName !== 'DETAILS' || !node.children[1]) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      const ids = [
 | 
						|
        peerConnectionElement.id + '-table-' + activeCandidatePair.id,
 | 
						|
        peerConnectionElement.id + '-table-' + localCandidate.id,
 | 
						|
        peerConnectionElement.id + '-table-' + remoteCandidate.id,
 | 
						|
      ];
 | 
						|
      if (ids.includes(node.children[1].id)) {
 | 
						|
        node.firstElementChild.classList.add(activeConnectionClass);
 | 
						|
      } else {
 | 
						|
        node.firstElementChild.classList.remove(activeConnectionClass);
 | 
						|
      }
 | 
						|
    });
 | 
						|
    // Mark active candidate-pair graph bold.
 | 
						|
    const statsGraphContainers = peerConnectionElement
 | 
						|
      .getElementsByClassName('stats-graph-container');
 | 
						|
    for (let i = 0; i < statsGraphContainers.length; i++) {
 | 
						|
      const node = statsGraphContainers[i];
 | 
						|
      if (node.nodeName !== 'DETAILS') {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      if (!node.id.startsWith(pcId + '-candidate-pair')) {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      if (node.id === pcId + '-candidate-pair-' + activeCandidatePair.id
 | 
						|
          + '-graph-container') {
 | 
						|
        node.firstElementChild.classList.add(activeConnectionClass);
 | 
						|
      } else {
 | 
						|
        node.firstElementChild.classList.remove(activeConnectionClass);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    candidateElement.innerText = '(not connected)';
 | 
						|
  }
 | 
						|
 | 
						|
  updateIceCandidateGrid(peerConnectionElement, r.statsById);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Notification that the audio debug recordings file selection dialog was
 | 
						|
 * cancelled, i.e. recordings have not been enabled.
 | 
						|
 */
 | 
						|
function audioDebugRecordingsFileSelectionCancelled() {
 | 
						|
  dumpCreator.clearAudioDebugRecordingsCheckbox();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Notification that the event log recordings file selection dialog was
 | 
						|
 * cancelled, i.e. recordings have not been enabled.
 | 
						|
 */
 | 
						|
function eventLogRecordingsFileSelectionCancelled() {
 | 
						|
  dumpCreator.clearEventLogRecordingsCheckbox();
 | 
						|
}
 |