tor-browser

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

test_peerConnection_replaceTrack.html (7365B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <script type="application/javascript" src="pc.js"></script>
      5 </head>
      6 <body>
      7 <pre id="test">
      8 <script type="application/javascript">
      9  createHTML({
     10    bug: "1032839",
     11    title: "Replace video and audio (with WebAudio) tracks",
     12    visible: true
     13  });
     14 
     15  function allLocalStreamsHaveSender(pc) {
     16    return pc.getLocalStreams()
     17      .every(s => s.getTracks()        // Every local stream,
     18        .some(t => pc.getSenders()     // should have some track,
     19          .some(sn => sn.track == t))) // that's being sent over |pc|.
     20  }
     21 
     22  function allRemoteStreamsHaveReceiver(pc) {
     23    return pc.getRemoteStreams()
     24      .every(s => s.getTracks()        // Every remote stream,
     25        .some(t => pc.getReceivers()   // should have some track,
     26          .some(sn => sn.track == t))) // that's being received over |pc|.
     27  }
     28 
     29  function replacetest(wrapper) {
     30    var pc = wrapper._pc;
     31    var oldSenderCount = pc.getSenders().length;
     32    var sender = pc.getSenders().find(sn => sn.track.kind == "video");
     33    var oldTrack = sender.track;
     34    ok(sender, "We have a sender for video");
     35    ok(allLocalStreamsHaveSender(pc),
     36       "Shouldn't have any local streams without a corresponding sender");
     37    ok(allRemoteStreamsHaveReceiver(pc),
     38       "Shouldn't have any remote streams without a corresponding receiver");
     39 
     40    var newTrack;
     41    var audiotrack;
     42    return getUserMedia({video:true, audio:true})
     43      .then(newStream => {
     44        window.grip = newStream;
     45        newTrack = newStream.getVideoTracks()[0];
     46        audiotrack = newStream.getAudioTracks()[0];
     47        isnot(newTrack, sender.track, "replacing with a different track");
     48        ok(!pc.getLocalStreams().some(s => s == newStream),
     49           "from a different stream");
     50        // Use wrapper function, since it updates expected tracks
     51        return wrapper.senderReplaceTrack(sender, newTrack, newStream);
     52      })
     53      .then(() => {
     54        is(pc.getSenders().length, oldSenderCount, "same sender count");
     55        is(sender.track, newTrack, "sender.track has been replaced");
     56        ok(!pc.getSenders().map(sn => sn.track).some(t => t == oldTrack),
     57           "old track not among senders");
     58        // Spec does not say we add this new track to any stream
     59        ok(!pc.getLocalStreams().some(s => s.getTracks()
     60                                           .some(t => t == sender.track)),
     61           "track does not exist among pc's local streams");
     62        return sender.replaceTrack(audiotrack)
     63          .then(() => ok(false, "replacing with different kind should fail"),
     64                e => is(e.name, "TypeError",
     65                        "replacing with different kind should fail"));
     66      });
     67  }
     68 
     69  runNetworkTest(function () {
     70    test = new PeerConnectionTest();
     71    test.audioCtx = new AudioContext();
     72    test.setMediaConstraints([{video: true, audio: true}], [{video: true}]);
     73    test.chain.removeAfter("PC_REMOTE_WAIT_FOR_MEDIA_FLOW");
     74 
     75    // Test replaceTrack on pcRemote separately since it's video only.
     76    test.chain.append([
     77      function PC_REMOTE_VIDEOONLY_REPLACE_VIDEOTRACK(test) {
     78        return replacetest(test.pcRemote);
     79      },
     80      function PC_LOCAL_NEW_VIDEOTRACK_WAIT_FOR_MEDIA_FLOW(test) {
     81        return test.pcLocal.waitForMediaFlow();
     82      }
     83    ]);
     84 
     85    // Replace video twice on pcLocal to make sure it still works
     86    // (does audio twice too, but hey)
     87    test.chain.append([
     88      function PC_LOCAL_AUDIOVIDEO_REPLACE_VIDEOTRACK_1(test) {
     89        return replacetest(test.pcLocal);
     90      },
     91      function PC_REMOTE_NEW_VIDEOTRACK_WAIT_FOR_MEDIA_FLOW_1(test) {
     92        return test.pcRemote.waitForMediaFlow();
     93      },
     94      function PC_LOCAL_AUDIOVIDEO_REPLACE_VIDEOTRACK_2(test) {
     95        return replacetest(test.pcLocal);
     96      },
     97      function PC_REMOTE_NEW_VIDEOTRACK_WAIT_FOR_MEDIA_FLOW_2(test) {
     98        return test.pcRemote.waitForMediaFlow();
     99      }
    100    ]);
    101 
    102    test.chain.append([
    103      function PC_LOCAL_AUDIOVIDEO_REPLACE_VIDEOTRACK_WITHSAME(test) {
    104        var pc = test.pcLocal._pc;
    105        var sender = pc.getSenders().find(sn => sn.track.kind == "video");
    106        ok(sender, "should still have a sender of video");
    107        return sender.replaceTrack(sender.track)
    108          .then(() => ok(true, "replacing with itself should succeed"));
    109      },
    110      function PC_REMOTE_NEW_SAME_VIDEOTRACK_WAIT_FOR_MEDIA_FLOW(test) {
    111        return test.pcRemote.waitForMediaFlow();
    112      }
    113    ]);
    114 
    115    // Replace the gUM audio track on pcLocal with a WebAudio track.
    116    test.chain.append([
    117      function PC_LOCAL_AUDIOVIDEO_REPLACE_AUDIOTRACK_WEBAUDIO(test) {
    118        var pc = test.pcLocal._pc;
    119        var sender = pc.getSenders().find(sn => sn.track.kind == "audio");
    120        ok(sender, "track has a sender");
    121        var oldSenderCount = pc.getSenders().length;
    122        var oldTrack = sender.track;
    123 
    124        var sourceNode = test.audioCtx.createOscillator();
    125        sourceNode.type = 'sine';
    126        // We need a frequency not too close to the fake audio track (1kHz).
    127        sourceNode.frequency.value = 2000;
    128        sourceNode.start();
    129 
    130        var destNode = test.audioCtx.createMediaStreamDestination();
    131        sourceNode.connect(destNode);
    132        var newTrack = destNode.stream.getAudioTracks()[0];
    133 
    134        return test.pcLocal.senderReplaceTrack(
    135            sender, newTrack, destNode.stream)
    136          .then(() => {
    137            is(pc.getSenders().length, oldSenderCount, "same sender count");
    138            ok(!pc.getSenders().some(sn => sn.track == oldTrack),
    139               "Replaced track should be removed from senders");
    140            // TODO: Should PC remove local streams when there are no senders
    141            // associated with it? getLocalStreams() isn't in the spec anymore,
    142            // so I guess it is pretty arbitrary?
    143            is(sender.track, newTrack, "sender.track has been replaced");
    144            // Spec does not say we add this new track to any stream
    145            ok(!pc.getLocalStreams().some(s => s.getTracks()
    146                                               .some(t => t == sender.track)),
    147               "track exists among pc's local streams");
    148          });
    149      }
    150    ]);
    151    test.chain.append([
    152      function PC_LOCAL_CHECK_WEBAUDIO_FLOW_PRESENT(test) {
    153        return test.pcRemote.checkReceivingToneFrom(test.audioCtx, test.pcLocal);
    154      }
    155    ]);
    156    test.chain.append([
    157      function PC_LOCAL_INVALID_ADD_VIDEOTRACKS(test) {
    158        let videoTransceivers = test.pcLocal._pc.getTransceivers()
    159          .filter(transceiver => {
    160            return !transceiver.stopped &&
    161                   transceiver.receiver.track.kind == "video" &&
    162                   transceiver.sender.track;
    163          });
    164 
    165        ok(videoTransceivers.length,
    166           "There is at least one non-stopped video transceiver with a track.");
    167 
    168        videoTransceivers.forEach(transceiver => {
    169            var stream = test.pcLocal._pc.getLocalStreams()[0];;
    170            var track = transceiver.sender.track;
    171            try {
    172              test.pcLocal._pc.addTrack(track, stream);
    173              ok(false, "addTrack existing track should fail");
    174            } catch (e) {
    175              is(e.name, "InvalidAccessError",
    176                 "addTrack existing track should fail");
    177            }
    178          });
    179      }
    180    ]);
    181    return test.run();
    182  });
    183 </script>
    184 </pre>
    185 </body>
    186 </html>