<!doctype html>
<meta charset="utf-8">
<title>Test RTCPeerConnection.prototype.onnegotiationneeded</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:
  //   generateOffer
  //   generateAnswer
  //   generateAudioReceiveOnlyOffer
  //   test_never_resolve

  // Listen to the negotiationneeded event on a peer connection
  // Returns a promise that resolves when the first event is fired.
  // The resolve result is a dictionary with event and nextPromise,
  // which resolves when the next negotiationneeded event is fired.
  // This allow us to promisify the event listening and assert whether
  // an event is fired or not by testing whether a promise is resolved.
  function awaitNegotiation(pc) {
    if(pc.onnegotiationneeded) {
      throw new Error('connection is already attached with onnegotiationneeded event handler');
    }

    function waitNextNegotiation() {
      return new Promise(resolve => {
        pc.onnegotiationneeded = event => {
          const nextPromise = waitNextNegotiation();
          resolve({ nextPromise, event });
        }
      });
    }

    return waitNextNegotiation();
  }

  // Return a promise that rejects if the first promise is resolved before second promise.
  // Also rejects when either promise rejects.
  function assert_first_promise_fulfill_after_second(promise1, promise2, message) {
    if(!message) {
      message = 'first promise is resolved before second promise';
    }

    return new Promise((resolve, reject) => {
      let secondResolved = false;

      promise1.then(() => {
        if(secondResolved) {
          resolve();
        } else {
          assert_unreached(message);
        }
      })
      .catch(reject);

      promise2.then(() => {
        secondResolved = true;
      }, reject);
    });
  }

  /*
    4.7.3.  Updating the Negotiation-Needed flag

      To update the negotiation-needed flag
      5.  Set connection's [[needNegotiation]] slot to true.
      6.  Queue a task that runs the following steps:
          3.  Fire a simple event named negotiationneeded at connection.

      To check if negotiation is needed
      2.  If connection has created any RTCDataChannels, and no m= section has
          been negotiated yet for data, return "true".

    6.1.  RTCPeerConnection Interface Extensions

      createDataChannel
        14. If channel was the first RTCDataChannel created on connection,
            update the negotiation-needed flag for connection.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const negotiated = awaitNegotiation(pc);

    pc.createDataChannel('test');
    return negotiated;
  }, 'Creating first data channel should fire negotiationneeded event');

  test_never_resolve(t => {
    const pc = new RTCPeerConnection();
    const negotiated = awaitNegotiation(pc);

    pc.createDataChannel('foo');
    return negotiated
      .then(({nextPromise}) => {
      pc.createDataChannel('bar');
      return nextPromise;
    });
  }, 'calling createDataChannel twice should fire negotiationneeded event once');

  /*
    4.7.3.  Updating the Negotiation-Needed flag
      To check if negotiation is needed
      3.  For each transceiver t in connection's set of transceivers, perform
          the following checks:
          1.  If t isn't stopped and isn't yet associated with an m= section
              according to [JSEP] (section 3.4.1.), return "true".

    5.1.  RTCPeerConnection Interface Extensions
      addTransceiver
        9.  Update the negotiation-needed flag for connection.
   */
  promise_test(t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());
    const negotiated = awaitNegotiation(pc);

    pc.addTransceiver('audio');
    return negotiated;
  }, 'addTransceiver() should fire negotiationneeded event');

  /*
    4.7.3.  Updating the Negotiation-Needed flag
      To update the negotiation-needed flag
      4.  If connection's [[needNegotiation]] slot is already true, abort these steps.
   */
  test_never_resolve(t => {
    const pc = new RTCPeerConnection();
    const negotiated = awaitNegotiation(pc);

    pc.addTransceiver('audio');
    return negotiated
    .then(({nextPromise}) => {
      pc.addTransceiver('video');
      return nextPromise;
    });
  }, 'Calling addTransceiver() twice should fire negotiationneeded event once');

  /*
    4.7.3.  Updating the Negotiation-Needed flag
      To update the negotiation-needed flag
      4.  If connection's [[needNegotiation]] slot is already true, abort these steps.
   */
  test_never_resolve(t => {
    const pc = new RTCPeerConnection();
    const negotiated = awaitNegotiation(pc);

    pc.createDataChannel('test');
    return negotiated
    .then(({nextPromise}) => {
      pc.addTransceiver('video');
      return nextPromise;
    });
  }, 'Calling both addTransceiver() and createDataChannel() should fire negotiationneeded event once');

  /*
    4.7.3.  Updating the Negotiation-Needed flag
      To update the negotiation-needed flag
      2.  If connection's signaling state is not "stable", abort these steps.
   */
  test_never_resolve(t => {
    const pc = new RTCPeerConnection();
    let negotiated;

    return generateAudioReceiveOnlyOffer(pc)
    .then(offer => {
      pc.setLocalDescription(offer);
      negotiated = awaitNegotiation(pc);
    })
    .then(() => negotiated)
    .then(({nextPromise}) => {
      assert_equals(pc.signalingState, 'have-local-offer');
      pc.createDataChannel('test');
      return nextPromise;
    });
  }, 'negotiationneeded event should not fire if signaling state is not stable');

  /*
    4.4.1.6.  Set the RTCSessionSessionDescription
      2.2.10. If connection's signaling state is now stable, update the negotiation-needed
              flag. If connection's [[NegotiationNeeded]] slot was true both before and after
              this update, queue a task that runs the following steps:
        2.  If connection's [[NegotiationNeeded]] slot is false, abort these steps.
        3.  Fire a simple event named negotiationneeded at connection.
   */
  promise_test(async t => {
    const pc = new RTCPeerConnection();

    t.add_cleanup(() => pc.close());

    pc.addTransceiver('audio');
    await new Promise(resolve => pc.onnegotiationneeded = resolve);

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    let fired = false;
    pc.onnegotiationneeded = e => fired = true;
    pc.createDataChannel('test');
    await pc.setRemoteDescription(await generateAnswer(offer));
    await undefined;
    assert_false(fired, "negotiationneeded should not fire until the next iteration of the event loop after SRD success");
    await new Promise(resolve => pc.onnegotiationneeded = resolve);
  }, 'negotiationneeded event should fire only after signaling state goes back to stable after setRemoteDescription');

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

    pc.addTransceiver('audio');
    await new Promise(resolve => pc.onnegotiationneeded = resolve);

    let fired = false;
    pc.onnegotiationneeded = e => fired = true;
    await pc.setRemoteDescription(await generateOffer());
    pc.createDataChannel('test');
    await pc.setLocalDescription(await pc.createAnswer());
    await undefined;
    assert_false(fired, "negotiationneeded should not fire until the next iteration of the event loop after SLD success");

    await new Promise(resolve => pc.onnegotiationneeded = resolve);
  }, 'negotiationneeded event should fire only after signaling state goes back to stable after setLocalDescription');

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

    t.add_cleanup(() => pc.close());

    pc.addTransceiver('audio');
    await new Promise(resolve => pc.onnegotiationneeded = resolve);

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    let fired = false;
    pc.onnegotiationneeded = e => fired = true;
    pc.createDataChannel('test');
    const p = pc.setRemoteDescription(await generateAnswer(offer));
    await new Promise(resolve => pc.onsignalingstatechange = resolve);
    assert_false(fired, "negotiationneeded should not fire before signalingstatechange fires");
    await new Promise(resolve => pc.onnegotiationneeded = resolve);
    await p;
  }, 'negotiationneeded event should fire only after signalingstatechange event fires from setRemoteDescription');

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

    pc.addTransceiver('audio');
    await new Promise(resolve => pc.onnegotiationneeded = resolve);

    let fired = false;
    pc.onnegotiationneeded = e => fired = true;
    await pc.setRemoteDescription(await generateOffer());
    pc.createDataChannel('test');

    const p = pc.setLocalDescription(await pc.createAnswer());
    await new Promise(resolve => pc.onsignalingstatechange = resolve);
    assert_false(fired, "negotiationneeded should not fire until the next iteration of the event loop after returning to stable");
    await new Promise(resolve => pc.onnegotiationneeded = resolve);
    await p;
  }, 'negotiationneeded event should fire only after signalingstatechange event fires from setLocalDescription');

  /*
    5.1.  RTCPeerConnection Interface Extensions

      addTrack
        10. Update the negotiation-needed flag for connection.
  */
  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);

    await new Promise(resolve => pc.onnegotiationneeded = resolve);
  }, 'addTrack should cause negotiationneeded to fire');

  /*
    5.1.  RTCPeerConnection Interface Extensions

      removeTrack
        12. Update the negotiation-needed flag for connection.
  */
  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);

    await new Promise(resolve => pc.onnegotiationneeded = resolve);
    pc.onnegotiationneeded = t.step_func(() => {
      assert_unreached('onnegotiationneeded misfired');
    });

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);

    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);

    pc.removeTrack(sender);
    await new Promise(resolve => pc.onnegotiationneeded = resolve)
  }, 'removeTrack should cause negotiationneeded to fire on the caller');

  /*
    5.1.  RTCPeerConnection Interface Extensions

      removeTrack
        12. Update the negotiation-needed flag for connection.
  */
  promise_test(async t => {
    const caller = new RTCPeerConnection();
    t.add_cleanup(() => caller.close());
    caller.addTransceiver('audio', {direction:'recvonly'});
    const offer = await caller.createOffer();

    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 sender = callee.addTrack(track, stream);

    await new Promise(resolve => callee.onnegotiationneeded = resolve);
    callee.onnegotiationneeded = t.step_func(() => {
      assert_unreached('onnegotiationneeded misfired');
    });

    await callee.setRemoteDescription(offer);
    const answer = await callee.createAnswer();
    callee.setLocalDescription(answer);

    callee.removeTrack(sender);
    await new Promise(resolve => callee.onnegotiationneeded = resolve)
  }, 'removeTrack should cause negotiationneeded to fire on the callee');

  /*
    5.4.  RTCRtpTransceiver Interface

      setDirection
        7.  Update the negotiation-needed flag for connection.
  */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const transceiver = pc.addTransceiver('audio', {direction:'sendrecv'});
    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);
    transceiver.direction = 'recvonly';
    await new Promise(resolve => pc.onnegotiationneeded = resolve);
  }, 'Updating the direction of the transceiver should cause negotiationneeded to fire');

  /*
    5.2.  RTCRtpSender Interface

      setStreams
        7.  Update the negotiation-needed flag for connection.
  */
  promise_test(async t => {
    const pc = new RTCPeerConnection();
    t.add_cleanup(() => pc.close());

    const transceiver = pc.addTransceiver('audio', {direction:'sendrecv'});
    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);

    const stream = new MediaStream();
    transceiver.sender.setStreams(stream);
    await new Promise(resolve => pc.onnegotiationneeded = resolve);
  }, 'Calling setStreams should cause negotiationneeded to fire');

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

    const transceiver = pc.addTransceiver('audio', {direction:'sendrecv'});
    const stream = new MediaStream();
    transceiver.sender.setStreams(stream);
    await new Promise(resolve => pc.onnegotiationneeded = resolve);

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);

    const stream2 = new MediaStream();
    transceiver.sender.setStreams(stream2);
    await new Promise(resolve => pc.onnegotiationneeded = resolve);
  }, 'Calling setStreams with a different stream as before should cause negotiationneeded to fire');

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

    const transceiver = pc.addTransceiver('audio', {direction:'sendrecv'});
    const stream = new MediaStream();
    transceiver.sender.setStreams(stream);
    await new Promise(resolve => pc.onnegotiationneeded = resolve);

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);

    const stream2 = new MediaStream();
    transceiver.sender.setStreams(stream, stream2);
    await new Promise(resolve => pc.onnegotiationneeded = resolve);
  }, 'Calling setStreams with an additional stream should cause negotiationneeded to fire');

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

    const transceiver = pc.addTransceiver('audio', {direction:'sendrecv'});
    const stream1 = new MediaStream();
    const stream2 = new MediaStream();
    transceiver.sender.setStreams(stream1, stream2);
    await new Promise(resolve => pc.onnegotiationneeded = resolve);

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);

    transceiver.sender.setStreams(stream2);
    await new Promise(resolve => pc.onnegotiationneeded = resolve);
  }, 'Calling setStreams with a stream removed should cause negotiationneeded to fire');

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

    const transceiver = pc.addTransceiver('audio', {direction:'sendrecv'});
    const stream1 = new MediaStream();
    const stream2 = new MediaStream();
    transceiver.sender.setStreams(stream1, stream2);
    await new Promise(resolve => pc.onnegotiationneeded = resolve);

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);

    transceiver.sender.setStreams();
    await new Promise(resolve => pc.onnegotiationneeded = resolve);
  }, 'Calling setStreams with all streams removed should cause negotiationneeded to fire');

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

    const transceiver = pc.addTransceiver('audio', {direction:'sendrecv'});
    const stream = new MediaStream();
    transceiver.sender.setStreams(stream);
    await new Promise(resolve => pc.onnegotiationneeded = resolve);

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);

    transceiver.sender.setStreams(stream);
    const event = await Promise.race([
      new Promise(r => pc.onnegotiationneeded = r),
      new Promise(r => t.step_timeout(r, 10))
    ]);
    assert_equals(event, undefined, "No negotiationneeded event");
  }, 'Calling setStreams with the same stream as before should not cause negotiationneeded to fire');

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

    const transceiver = pc.addTransceiver('audio', {direction:'sendrecv'});
    const stream = new MediaStream();
    transceiver.sender.setStreams(stream);
    await new Promise(resolve => pc.onnegotiationneeded = resolve);

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);

    transceiver.sender.setStreams(stream, stream);
    const event = await Promise.race([
      new Promise(r => pc.onnegotiationneeded = r),
      new Promise(r => t.step_timeout(r, 10))
    ]);
    assert_equals(event, undefined, "No negotiationneeded event");
  }, 'Calling setStreams with duplicates of the same stream as before should not cause negotiationneeded to fire');

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

    const transceiver = pc.addTransceiver('audio', {direction:'sendrecv'});
    const stream1 = new MediaStream();
    const stream2 = new MediaStream();
    transceiver.sender.setStreams(stream1, stream2);
    await new Promise(resolve => pc.onnegotiationneeded = resolve);

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);

    transceiver.sender.setStreams(stream2, stream1);
    const event = await Promise.race([
      new Promise(r => pc.onnegotiationneeded = r),
      new Promise(r => t.step_timeout(r, 10))
    ]);
    assert_equals(event, undefined, "No negotiationneeded event");
  }, 'Calling setStreams with the same streams as before in a different order should not cause negotiationneeded to fire');

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

    const transceiver = pc.addTransceiver('audio', {direction:'sendrecv'});
    const stream1 = new MediaStream();
    const stream2 = new MediaStream();
    transceiver.sender.setStreams(stream1, stream2);
    await new Promise(resolve => pc.onnegotiationneeded = resolve);

    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    const answer = await generateAnswer(offer);
    await pc.setRemoteDescription(answer);

    transceiver.sender.setStreams(stream1, stream2, stream1);
    const event = await Promise.race([
      new Promise(r => pc.onnegotiationneeded = r),
      new Promise(r => t.step_timeout(r, 10))
    ]);
    assert_equals(event, undefined, "No negotiationneeded event");
  }, 'Calling setStreams with duplicates of the same streams as before should not cause negotiationneeded to fire');

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

    let negotiationCount = 0;
    pc1.onnegotiationneeded = async () => {
      negotiationCount++;
      await pc1.setLocalDescription(await pc1.createOffer());
      await pc2.setRemoteDescription(pc1.localDescription);
      await pc2.setLocalDescription(await pc2.createAnswer());
      await pc1.setRemoteDescription(pc2.localDescription);
    }

    pc1.addTransceiver("video");
    await new Promise(r => pc1.onsignalingstatechange = () => pc1.signalingState == "stable" && r());
    pc1.addTransceiver("audio");
    await new Promise(r => pc1.onsignalingstatechange = () => pc1.signalingState == "stable" && r());
    assert_equals(negotiationCount, 2);
  }, 'Adding two transceivers, one at a time, results in the expected number of negotiationneeded events');

  /*
    TODO
    4.7.3.  Updating the Negotiation-Needed flag

      To update the negotiation-needed flag
      3.  If the result of checking if negotiation is needed is "false",
          clear the negotiation-needed flag by setting connection's
          [[needNegotiation]] slot to false, and abort these steps.
      6.  Queue a task that runs the following steps:
          2.  If connection's [[needNegotiation]] slot is false, abort these steps.

      To check if negotiation is needed
      3.  For each transceiver t in connection's set of transceivers, perform
          the following checks:
          2.  If t isn't stopped and is associated with an m= section according
              to [JSEP] (section 3.4.1.), then perform the following checks:
              1.  If t's direction is "sendrecv" or "sendonly", and the
                  associated m= section in connection's currentLocalDescription
                  doesn't contain an "a=msid" line, return "true".
              2.  If connection's currentLocalDescription if of type "offer",
                  and the direction of the associated m= section in neither the
                  offer nor answer matches t's direction, return "true".
              3.  If connection's currentLocalDescription if of type "answer",
                  and the direction of the associated m= section in the answer
                  does not match t's direction intersected with the offered
                  direction (as described in [JSEP] (section 5.3.1.)),
                  return "true".
          3.  If t is stopped and is associated with an m= section according
              to [JSEP] (section 3.4.1.), but the associated m= section is
              not yet rejected in connection's currentLocalDescription or
              currentRemoteDescription , return "true".
      4.  If all the preceding checks were performed and "true" was not returned,
          nothing remains to be negotiated; return "false".

    4.3.1.  RTCPeerConnection Operation

      When the RTCPeerConnection() constructor is invoked
        7.  Let connection have a [[needNegotiation]] internal slot, initialized to false.

    5.4.  RTCRtpTransceiver Interface

      stop
        11. Update the negotiation-needed flag for connection.

    Untestable
    4.7.3.  Updating the Negotiation-Needed flag
      1.  If connection's [[isClosed]] slot is true, abort these steps.
      6.  Queue a task that runs the following steps:
          1.  If connection's [[isClosed]] slot is true, abort these steps.
   */

</script>
