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

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

  /*
    5.5.  RTCDtlsTransport Interface
      interface RTCDtlsTransport : EventTarget {
        readonly attribute RTCDtlsTransportState state;
        sequence<ArrayBuffer> getRemoteCertificates();
                 attribute EventHandler          onstatechange;
                 attribute EventHandler          onerror;
        ...
      };

      enum RTCDtlsTransportState {
        "new",
        "connecting",
        "connected",
        "closed",
        "failed"
      };

      getRemoteCertificates
        Returns the certificate chain in use by the remote side, with each certificate
        encoded in binary Distinguished Encoding Rules (DER) [X690].
        getRemoteCertificates() will return an empty list prior to selection of the
        remote certificate, which will be completed by the time RTCDtlsTransportState
        transitions to "connected".
   */
  async_test(t => {
    const pc1 = new RTCPeerConnection();
    t.add_cleanup(() => pc1.close());
    const pc2 = new RTCPeerConnection();
    t.add_cleanup(() => pc2.close());

    pc1.addTrack(trackFactories.audio());
    exchangeIceCandidates(pc1, pc2);

    exchangeOfferAnswer(pc1, pc2)
    .then(t.step_func(() => {
      const dtlsTransport1 = pc1.getSenders()[0].transport;
      const dtlsTransport2 = pc2.getReceivers()[0].transport;

      const testedTransports = new Set();

      // Callback function that test the respective DTLS transports
      // when they become connected.
      const onConnected = t.step_func(dtlsTransport => {
        const certs = dtlsTransport.getRemoteCertificates();

        assert_greater_than(certs.length, 0,
          'Expect DTLS transport to have at least one remote certificate when connected');

        for(const cert of certs) {
          assert_true(cert instanceof ArrayBuffer,
            'Expect certificate elements be instance of ArrayBuffer');
        }

        testedTransports.add(dtlsTransport);

        // End the test if both dtlsTransports are tested.
        if(testedTransports.has(dtlsTransport1) && testedTransports.has(dtlsTransport2)) {
          t.done();
        }
      })

      for(const dtlsTransport of [dtlsTransport1, dtlsTransport2]) {
        if(dtlsTransport.state === 'connected') {
          onConnected(dtlsTransport);
        } else {
          assert_array_equals(dtlsTransport.getRemoteCertificates(), [],
            'Expect DTLS certificates be initially empty until become connected');

          dtlsTransport.addEventListener('statechange', t.step_func(() => {
            if(dtlsTransport.state === 'connected') {
              onConnected(dtlsTransport);
            }
          }));

          dtlsTransport.addEventListener('error', t.step_func(err => {
            assert_unreached(`Unexpected error during DTLS handshake: ${err}`);
          }));
        }
      }
    }));
  });

</script>
