tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RTCDTMFSender-insertDTMF.https.html (6345B)


      1 <!doctype html>
      2 <meta charset=utf-8>
      3 <title>RTCDTMFSender.prototype.insertDTMF</title>
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <script src="RTCPeerConnection-helper.js"></script>
      7 <script src="RTCDTMFSender-helper.js"></script>
      8 <script>
      9  'use strict';
     10 
     11  // Test is based on the following editor draft:
     12  // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
     13 
     14  // The following helper functions are called from RTCPeerConnection-helper.js
     15  //   generateAnswer
     16 
     17  // The following helper functions are called from RTCDTMFSender-helper.js
     18  //   createDtmfSender
     19  //   test_tone_change_events
     20  //   getTransceiver
     21 
     22  /*
     23    7.  Peer-to-peer DTMF
     24      partial interface RTCRtpSender {
     25        readonly attribute RTCDTMFSender? dtmf;
     26      };
     27 
     28      interface RTCDTMFSender : EventTarget {
     29        void insertDTMF(DOMString tones,
     30                        optional unsigned long duration = 100,
     31                        optional unsigned long interToneGap = 70);
     32                 attribute EventHandler ontonechange;
     33        readonly attribute DOMString    toneBuffer;
     34      };
     35   */
     36 
     37  /*
     38    7.2.  insertDTMF
     39      The tones parameter is treated as a series of characters.
     40 
     41      The characters 0 through 9, A through D, #, and * generate the associated
     42      DTMF tones.
     43 
     44      The characters a to d MUST be normalized to uppercase on entry and are
     45      equivalent to A to D.
     46 
     47      As noted in [RTCWEB-AUDIO] Section 3, support for the characters 0 through 9,
     48      A through D, #, and * are required.
     49 
     50      The character ',' MUST be supported, and indicates a delay of 2 seconds
     51      before processing the next character in the tones parameter.
     52 
     53      All other characters (and only those other characters) MUST be considered
     54      unrecognized.
     55   */
     56  promise_test(async t => {
     57    const dtmfSender = await createDtmfSender();
     58    dtmfSender.insertDTMF('');
     59    dtmfSender.insertDTMF('012345689');
     60    dtmfSender.insertDTMF('ABCD');
     61    dtmfSender.insertDTMF('abcd');
     62    dtmfSender.insertDTMF('#*');
     63    dtmfSender.insertDTMF(',');
     64    dtmfSender.insertDTMF('0123456789ABCDabcd#*,');
     65  }, 'insertDTMF() should succeed if tones contains valid DTMF characters');
     66 
     67 
     68  /*
     69    7.2.  insertDTMF
     70      6.  If tones contains any unrecognized characters, throw an
     71          InvalidCharacterError.
     72   */
     73  promise_test(async t => {
     74    const dtmfSender = await createDtmfSender();
     75    assert_throws_dom('InvalidCharacterError', () =>
     76      // 'F' is invalid
     77      dtmfSender.insertDTMF('123FFABC'));
     78 
     79    assert_throws_dom('InvalidCharacterError', () =>
     80      // 'E' is invalid
     81      dtmfSender.insertDTMF('E'));
     82 
     83    assert_throws_dom('InvalidCharacterError', () =>
     84      // ' ' is invalid
     85      dtmfSender.insertDTMF('# *'));
     86  }, 'insertDTMF() should throw InvalidCharacterError if tones contains invalid DTMF characters');
     87 
     88  /*
     89    7.2.  insertDTMF
     90      3.  If transceiver.stopped is true, throw an InvalidStateError.
     91   */
     92  test(t => {
     93    const pc = new RTCPeerConnection();
     94    const transceiver = pc.addTransceiver('audio');
     95    const dtmfSender = transceiver.sender.dtmf;
     96 
     97    transceiver.stop();
     98    assert_throws_dom('InvalidStateError', () => dtmfSender.insertDTMF(''));
     99 
    100  }, 'insertDTMF() should throw InvalidStateError if transceiver is stopped');
    101 
    102  /*
    103    7.2.  insertDTMF
    104      4.  If transceiver.currentDirection is recvonly or inactive, throw an InvalidStateError.
    105   */
    106  promise_test(async t => {
    107    const caller = new RTCPeerConnection();
    108    t.add_cleanup(() => caller.close());
    109    const callee = new RTCPeerConnection();
    110    t.add_cleanup(() => callee.close());
    111    const transceiver =
    112        caller.addTransceiver('audio', { direction: 'recvonly' });
    113    const dtmfSender = transceiver.sender.dtmf;
    114 
    115    const offer = await caller.createOffer();
    116    await caller.setLocalDescription(offer);
    117    await callee.setRemoteDescription(offer);
    118    const stream = await getNoiseStream({audio: true});
    119    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    120    const [track] = stream.getTracks();
    121    callee.addTrack(track, stream);
    122    const answer = await callee.createAnswer();
    123    await callee.setLocalDescription(answer);
    124    await caller.setRemoteDescription(answer);
    125    assert_equals(transceiver.currentDirection, 'recvonly');
    126    assert_throws_dom('InvalidStateError', () => dtmfSender.insertDTMF(''));
    127  }, 'insertDTMF() should throw InvalidStateError if transceiver.currentDirection is recvonly');
    128 
    129  promise_test(async t => {
    130    const pc = new RTCPeerConnection();
    131    t.add_cleanup(() => pc.close());
    132    const transceiver =
    133        pc.addTransceiver('audio', { direction: 'inactive' });
    134    const dtmfSender = transceiver.sender.dtmf;
    135 
    136    const offer = await pc.createOffer();
    137    await pc.setLocalDescription(offer);
    138    const answer = await generateAnswer(offer);
    139    await pc.setRemoteDescription(answer);
    140    assert_equals(transceiver.currentDirection, 'inactive');
    141    assert_throws_dom('InvalidStateError', () => dtmfSender.insertDTMF(''));
    142  }, 'insertDTMF() should throw InvalidStateError if transceiver.currentDirection is inactive');
    143 
    144  /*
    145    7.2.  insertDTMF
    146      The characters a to d MUST be normalized to uppercase on entry and are
    147      equivalent to A to D.
    148 
    149      7.  Set the object's toneBuffer attribute to tones.
    150   */
    151  promise_test(async t => {
    152    const dtmfSender = await createDtmfSender();
    153    dtmfSender.insertDTMF('123');
    154    assert_equals(dtmfSender.toneBuffer, '123');
    155 
    156    dtmfSender.insertDTMF('ABC');
    157    assert_equals(dtmfSender.toneBuffer, 'ABC');
    158 
    159    dtmfSender.insertDTMF('bcd');
    160    assert_equals(dtmfSender.toneBuffer, 'BCD');
    161  }, 'insertDTMF() should set toneBuffer to provided tones normalized, with old tones overridden');
    162 
    163  promise_test(async t => {
    164    const pc = new RTCPeerConnection();
    165    t.add_cleanup(() => pc.close());
    166    const [track, mediaStream] = await getTrackFromUserMedia('audio');
    167    const sender = pc.addTrack(track, mediaStream);
    168    await pc.setLocalDescription(await pc.createOffer());
    169    const dtmfSender = sender.dtmf;
    170    pc.removeTrack(sender);
    171    pc.close();
    172    assert_throws_dom('InvalidStateError', () =>
    173                      dtmfSender.insertDTMF('123'));
    174  }, 'insertDTMF() after remove and close should reject');
    175 
    176 </script>