Reland: Implement RTCIceTransport.onselectedcandidatepairchange

TBR=hta@chromium.org,haraken@chromium.org

Bug: 864871
Change-Id: I6a2e0dc98efc58e22b33066ee3d37ded3c9b021a
Reviewed-on: https://chromium-review.googlesource.com/c/1258503
Commit-Queue: Steve Anton <steveanton@chromium.org>
Reviewed-by: Henrik Boström <hbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596207}
diff --git a/webrtc/RTCIceTransport-extension.https.html b/webrtc/RTCIceTransport-extension.https.html
index 5adee9f..7803bde 100644
--- a/webrtc/RTCIceTransport-extension.https.html
+++ b/webrtc/RTCIceTransport-extension.https.html
@@ -15,12 +15,6 @@
 //   makeIceTransport
 //   makeGatherAndStartTwoIceTransports
 
-function makeIceTransport(t) {
-  const iceTransport = new RTCIceTransport();
-  t.add_cleanup(() => iceTransport.stop());
-  return iceTransport;
-}
-
 test(() => {
   const iceTransport = new RTCIceTransport();
 }, 'RTCIceTransport constructor does not throw');
@@ -260,4 +254,49 @@
   ]);
 }, 'Two RTCIceTransports connect to each other');
 
+promise_test(async t => {
+  async function waitForConnectedThenSelectedCandidatePairChange(t, transport,
+      transportName) {
+    const watcher = new EventWatcher(t, transport,
+        [ 'statechange', 'selectedcandidatepairchange' ]);
+    await watcher.wait_for('statechange');
+    assert_equals(transport.state, 'connected',
+        `${transportName} state should be 'connected'`);
+    await watcher.wait_for('selectedcandidatepairchange');
+    const selectedCandidatePair = transport.getSelectedCandidatePair();
+    assert_not_equals(selectedCandidatePair, null,
+        `${transportName} selected candidate pair should not be null once ` +
+        'the selectedcandidatepairchange event fires');
+    assert_true(
+        transport.getLocalCandidates().some(
+            ({ candidate }) =>
+                candidate === selectedCandidatePair.local.candidate),
+        `${transportName} selected candidate pair local should be in the ` +
+        'list of local candidates');
+    assert_true(
+        transport.getRemoteCandidates().some(
+            ({ candidate }) =>
+                candidate === selectedCandidatePair.remote.candidate),
+        `${transportName} selected candidate pair local should be in the ` +
+        'list of remote candidates');
+  }
+  const [ localTransport, remoteTransport ] =
+      makeGatherAndStartTwoIceTransports(t);
+  await Promise.all([
+    waitForConnectedThenSelectedCandidatePairChange(t, localTransport,
+        'local transport'),
+    waitForConnectedThenSelectedCandidatePairChange(t, remoteTransport,
+        'remote transport'),
+  ]);
+}, 'Selected candidate pair changes once the RTCIceTransports connect.');
+
+promise_test(async t => {
+  const [ transport, ] = makeGatherAndStartTwoIceTransports(t);
+  const watcher = new EventWatcher(t, transport, 'selectedcandidatepairchange');
+  await watcher.wait_for('selectedcandidatepairchange');
+  transport.stop();
+  assert_equals(transport.getSelectedCandidatePair(), null);
+}, 'getSelectedCandidatePair() returns null once the RTCIceTransport is ' +
+    'stopped.');
+
 </script>