<!doctype html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>RTCPeerConnection Connection Test</title>
  <script src="RTCPeerConnection-helper.js"></script>
</head>
<body>
  <div id="log"></div>
  <div>
    <video id="local-view" muted autoplay="autoplay"></video>
    <video id="remote-view" muted autoplay="autoplay"/>
    </video>
  </div>

  <!-- These files are in place when executing on W3C. -->
  <script src="/resources/testharness.js"></script>
  <script src="/resources/testharnessreport.js"></script>
  <script type="text/javascript">
  var test = async_test('Can set up a basic WebRTC call without announcing ssrcs.');

  var gFirstConnection = null;
  var gSecondConnection = null;

  // if the remote video gets video data that implies the negotiation
  // as well as the ICE and DTLS connection are up.
  document.getElementById('remote-view')
      .addEventListener('loadedmetadata', function() {
    // Call negotiated: done.
    test.done();
  });

  function getNoiseStreamOkCallback(localStream) {
    gFirstConnection = new RTCPeerConnection(null);
    test.add_cleanup(() => gFirstConnection.close());
    gFirstConnection.onicecandidate = onIceCandidateToFirst;
    localStream.getTracks().forEach(function(track) {
      gFirstConnection.addTrack(track, localStream);
    });
    gFirstConnection.createOffer().then(onOfferCreated, failed('createOffer'));

    var videoTag = document.getElementById('local-view');
    videoTag.srcObject = localStream;
  };

  var onOfferCreated = test.step_func(function(offer) {
    gFirstConnection.setLocalDescription(offer);

    // remove all a=ssrc: lines and the (obsolete) msid-semantic line.
    var sdp = offer.sdp.replace(/^a=ssrc:.*$\r\n/gm, '')
      .replace(/^a=msid-semantic.*$\r\n/gm, '');

    // This would normally go across the application's signaling solution.
    // In our case, the "signaling" is to call this function.
    receiveCall(sdp);
  });

  function receiveCall(offerSdp) {
    gSecondConnection = new RTCPeerConnection(null);
    test.add_cleanup(() => gSecondConnection.close());
    gSecondConnection.onicecandidate = onIceCandidateToSecond;
    gSecondConnection.ontrack = onRemoteTrack;

    var parsedOffer = new RTCSessionDescription({ type: 'offer',
                                                  sdp: offerSdp });
    gSecondConnection.setRemoteDescription(parsedOffer);

    gSecondConnection.createAnswer().then(onAnswerCreated,
                                   failed('createAnswer'));
  };

  var onAnswerCreated = test.step_func(function(answer) {
    gSecondConnection.setLocalDescription(answer);

    // remove all a=ssrc: lines, the msid-semantic line and any a=msid:.
    var sdp = answer.sdp.replace(/^a=ssrc:.*$\r\n/gm, '')
      .replace(/^a=msid-semantic.*$\r\n/gm, '')
      .replace(/^a=msid:.*$\r\n/gm, '');

    // Similarly, this would go over the application's signaling solution.
    handleAnswer(sdp);
  });

  function handleAnswer(answerSdp) {
    var parsedAnswer = new RTCSessionDescription({ type: 'answer',
                                                   sdp: answerSdp });
    gFirstConnection.setRemoteDescription(parsedAnswer);
  };

  var onIceCandidateToFirst = test.step_func(function(event) {
    gSecondConnection.addIceCandidate(event.candidate);
  });

  var onIceCandidateToSecond = test.step_func(function(event) {
    gFirstConnection.addIceCandidate(event.candidate);
  });

  var onRemoteTrack = test.step_func(function(event) {
    var videoTag = document.getElementById('remote-view');
    if (!videoTag.srcObject) {
      videoTag.srcObject = event.streams[0];
    }
  });

  // Returns a suitable error callback.
  function failed(function_name) {
    return test.unreached_func('WebRTC called error callback for ' + function_name);
  }

  // This function starts the test.
  test.step(function() {
    getNoiseStream({ video: true, audio: true })
      .then(test.step_func(getNoiseStreamOkCallback), failed('getNoiseStream'));
  });
</script>

</body>
</html>
