<!doctype html>
<meta charset=utf-8>
<title>RTCPeerConnection.prototype.removeTrack</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="RTCPeerConnection-helper.js"></script>
<script>
  'use strict';

  // Test is based on the following editor draft:
  // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html

  // The following helper functions are called from RTCPeerConnection-helper.js:
  // generateAnswer

  /*
    5.1.  RTCPeerConnection Interface Extensions
      partial interface RTCPeerConnection {
        ...
        void                removeTrack(RTCRtpSender sender);
        RTCRtpTransceiver   addTransceiver((MediaStreamTrack or DOMString) trackOrKind,
                                                   optional RTCRtpTransceiverInit init);
      };
   */

  // Before calling removeTrack can be tested, one needs to add MediaStreamTracks to
  // a peer connection. There are two ways for adding MediaStreamTrack: addTrack and
  // addTransceiver. addTransceiver is a newer API while addTrack has been implemented
  // in current browsers for some time. As a result some of the removeTrack tests have
  // two versions so that removeTrack can be partially tested without addTransceiver
  // and the transceiver APIs being implemented.

  /*
    5.1.  removeTrack
      3.  If connection's [[isClosed]] slot is true, throw an InvalidStateError.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const transceiver = pc.addTransceiver(track);
    const { sender } = transceiver;

    pc.close();
    assert_throws('InvalidStateError', () => pc.removeTrack(sender));
  }, 'addTransceiver - Calling removeTrack when connection is closed should throw InvalidStateError');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const stream = await getNoiseStream({ audio: true });
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const sender = pc.addTrack(track, stream);

    pc.close();
    assert_throws('InvalidStateError', () => pc.removeTrack(sender));
  }, 'addTrack - Calling removeTrack when connection is closed should throw InvalidStateError');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const transceiver = pc.addTransceiver(track);
    const { sender } = transceiver;

    const pc2 = new RTCPeerConnection();
    pc2.close();
    assert_throws('InvalidStateError', () => pc2.removeTrack(sender));
  }, 'addTransceiver - Calling removeTrack on different connection that is closed should throw InvalidStateError');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const stream = await getNoiseStream({ audio: true });
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const sender = pc.addTrack(track, stream);

    const pc2 = new RTCPeerConnection();
    pc2.close();
    assert_throws('InvalidStateError', () => pc2.removeTrack(sender));
  }, 'addTrack - Calling removeTrack on different connection that is closed should throw InvalidStateError');

  /*
    5.1.  removeTrack
      4.  If sender was not created by connection, throw an InvalidAccessError.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const transceiver = pc.addTransceiver(track);
    const { sender } = transceiver;

    const pc2 = new RTCPeerConnection();
    t.add_cleanup(() => pc2.close());
    assert_throws('InvalidAccessError', () => pc2.removeTrack(sender));
  }, 'addTransceiver - Calling removeTrack on different connection should throw InvalidAccessError');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const stream = await getNoiseStream({ audio: true });
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const sender = pc.addTrack(track, stream);

    const pc2 = new RTCPeerConnection();
    t.add_cleanup(() => pc2.close());
    assert_throws('InvalidAccessError', () => pc2.removeTrack(sender));
  }, 'addTrack - Calling removeTrack on different connection should throw InvalidAccessError')

  /*
    5.1.  removeTrack
      7.  Set sender.track to null.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const transceiver = pc.addTransceiver(track);
    const { sender } = transceiver;

    assert_equals(sender.track, track);
    assert_equals(transceiver.direction, 'sendrecv');
    assert_equals(transceiver.currentDirection, null);

    pc.removeTrack(sender);
    assert_equals(sender.track, null);
    assert_equals(transceiver.direction, 'recvonly');
  }, 'addTransceiver - Calling removeTrack with valid sender should set sender.track to null');

  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const stream = await getNoiseStream({ audio: true });
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const sender = pc.addTrack(track, stream);

    assert_equals(sender.track, track);

    pc.removeTrack(sender);
    assert_equals(sender.track, null);
  }, 'addTrack - Calling removeTrack with valid sender should set sender.track to null');

  /*
    5.1.  removeTrack
      7.  Set sender.track to null.
      10. If transceiver.currentDirection is sendrecv set transceiver.direction
          to recvonly.
   */
  promise_test(async t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const transceiver = caller.addTransceiver(track);
    const { sender } = transceiver;

    assert_equals(sender.track, track);
    assert_equals(transceiver.direction, 'sendrecv');
    assert_equals(transceiver.currentDirection, null);

    const offer = await caller.createOffer();
    await caller.setLocalDescription(offer);
    await callee.setRemoteDescription(offer);
    callee.addTrack(track, stream);
    const answer = await callee.createAnswer();
    await callee.setLocalDescription(answer);
    await caller.setRemoteDescription(answer);
    assert_equals(transceiver.currentDirection, 'sendrecv');

    caller.removeTrack(sender);
    assert_equals(sender.track, null);
    assert_equals(transceiver.direction, 'recvonly');
    assert_equals(transceiver.currentDirection, 'sendrecv',
      'Expect currentDirection to not change');
  }, 'Calling removeTrack with currentDirection sendrecv should set direction to recvonly');

  /*
    5.1.  removeTrack
      7.  Set sender.track to null.
      11. If transceiver.currentDirection is sendonly set transceiver.direction
          to inactive.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const transceiver = pc.addTransceiver(track, { direction: 'sendonly' });
    const { sender } = transceiver;

    assert_equals(sender.track, track);
    assert_equals(transceiver.direction, 'sendonly');
    assert_equals(transceiver.currentDirection, null);

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);
    assert_equals(transceiver.currentDirection, 'sendonly');

    pc.removeTrack(sender);
    assert_equals(sender.track, null);
    assert_equals(transceiver.direction, 'inactive');
    assert_equals(transceiver.currentDirection, 'sendonly',
      'Expect currentDirection to not change');
  }, 'Calling removeTrack with currentDirection sendonly should set direction to inactive');

  /*
    5.1.  removeTrack
      7.  Set sender.track to null.
      9.  If transceiver.currentDirection is recvonly or inactive,
          then abort these steps.
   */
  promise_test(async t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    const callee = new RTCPeerConnection();
    t.add_cleanup(() => callee.close());
    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const transceiver = caller.addTransceiver(track, { direction: 'recvonly' });
    const { sender } = transceiver;

    assert_equals(sender.track, track);
    assert_equals(transceiver.direction, 'recvonly');
    assert_equals(transceiver.currentDirection, null);

    const offer = await caller.createOffer();
    await caller.setLocalDescription(offer);
    await callee.setRemoteDescription(offer);
    callee.addTrack(track, stream);
    const answer = await callee.createAnswer();
    await callee.setLocalDescription(answer);
    await caller.setRemoteDescription(answer);
    assert_equals(transceiver.currentDirection, 'recvonly');

    caller.removeTrack(sender);
    assert_equals(sender.track, null);
    assert_equals(transceiver.direction, 'recvonly');
    assert_equals(transceiver.currentDirection, 'recvonly');
  }, 'Calling removeTrack with currentDirection recvonly should not change direction');

  /*
    5.1.  removeTrack
      7.  Set sender.track to null.
      9.  If transceiver.currentDirection is recvonly or inactive,
          then abort these steps.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const transceiver = pc.addTransceiver(track, { direction: 'inactive' });
    const { sender } = transceiver;

    assert_equals(sender.track, track);
    assert_equals(transceiver.direction, 'inactive');
    assert_equals(transceiver.currentDirection, null);

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);
    assert_equals(transceiver.currentDirection, 'inactive');

    pc.removeTrack(sender);
    assert_equals(sender.track, null);
    assert_equals(transceiver.direction, 'inactive');
    assert_equals(transceiver.currentDirection, 'inactive');
  }, 'Calling removeTrack with currentDirection inactive should not change direction');

  /*
    TODO
      5.1.  removeTrack
        Stops sending media from sender. The RTCRtpSender will still appear
        in getSenders. Doing so will cause future calls to createOffer to
        mark the media description for the corresponding transceiver as
        recvonly or inactive, as defined in [JSEP] (section 5.2.2.).

        When the other peer stops sending a track in this manner, an ended
        event is fired at the MediaStreamTrack object.

        6.  If sender is not in senders (which indicates that it was removed
            due to setting an RTCSessionDescription of type "rollback"),
            then abort these steps.
        12. Update the negotiation-needed flag for connection.
   */
</script>
