<!doctype html>
<meta charset=utf-8>
<title>RTCPeerConnection.prototype.addTrack</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src='../mediacapture-streams/permission-helper.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:
  //   getNoiseStream()

  /*
    5.1.  RTCPeerConnection Interface Extensions
      partial interface RTCPeerConnection {
        ...
        sequence<RTCRtpSender>      getSenders();
        sequence<RTCRtpReceiver>    getReceivers();
        sequence<RTCRtpTransceiver> getTransceivers();
        RTCRtpSender                addTrack(MediaStreamTrack track,
                                             MediaStream... streams);
        RTCRtpTransceiver           addTransceiver((MediaStreamTrack or DOMString) trackOrKind,
                                                   optional RTCRtpTransceiverInit init);
      };

      Note
        While addTrack checks if the MediaStreamTrack given as an argument is
        already being sent to avoid sending the same MediaStreamTrack twice,
        the other ways do not, allowing the same MediaStreamTrack to be sent
        several times simultaneously.
   */

  /*
    5.1.  addTrack
      4.  If connection's [[isClosed]] slot is true, throw an 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();

    pc.close();
    assert_throws_dom('InvalidStateError', () => pc.addTrack(track, stream))
  }, 'addTrack when pc is closed should throw InvalidStateError');

  /*
    5.1.  addTrack
      8.  If sender is null, run the following steps:
          1.  Create an RTCRtpSender with track and streams and let sender be
              the result.
          2.  Create an RTCRtpReceiver with track.kind as kind and let receiver
              be the result.
          3.  Create an RTCRtpTransceiver with sender and receiver and let
              transceiver be the result.
          4.  Add transceiver to connection's set of transceivers.
   */
  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);

    assert_true(sender instanceof RTCRtpSender,
      'Expect sender to be instance of RTCRtpSender');

    assert_equals(sender.track, track,
      `Expect sender's track to be the added track`);

    const transceivers = pc.getTransceivers();
    assert_equals(transceivers.length, 1,
      'Expect only one transceiver with sender added');

    const [transceiver] = transceivers;
    assert_equals(transceiver.sender, sender);

    assert_array_equals([sender], pc.getSenders(),
      'Expect only one sender with given track added');

    const { receiver } = transceiver;
    assert_equals(receiver.track.kind, 'audio');
    assert_array_equals([transceiver.receiver], pc.getReceivers(),
      'Expect only one receiver associated with transceiver added');
  }, 'addTrack with single track argument and no stream should succeed');

  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_true(sender instanceof RTCRtpSender,
      'Expect sender to be instance of RTCRtpSender');

    assert_equals(sender.track, track,
      `Expect sender's track to be the added track`);
  }, 'addTrack with single track argument and single stream should succeed');

  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 stream2 = new MediaStream([track]);
    const sender = pc.addTrack(track, stream, stream2);

    assert_true(sender instanceof RTCRtpSender,
      'Expect sender to be instance of RTCRtpSender');

    assert_equals(sender.track, track,
      `Expect sender's track to be the added track`);
  }, 'addTrack with single track argument and multiple streams should succeed');

  /*
    5.1.  addTrack
      5.  Let senders be the result of executing the CollectSenders algorithm.
          If an RTCRtpSender for track already exists in senders, throw an
          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();

    pc.addTrack(track, stream);
    assert_throws_dom('InvalidAccessError', () => pc.addTrack(track, stream));
  }, 'Adding the same track multiple times should throw InvalidAccessError');

  /*
    5.1.  addTrack
      6.  The steps below describe how to determine if an existing sender can
          be reused.

          If any RTCRtpSender object in senders matches all the following
          criteria, let sender be that object, or null otherwise:
            - The sender's track is null.
            - The transceiver kind of the RTCRtpTransceiver, associated with
              the sender, matches track's kind.
            - The sender has never been used to send. More precisely, the
              RTCRtpTransceiver associated with the sender has never had a
              currentDirection of sendrecv or sendonly.
      7.  If sender is not null, run the following steps to use that sender:
          1.  Set sender.track to track.
          3.  Enable sending direction on the RTCRtpTransceiver associated
              with sender.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const transceiver = pc.addTransceiver('audio', { direction: 'recvonly' });
    assert_equals(transceiver.sender.track, null);
    assert_equals(transceiver.direction, 'recvonly');

    await setMediaPermission("granted", ["microphone"]);
    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const sender = pc.addTrack(track);

    assert_equals(sender, transceiver.sender);
    assert_equals(sender.track, track);
    assert_equals(transceiver.direction, 'sendrecv');
    assert_array_equals([sender], pc.getSenders());
  }, 'addTrack with existing sender with null track, same kind, and recvonly direction should reuse sender');

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

    const transceiver = pc.addTransceiver('audio');
    assert_equals(transceiver.sender.track, null);
    assert_equals(transceiver.direction, 'sendrecv');

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

    assert_equals(sender.track, track);
    assert_equals(sender, transceiver.sender);
  }, 'addTrack with existing sender that has not been used to send should reuse the sender');

  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 getNoiseStream({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const transceiver = caller.addTransceiver(track);
    {
      const offer = await caller.createOffer();
      await caller.setLocalDescription(offer);
      await callee.setRemoteDescription(offer);
      const answer = await callee.createAnswer();
      await callee.setLocalDescription(answer);
      await caller.setRemoteDescription(answer);
    }
    assert_equals(transceiver.currentDirection, 'sendonly');

    caller.removeTrack(transceiver.sender);
    {
      const offer = await caller.createOffer();
      await caller.setLocalDescription(offer);
      await callee.setRemoteDescription(offer);
      const answer = await callee.createAnswer();
      await callee.setLocalDescription(answer);
      await caller.setRemoteDescription(answer);
    }
    assert_equals(transceiver.direction, 'recvonly');
    assert_equals(transceiver.currentDirection, 'inactive');

    // |transceiver.sender| is currently not used for sending, but it should not
    // be reused because it has been used for sending before.
    const sender = caller.addTrack(track);
    assert_true(sender != null);
    assert_not_equals(sender, transceiver.sender);
  }, 'addTrack with existing sender that has been used to send should create new sender');

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

    const transceiver = pc.addTransceiver('video', { direction: 'recvonly' });
    assert_equals(transceiver.sender.track, null);
    assert_equals(transceiver.direction, 'recvonly');

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

    assert_equals(sender.track, track);
    assert_not_equals(sender, transceiver.sender);

    const senders = pc.getSenders();
    assert_equals(senders.length, 2,
      'Expect 2 senders added to connection');

    assert_true(senders.includes(sender),
      'Expect senders list to include sender');

    assert_true(senders.includes(transceiver.sender),
      `Expect senders list to include first transceiver's sender`);
  }, 'addTrack with existing sender with null track, different kind, and recvonly direction should create new sender');

  /*
    TODO
      5.1.  addTrack
        3.  Let streams be a list of MediaStream objects constructed from the
            method's remaining arguments, or an empty list if the method was
            called with a single argument.
        6.  The steps below describe how to determine if an existing sender can
            be reused. Doing so will cause future calls to createOffer and
            createAnswer to mark the corresponding media description as sendrecv
            or sendonly and add the MSID of the track added, as defined in [JSEP]
            (section 5.2.2. and section 5.3.2.).

    Non-Testable
      5.1.  addTrack
        7.  If sender is not null, run the following steps to use that sender:
          2.  Set sender's [[associated MediaStreams]] to streams.

    Tested in RTCPeerConnection-onnegotiationneeded.html:
      5.1. addTrack
        10. Update the negotiation-needed flag for connection.

  */

  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 getNoiseStream({audio: true});
    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
    const [track] = stream.getTracks();
    const transceiver = caller.addTransceiver(track);
    // Note that this test doesn't process canididates.
    {
      const offer = await caller.createOffer();
      await caller.setLocalDescription(offer);
      await callee.setRemoteDescription(offer);
      const answer = await callee.createAnswer();
      await callee.setLocalDescription(answer);
      await caller.setRemoteDescription(answer);
    }
    assert_equals(transceiver.currentDirection, 'sendonly');
    await waitForIceGatheringState(caller, ['complete']);
    await waitForIceGatheringState(callee, ['complete']);

    const second_stream = await getNoiseStream({audio: true});
    t.add_cleanup(() => second_stream.getTracks().forEach(track => track.stop()));
    // There may be callee candidates in flight. It seems that waiting
    // for a createOffer() is enough time to let them complete processing.
    // TODO(https://crbug.com/webrtc/13095): Fix bug and remove.
    await caller.createOffer();

    const [second_track] = second_stream.getTracks();
    caller.onicecandidate = t.unreached_func(
      'No caller candidates should be generated.');
    callee.onicecandidate = t.unreached_func(
      'No callee candidates should be generated.');
    caller.addTrack(second_track);
    {
      const offer = await caller.createOffer();
      await caller.setLocalDescription(offer);
      await callee.setRemoteDescription(offer);
      const answer = await callee.createAnswer();
      await callee.setLocalDescription(answer);
      await caller.setRemoteDescription(answer);
    }
    // Check that we're bundled.
    const [first_transceiver, second_transceiver] = caller.getTransceivers();
    assert_equals(first_transceiver.transport, second_transceiver.transport);

  }, 'Adding more tracks does not generate more candidates if bundled');

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

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

    pc1.addTrack(track);
    const offer = await pc1.createOffer();
    // We do not await here; we want to ensure that the transceiver this creates
    // is untouched by addTrack, and that addTrack creates _another_ transceiver
    const srdPromise = pc2.setRemoteDescription(offer);

    const sender = pc2.addTrack(track);

    await srdPromise;

    assert_equals(pc2.getTransceivers().length, 1, "Should have 1 transceiver");
    assert_equals(pc2.getTransceivers()[0].sender, sender, "The transceiver should be the one added by addTrack");
  }, 'Calling addTrack while sRD(offer) is pending should allow the new remote transceiver to be the same one that addTrack creates');

  promise_test(async t => {
    const pc1 = new RTCPeerConnection();
    t.add_cleanup(() => pc1.close());
    const pc2 = new RTCPeerConnection();
    t.add_cleanup(() => pc2.close());
    pc1.addTransceiver('video');

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

    const offer = await pc1.createOffer();
    const srdPromise = pc2.setRemoteDescription(offer);
    assert_equals(pc2.getTransceivers().length, 0);
    pc2.addTrack(track);
    assert_equals(pc2.getTransceivers().length, 1);
    const transceiver0 = pc2.getTransceivers()[0];
    assert_equals(transceiver0.mid, null);
    await srdPromise;
    assert_equals(pc2.getTransceivers().length, 2);
    const transceiver1 = pc2.getTransceivers()[1];
    assert_equals(transceiver0.mid, null);
    assert_not_equals(transceiver1.mid, null);
  }, 'When addTrack is called while sRD is in progress, and both addTrack and sRD add a transceiver of different media types, the addTrack transceiver should come first, and then the sRD transceiver.');

</script>
