<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[243041] trunk/LayoutTests</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/243041">243041</a></dd>
<dt>Author</dt> <dd>youenn@apple.com</dd>
<dt>Date</dt> <dd>2019-03-16 09:35:16 -0700 (Sat, 16 Mar 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>Update WPT WebRTC tests up to a22a149
https://bugs.webkit.org/show_bug.cgi?id=195831

Reviewed by Eric Carlson.

LayoutTests/imported/w3c:

* web-platform-tests/webrtc: Resynced.

LayoutTests:

* tests-options.json:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsTestExpectations">trunk/LayoutTests/TestExpectations</a></li>
<li><a href="#trunkLayoutTestsimportedw3cChangeLog">trunk/LayoutTests/imported/w3c/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcMETAyml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/META.yml</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCConfigurationrtcpMuxPolicyhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCConfiguration-rtcpMuxPolicy.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCDTMFSenderinsertDTMFhttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDTMFSender-insertDTMF.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCDataChannelbufferedAmountexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-bufferedAmount-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCDataChannelbufferedAmounthtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-bufferedAmount.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCDataChannelsendhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-send.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCIceCandidateconstructorexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceCandidate-constructor-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCIceCandidateconstructorhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceCandidate-constructor.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCIceTransportextensionhttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceTransport-extension.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCIceTransportextensionhttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceTransport-extension.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionaddIceCandidateexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-addIceCandidate-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionaddIceCandidatehtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-addIceCandidate.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionconnectionStateexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-connectionState-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionconnectionStatehtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-connectionState.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiongetStatshttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-getStats.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiongetStatshttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionhelperjs">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-helper.js</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectioniceGatheringStateexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceGatheringState-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectioniceGatheringStatehtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceGatheringState.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiononnegotiationneededexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiononnegotiationneededhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onnegotiationneeded.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionremotetrackmutehttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-remote-track-mute.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionremotetrackmutehttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-remote-track-mute.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionremoveTrackhttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-removeTrack.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionanswerexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionofferexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionrollbackhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-rollback.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionofferexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionofferhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionrollbackexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-rollback-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionrollbackhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptiontrackshttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiontrackstatshttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-track-stats.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiontrackstatshttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-track-stats.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiontransceivershttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-transceivers.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiontransceivershttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-transceivers.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpParametersencodingsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-encodings-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpParametersencodingshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-encodings.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpParametershelperjs">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-helper.js</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetContributingSourceshttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getContributingSources.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetContributingSourceshttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getContributingSources.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetParametersexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getParameters-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetParametershtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getParameters.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetStatshttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getStats.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetSynchronizationSourceshttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetSynchronizationSourceshttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpSenderreplaceTrackhttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-replaceTrack.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpTransceiverhttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpTransceiverhttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCTrackEventconstructorhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-constructor.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcgetstatsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/getstats-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcgetstatshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/getstats.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcnomediacallhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/no-media-call.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolREADMEtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/README.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolw3cimportlog">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/w3c-import.log</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcrtcpeerconnectionrtcpeerconnectionidlexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/rtcpeerconnection/rtcpeerconnection-idl-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcsimplecallnossrcshttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/simplecall-no-ssrcs.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcsimplecallhttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/simplecall.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcw3cimportlog">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/w3c-import.log</a></li>
<li><a href="#trunkLayoutTeststestsoptionsjson">trunk/LayoutTests/tests-options.json</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCDtlsTransportstateexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDtlsTransport-state-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCDtlsTransportstatehtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDtlsTransport-state.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCErrorexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCError-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCErrorhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCError.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCIceConnectionStatecandidatepairhttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceConnectionState-candidate-pair.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCIceConnectionStatecandidatepairhttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceConnectionState-candidate-pair.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectioniceConnectionStatehttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectioniceConnectionStatehttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiononsignalingstatechangedhttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiononsignalingstatechangedhttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionnomsidexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionnomsidhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpSendertransporthttpsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-transport.https-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpSendertransporthttpshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-transport.https.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpTransceiverstopexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver-stop-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpTransceiverstophtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver-stop.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCTrackEventfireexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-fire-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCTrackEventfirehtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-fire.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolmissingfieldsexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/missing-fields-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolmissingfieldshtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/missing-fields.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolmsidparseexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/msid-parse-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolmsidparsehtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/msid-parse.html</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolsimulcastofferexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/simulcast-offer-expected.txt</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolsimulcastofferhtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/simulcast-offer.html</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectioniceConnectionStatehtml">trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/ChangeLog 2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2019-03-16  Youenn Fablet  <youenn@apple.com>
+
+        Update WPT WebRTC tests up to a22a149
+        https://bugs.webkit.org/show_bug.cgi?id=195831
+
+        Reviewed by Eric Carlson.
+
+        * tests-options.json:
+
</ins><span class="cx"> 2019-03-15  Joseph Pecoraro  <pecoraro@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: HAR Extension for Resource Priority
</span></span></pre></div>
<a id="trunkLayoutTestsTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/TestExpectations (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/TestExpectations       2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/TestExpectations  2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1340,8 +1340,15 @@
</span><span class="cx"> webkit.org/b/172f21 imported/w3c/web-platform-tests/webrtc/getstats.html [ Failure ]
</span><span class="cx"> imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-offer.html [ Failure ]
</span><span class="cx"> imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-answer.html [ Failure ]
</span><ins>+imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceGatheringState.html [ Pass Failure ]
+
</ins><span class="cx"> # Skip timing out test
</span><span class="cx"> imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html [ Skip ]
</span><ins>+imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-remote-track-mute.https.html [ Skip ]
+imported/w3c/web-platform-tests/webrtc/RTCDataChannel-bufferedAmount.html [ Skip ]
+imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-fire.html [ Skip ]
+imported/w3c/web-platform-tests/webrtc/rtcpeerconnection/iceGatheringState.html [ Skip ]
+imported/w3c/web-platform-tests/webrtc/RTCIceConnectionState-candidate-pair.https.html [ Skip ]
</ins><span class="cx"> 
</span><span class="cx"> # Uses legacy WebRTC API.
</span><span class="cx"> imported/w3c/web-platform-tests/webrtc/rtcpeerconnection/setRemoteDescription.html [ Skip ]
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/ChangeLog (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/ChangeLog 2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/ChangeLog    2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2019-03-16  Youenn Fablet  <youenn@apple.com>
+
+        Update WPT WebRTC tests up to a22a149
+        https://bugs.webkit.org/show_bug.cgi?id=195831
+
+        Reviewed by Eric Carlson.
+
+        * web-platform-tests/webrtc: Resynced.
+
</ins><span class="cx"> 2019-03-16  Sihui Liu  <sihui_liu@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Layout tests imported/w3c/web-platform-tests/IndexedDB/*-exception-order.html are failing
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcMETAyml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/META.yml (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/META.yml        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/META.yml   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -3,10 +3,8 @@
</span><span class="cx">   - snuggs
</span><span class="cx">   - agouaillard
</span><span class="cx">   - alvestrand
</span><del>-  - dontcallmedom
</del><span class="cx">   - guidou
</span><span class="cx">   - henbos
</span><del>-  - phoglund
</del><span class="cx">   - youennf
</span><span class="cx">   - rwaldron
</span><span class="cx">   - jan-ivar
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCConfigurationrtcpMuxPolicyhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCConfiguration-rtcpMuxPolicy.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCConfiguration-rtcpMuxPolicy.html     2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCConfiguration-rtcpMuxPolicy.html        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -3,6 +3,7 @@
</span><span class="cx"> <script src="/resources/testharness.js"></script>
</span><span class="cx"> <script src="/resources/testharnessreport.js"></script>
</span><span class="cx"> <script src="RTCConfiguration-helper.js"></script>
</span><ins>+<script src="RTCPeerConnection-helper.js"></script>
</ins><span class="cx"> <script>
</span><span class="cx">   'use strict';
</span><span class="cx"> 
</span><span class="lines">@@ -188,8 +189,8 @@
</span><span class="cx">     const pc = new RTCPeerConnection({rtcpMuxPolicy: 'require'});
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><span class="cx"> 
</span><del>-    await pc.createOffer({offerToReceiveAudio: true})
-      .then(offer => pc.setLocalDescription(offer));
</del><ins>+    const offer = await generateAudioReceiveOnlyOffer(pc);
+    await pc.setLocalDescription(offer);
</ins><span class="cx">     return promise_rejects(t, 'InvalidAccessError', pc.setRemoteDescription({type: 'answer', sdp}));
</span><span class="cx">   }, 'setRemoteDescription throws InvalidAccessError when called with an answer without rtcp-mux and rtcpMuxPolicy is set to require');
</span><span class="cx"> </script>
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCDTMFSenderinsertDTMFhttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDTMFSender-insertDTMF.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDTMFSender-insertDTMF.https.html     2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDTMFSender-insertDTMF.https.html        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -122,7 +122,7 @@
</span><span class="cx">     const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</span><span class="cx">     t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track] = stream.getTracks();
</span><del>-    callee.addTrack(track);
</del><ins>+    callee.addTrack(track, stream);
</ins><span class="cx">     const answer = await callee.createAnswer();
</span><span class="cx">     await callee.setLocalDescription(answer);
</span><span class="cx">     await caller.setRemoteDescription(answer);
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCDataChannelbufferedAmountexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-bufferedAmount-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-bufferedAmount-expected.txt      2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-bufferedAmount-expected.txt 2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,6 +1,13 @@
</span><span class="cx"> 
</span><ins>+Harness Error (TIMEOUT), message = null
+
</ins><span class="cx"> FAIL bufferedAmount should increase to byte length of encoded unicode string sent assert_equals: Expect bufferedAmount to be the byte length of the unicode string expected 12 but got 0
</span><span class="cx"> FAIL bufferedAmount should increase to byte length of buffer sent assert_equals: Expect bufferedAmount to increase to byte length of sent buffer expected 5 but got 0
</span><span class="cx"> FAIL bufferedAmount should increase to size of blob sent promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
</span><span class="cx"> FAIL bufferedAmount should increase by byte length for each message sent assert_unreached: Unexpected promise rejection: Error: assert_equals: Expect bufferedAmount to be the total length of all messages queued to send expected 5 but got 0 Reached unreachable code
</span><ins>+TIMEOUT Data channel bufferedamountlow event fires after send() is complete Test timed out
+NOTRUN Data channel bufferedamount is data.length on send(data) 
+NOTRUN Data channel bufferedamount returns the same amount if no more data is sent on the channel 
+NOTRUN Data channel bufferedamountlow event fires only once after multiple consecutive send() calls 
+NOTRUN Data channel bufferedamountlow event fires after each sent message 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCDataChannelbufferedAmounthtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-bufferedAmount.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-bufferedAmount.html      2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-bufferedAmount.html 2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -166,4 +166,59 @@
</span><span class="cx">       assert_unreached(`Unexpected promise rejection: ${err}`)));
</span><span class="cx">   }, 'bufferedAmount should increase by byte length for each message sent');
</span><span class="cx"> 
</span><ins>+  promise_test(async t => {
+    const [channel1, channel2] = await createDataChannelPair();
+    channel1.addEventListener('bufferedamountlow', t.step_func_done(() => {
+      assert_true(channel1.bufferedAmount <= channel1.bufferedAmountLowThreshold);
+    }));
+    const eventWatcher = new EventWatcher(t, channel1, ['bufferedamountlow']);
+    channel1.send(helloString);
+    await eventWatcher.wait_for(['bufferedamountlow']);
+  }, 'Data channel bufferedamountlow event fires after send() is complete');
+
+  promise_test(async t => {
+    const [channel1, channel2] = await createDataChannelPair();
+    channel1.send(helloString);
+    assert_equals(channel1.bufferedAmount, helloString.length);
+    await awaitMessage(channel2);
+    assert_equals(channel1.bufferedAmount, 0);
+  }, 'Data channel bufferedamount is data.length on send(data)');
+
+  promise_test(async t => {
+    const [channel1, channel2] = await createDataChannelPair();
+    channel1.send(helloString);
+    assert_equals(channel1.bufferedAmount, helloString.length);
+    assert_equals(channel1.bufferedAmount, helloString.length);
+  }, 'Data channel bufferedamount returns the same amount if no more data is' +
+     ' sent on the channel');
+
+  promise_test(async t => {
+    const [channel1, channel2] = await createDataChannelPair();
+    let eventFireCount = 0;
+    channel1.addEventListener('bufferedamountlow', t.step_func(() => {
+      assert_true(channel1.bufferedAmount <= channel1.bufferedAmountLowThreshold);
+      assert_equals(++eventFireCount, 1);
+    }));
+    const eventWatcher = new EventWatcher(t, channel1, ['bufferedamountlow']);
+    channel1.send(helloString);
+    assert_equals(channel1.bufferedAmount, helloString.length);
+    channel1.send(helloString);
+    assert_equals(channel1.bufferedAmount, 2 * helloString.length);
+    await eventWatcher.wait_for(['bufferedamountlow']);
+  }, 'Data channel bufferedamountlow event fires only once after multiple' +
+    ' consecutive send() calls');
+
+  promise_test(async t => {
+    const [channel1, channel2] = await createDataChannelPair();
+    const eventWatcher = new EventWatcher(t, channel1, ['bufferedamountlow']);
+    channel1.send(helloString);
+    assert_equals(channel1.bufferedAmount, helloString.length);
+    await eventWatcher.wait_for(['bufferedamountlow']);
+    assert_equals(await awaitMessage(channel2), helloString);
+    channel1.send(helloString);
+    assert_equals(channel1.bufferedAmount, helloString.length);
+    await eventWatcher.wait_for(['bufferedamountlow']);
+    assert_equals(await awaitMessage(channel2), helloString);
+  }, 'Data channel bufferedamountlow event fires after each sent message');
+
</ins><span class="cx"> </script>
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCDataChannelsendhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-send.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-send.html        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-send.html   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -14,7 +14,7 @@
</span><span class="cx">   //  createDataChannelPair
</span><span class="cx">   //  awaitMessage
</span><span class="cx">   //  blobToArrayBuffer
</span><del>-  //  assert_equals_array_buffer
</del><ins>+  //  assert_equals_typed_array
</ins><span class="cx"> 
</span><span class="cx">   /*
</span><span class="cx">     6.2.  RTCDataChannel
</span><span class="lines">@@ -140,7 +140,7 @@
</span><span class="cx">       assert_true(messageBuffer instanceof ArrayBuffer,
</span><span class="cx">         'Expect messageBuffer to be an ArrayBuffer');
</span><span class="cx"> 
</span><del>-      assert_equals_array_buffer(messageBuffer, helloBuffer.buffer);
</del><ins>+      assert_equals_typed_array(messageBuffer, helloBuffer.buffer);
</ins><span class="cx">     });
</span><span class="cx">   }, 'Data channel should be able to send Uint8Array message and receive as ArrayBuffer');
</span><span class="cx"> 
</span><span class="lines">@@ -162,7 +162,7 @@
</span><span class="cx">       assert_true(messageBuffer instanceof ArrayBuffer,
</span><span class="cx">         'Expect messageBuffer to be an ArrayBuffer');
</span><span class="cx"> 
</span><del>-      assert_equals_array_buffer(messageBuffer, helloBuffer.buffer);
</del><ins>+      assert_equals_typed_array(messageBuffer, helloBuffer.buffer);
</ins><span class="cx">     });
</span><span class="cx">   }, 'Data channel should be able to send ArrayBuffer message and receive as ArrayBuffer');
</span><span class="cx"> 
</span><span class="lines">@@ -183,7 +183,7 @@
</span><span class="cx">       assert_true(messageBuffer instanceof ArrayBuffer,
</span><span class="cx">         'Expect messageBuffer to be an ArrayBuffer');
</span><span class="cx"> 
</span><del>-      assert_equals_array_buffer(messageBuffer, helloBuffer.buffer);
</del><ins>+      assert_equals_typed_array(messageBuffer, helloBuffer.buffer);
</ins><span class="cx">     });
</span><span class="cx">   }, 'Data channel should be able to send Blob message and receive as ArrayBuffer');
</span><span class="cx"> 
</span><span class="lines">@@ -210,7 +210,7 @@
</span><span class="cx">       assert_true(messageBuffer instanceof ArrayBuffer,
</span><span class="cx">         'Expect messageBuffer to be an ArrayBuffer');
</span><span class="cx"> 
</span><del>-      assert_equals_array_buffer(messageBuffer, helloBuffer.buffer);
</del><ins>+      assert_equals_typed_array(messageBuffer, helloBuffer.buffer);
</ins><span class="cx">     });
</span><span class="cx">   }, 'Data channel should be able to send ArrayBuffer message and receive as Blob');
</span><span class="cx"> 
</span><span class="lines">@@ -240,7 +240,7 @@
</span><span class="cx">       assert_true(messageBuffer instanceof ArrayBuffer,
</span><span class="cx">         'Expect messageBuffer to be an ArrayBuffer');
</span><span class="cx"> 
</span><del>-      assert_equals_array_buffer(messageBuffer, helloBuffer.buffer);
</del><ins>+      assert_equals_typed_array(messageBuffer, helloBuffer.buffer);
</ins><span class="cx">     });
</span><span class="cx">   }, 'Data channel binaryType should receive message as Blob by default');
</span><span class="cx"> 
</span><span class="lines">@@ -253,9 +253,9 @@
</span><span class="cx">       receivedMessages.push(data);
</span><span class="cx"> 
</span><span class="cx">       if(receivedMessages.length === 3) {
</span><del>-        assert_equals_array_buffer(receivedMessages[0], helloBuffer.buffer);
</del><ins>+        assert_equals_typed_array(receivedMessages[0], helloBuffer.buffer);
</ins><span class="cx">         assert_equals(receivedMessages[1], unicodeString);
</span><del>-        assert_equals_array_buffer(receivedMessages[2], helloBuffer.buffer);
</del><ins>+        assert_equals_typed_array(receivedMessages[2], helloBuffer.buffer);
</ins><span class="cx"> 
</span><span class="cx">         t.done();
</span><span class="cx">       }
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCDtlsTransportstateexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDtlsTransport-state-expected.txt (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDtlsTransport-state-expected.txt                             (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDtlsTransport-state-expected.txt        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+
+FAIL DTLS transport goes to connected state promise_test: Unhandled rejection with value: object "ReferenceError: Can't find variable: RTCDtlsTransport"
+FAIL close() causes the local transport to close immediately promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'dtlstransport.state')"
+FAIL close() causes the other end's DTLS transport to close promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'dtlstransport.state')"
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCDtlsTransportstatehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDtlsTransport-state.html (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDtlsTransport-state.html                             (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDtlsTransport-state.html        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,122 @@
</span><ins>+<!doctype html>
+<meta charset="utf-8">
+<title>RTCDtlsTransport</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
+//   doSignalingHandshake
+//   trackFactories.audio()
+
+/*
+    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"
+      };
+
+*/
+function resolveWhen(t, dtlstransport, state) {
+  return new Promise((resolve, reject) => {
+    if (dtlstransport.state == state) { resolve(); }
+    dtlstransport.addEventListener('statechange', t.step_func(e => {
+      if (dtlstransport.state == state) {
+        resolve();
+      }
+    }));
+  });
+}
+
+// Helper class to exchange ice candidates between
+// two local peer connections
+class CandidateChannel {
+  constructor(source, dest) {
+    source.addEventListener('icecandidate', event => {
+      const { candidate } = event;
+      if (candidate && this.activated
+          && this.destination.signalingState !== 'closed') {
+        this.destination.addIceCandidate(candidate);
+      } else {
+        this.queue.push(candidate);
+      }
+    });
+    this.destination = dest;
+    this.activated = false;
+    this.queue = [];
+  }
+  activate() {
+    this.activated = true;
+    for (const candidate of this.queue) {
+      this.destination.addIceCandidate(candidate);
+    }
+  }
+}
+
+function coupleCandidates(pc1, pc2) {
+  const ch1 = new CandidateChannel(pc1, pc2);
+  const ch2 = new CandidateChannel(pc2, pc1);
+  return [ch1, ch2];
+}
+
+async function setupConnections(t) {
+  const pc1 = new RTCPeerConnection();
+  t.add_cleanup(() => pc1.close());
+  const pc2 = new RTCPeerConnection();
+  t.add_cleanup(() => pc2.close());
+
+  pc1.addTrack(trackFactories.audio());
+  const channels = coupleCandidates(pc1, pc2);
+  await doSignalingHandshake(pc1, pc2);
+  for (const channel of channels) {
+    channel.activate();
+  }
+  return [pc1, pc2];
+}
+
+promise_test(async t => {
+  const [pc1, pc2] = await setupConnections(t);
+  const dtlsTransport1 = pc1.getTransceivers()[0].sender.transport;
+  const dtlsTransport2 = pc2.getTransceivers()[0].sender.transport;
+  assert_true(dtlsTransport1 instanceof RTCDtlsTransport);
+  assert_true(dtlsTransport2 instanceof RTCDtlsTransport);
+  await Promise.all([resolveWhen(t, dtlsTransport1, 'connected'),
+                     resolveWhen(t, dtlsTransport2, 'connected')]);
+}, 'DTLS transport goes to connected state');
+
+promise_test(async t => {
+  const [pc1, pc2] = await setupConnections(t);
+
+  const dtlsTransport1 = pc1.getTransceivers()[0].sender.transport;
+  const dtlsTransport2 = pc2.getTransceivers()[0].sender.transport;
+  await Promise.all([resolveWhen(t, dtlsTransport1, 'connected'),
+                     resolveWhen(t, dtlsTransport2, 'connected')]);
+  pc1.close();
+  assert_equals(dtlsTransport1.state, 'closed');
+}, 'close() causes the local transport to close immediately');
+
+promise_test(async t => {
+  const [pc1, pc2] = await setupConnections(t);
+  const dtlsTransport1 = pc1.getTransceivers()[0].sender.transport;
+  const dtlsTransport2 = pc2.getTransceivers()[0].sender.transport;
+  await Promise.all([resolveWhen(t, dtlsTransport1, 'connected'),
+                     resolveWhen(t, dtlsTransport2, 'connected')]);
+  pc1.close();
+  await resolveWhen(t, dtlsTransport2, 'closed');
+}, 'close() causes the other end\'s DTLS transport to close');
+
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCErrorexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCError-expected.txt (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCError-expected.txt                           (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCError-expected.txt      2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+
+FAIL RTCError constructor with errorDetail and message Can't find variable: RTCError
+FAIL RTCError constructor's message argument is optional Can't find variable: RTCError
+FAIL RTCError constructor throws TypeError if arguments are missing assert_throws: function "() => {
+    new RTCError();
+  }" threw object "ReferenceError: Can't find variable: RTCError" ("ReferenceError") expected object "TypeError" ("TypeError")
+FAIL RTCError constructor throws TypeError if the errorDetail is invalid assert_throws: function "() => {
+    new RTCError({errorDetail:'invalid-error-detail'}, 'message');
+  }" threw object "ReferenceError: Can't find variable: RTCError" ("ReferenceError") expected object "TypeError" ("TypeError")
+FAIL RTCError.name is 'RTCError' Can't find variable: RTCError
+FAIL RTCError.code is 0 Can't find variable: RTCError
+FAIL RTCError.errorDetail is readonly. Can't find variable: RTCError
+FAIL RTCErrorInit.errorDetail is the only required attribute assert_throws: function "() => {
+    new RTCError({}, 'message');
+  }" threw object "ReferenceError: Can't find variable: RTCError" ("ReferenceError") expected object "TypeError" ("TypeError")
+FAIL RTCError.sdpLineNumber is null by default Can't find variable: RTCError
+FAIL RTCError.sdpLineNumber is settable by constructor Can't find variable: RTCError
+FAIL RTCError.sdpLineNumber is readonly Can't find variable: RTCError
+FAIL RTCError.httpRequestStatusCode is null by default Can't find variable: RTCError
+FAIL RTCError.httpRequestStatusCode is settable by constructor Can't find variable: RTCError
+FAIL RTCError.httpRequestStatusCode is readonly Can't find variable: RTCError
+FAIL RTCError.sctpCauseCode is null by default Can't find variable: RTCError
+FAIL RTCError.sctpCauseCode is settable by constructor Can't find variable: RTCError
+FAIL RTCError.sctpCauseCode is readonly Can't find variable: RTCError
+FAIL RTCError.receivedAlert is null by default Can't find variable: RTCError
+FAIL RTCError.receivedAlert is settable by constructor Can't find variable: RTCError
+FAIL RTCError.receivedAlert is readonly Can't find variable: RTCError
+FAIL RTCError.sentAlert is null by default Can't find variable: RTCError
+FAIL RTCError.sentAlert is settable by constructor Can't find variable: RTCError
+FAIL RTCError.sentAlert is readonly Can't find variable: RTCError
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCErrorhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCError.html (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCError.html                           (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCError.html      2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,89 @@
</span><ins>+<!doctype html>
+<meta charset=utf-8>
+<title>RTCError and RTCErrorInit</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="RTCPeerConnection-helper.js"></script>
+<script>
+'use strict';
+
+test(() => {
+  const error = new RTCError({errorDetail:'data-channel-failure'}, 'message');
+  assert_equals(error.message, 'message');
+  assert_equals(error.errorDetail, 'data-channel-failure');
+}, 'RTCError constructor with errorDetail and message');
+
+test(() => {
+  const error = new RTCError({errorDetail:'data-channel-failure'});
+  assert_equals(error.message, '');
+}, 'RTCError constructor\'s message argument is optional');
+
+test(() => {
+  assert_throws(new TypeError(), () => {
+    new RTCError();
+  });
+  assert_throws(new TypeError(), () => {
+    new RTCError({});  // {errorDetail} is missing.
+  });
+}, 'RTCError constructor throws TypeError if arguments are missing');
+
+test(() => {
+  assert_throws(new TypeError(), () => {
+    new RTCError({errorDetail:'invalid-error-detail'}, 'message');
+  });
+}, 'RTCError constructor throws TypeError if the errorDetail is invalid');
+
+test(() => {
+  const error = new RTCError({errorDetail:'data-channel-failure'}, 'message');
+  assert_equals(error.name, 'RTCError');
+}, 'RTCError.name is \'RTCError\'');
+
+test(() => {
+  const error = new RTCError({errorDetail:'data-channel-failure'}, 'message');
+  assert_equals(error.code, 0);
+}, 'RTCError.code is 0');
+
+test(() => {
+  const error = new RTCError({errorDetail:'data-channel-failure'}, 'message');
+  assert_throws(new TypeError(), () => {
+    error.errorDetail = 'dtls-failure';
+  });
+}, 'RTCError.errorDetail is readonly.');
+
+test(() => {
+  // Infers what are valid RTCErrorInit objects by passing them to the RTCError
+  // constructor.
+  assert_throws(new TypeError(), () => {
+    new RTCError({}, 'message');
+  });
+  new RTCError({errorDetail:'data-channel-failure'}, 'message');
+}, 'RTCErrorInit.errorDetail is the only required attribute');
+
+// All of these are number types (long or unsigned long).
+const nullableAttributes = ['sdpLineNumber',
+                            'httpRequestStatusCode',
+                            'sctpCauseCode',
+                            'receivedAlert',
+                            'sentAlert'];
+
+nullableAttributes.forEach(attribute => {
+  test(() => {
+    const error = new RTCError({errorDetail:'data-channel-failure'}, 'message');
+    assert_equals(error[attribute], null);
+  }, 'RTCError.' + attribute + ' is null by default');
+
+  test(() => {
+    const error = new RTCError(
+        {errorDetail:'data-channel-failure', [attribute]: 0}, 'message');
+    assert_equals(error[attribute], 0);
+  }, 'RTCError.' + attribute + ' is settable by constructor');
+
+  test(() => {
+    const error = new RTCError({errorDetail:'data-channel-failure'}, 'message');
+    assert_throws(new TypeError(), () => {
+      error[attribute] = 42;
+    });
+  }, 'RTCError.' + attribute + ' is readonly');
+});
+
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCIceCandidateconstructorexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceCandidate-constructor-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceCandidate-constructor-expected.txt        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceCandidate-constructor-expected.txt   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -6,14 +6,15 @@
</span><span class="cx"> PASS new RTCIceCandidate({ candidate: '' }) 
</span><span class="cx"> PASS new RTCIceCandidate({ candidate: null }) 
</span><span class="cx"> PASS new RTCIceCandidate({ ... }) with valid candidate string only 
</span><del>-FAIL new RTCIceCandidate({ sdpMid: 'audio' }) assert_equals: expected (object) null but got (undefined) undefined
-FAIL new RTCIceCandidate({ sdpMLineIndex: 0 }) assert_equals: expected (object) null but got (undefined) undefined
-FAIL new RTCIceCandidate({ sdpMid: 'audio', sdpMLineIndex: 0 }) assert_equals: expected (object) null but got (undefined) undefined
-FAIL new RTCIceCandidate({ candidate: '', sdpMid: 'audio' } assert_equals: expected (object) null but got (undefined) undefined
-FAIL new RTCIceCandidate({ candidate: '', sdpMLineIndex: 0 } assert_equals: expected (object) null but got (undefined) undefined
-FAIL new RTCIceCandidate({ ... }) with valid candidate string and sdpMid assert_equals: expected (object) null but got (undefined) undefined
-FAIL new RTCIceCandidate({ ... }) with invalid candidate string and sdpMid assert_equals: expected (object) null but got (undefined) undefined
-FAIL new RTCIceCandidate({ ... }) with non default value for all fields assert_equals: expected (string) "test" but got (undefined) undefined
-FAIL new RTCIceCandidate({ ... }) with invalid sdpMid assert_equals: expected (object) null but got (undefined) undefined
-FAIL new RTCIceCandidate({ ... }) with invalid sdpMLineIndex assert_equals: expected (object) null but got (undefined) undefined
</del><ins>+FAIL new RTCIceCandidate({ sdpMid: 'audio' }) assert_equals: usernameFragment expected (object) null but got (undefined) undefined
+FAIL new RTCIceCandidate({ sdpMLineIndex: 0 }) assert_equals: usernameFragment expected (object) null but got (undefined) undefined
+FAIL new RTCIceCandidate({ sdpMid: 'audio', sdpMLineIndex: 0 }) assert_equals: usernameFragment expected (object) null but got (undefined) undefined
+FAIL new RTCIceCandidate({ candidate: '', sdpMid: 'audio' } assert_equals: usernameFragment expected (object) null but got (undefined) undefined
+FAIL new RTCIceCandidate({ candidate: '', sdpMLineIndex: 0 } assert_equals: usernameFragment expected (object) null but got (undefined) undefined
+FAIL new RTCIceCandidate({ ... }) with valid candidate string and sdpMid assert_equals: usernameFragment expected (object) null but got (undefined) undefined
+FAIL new RTCIceCandidate({ ... }) with invalid candidate string and sdpMid assert_equals: usernameFragment expected (object) null but got (undefined) undefined
+FAIL new RTCIceCandidate({ ... }) with nondefault values for all fields assert_equals: usernameFragment expected (string) "test" but got (undefined) undefined
+FAIL new RTCIceCandidate({ ... }) with nondefault values for all fields, tcp candidate assert_equals: usernameFragment expected (string) "user1" but got (undefined) undefined
+FAIL new RTCIceCandidate({ ... }) with invalid sdpMid assert_equals: usernameFragment expected (object) null but got (undefined) undefined
+FAIL new RTCIceCandidate({ ... }) with invalid sdpMLineIndex assert_equals: usernameFragment expected (object) null but got (undefined) undefined
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCIceCandidateconstructorhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceCandidate-constructor.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceCandidate-constructor.html        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceCandidate-constructor.html   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -6,6 +6,7 @@
</span><span class="cx">   'use strict';
</span><span class="cx"> 
</span><span class="cx">   const candidateString = 'candidate:1905690388 1 udp 2113937151 192.168.0.1 58041 typ host generation 0 ufrag thC8 network-cost 50';
</span><ins>+  const candidateString2 = 'candidate:435653019 2 tcp 1845501695 192.168.0.196 4444 typ srflx raddr www.example.com rport 22222 tcptype active';
</ins><span class="cx">   const arbitraryString = '<arbitrary string[0] content>;';
</span><span class="cx"> 
</span><span class="cx">   test(t => {
</span><span class="lines">@@ -74,19 +75,19 @@
</span><span class="cx">   test(t => {
</span><span class="cx">     const candidate = new RTCIceCandidate({ sdpMid: 'audio' });
</span><span class="cx"> 
</span><del>-    assert_equals(candidate.candidate, '');
-    assert_equals(candidate.sdpMid, 'audio');
-    assert_equals(candidate.sdpMLineIndex, null);
-    assert_equals(candidate.usernameFragment, null);
</del><ins>+    assert_equals(candidate.candidate, '', 'candidate');
+    assert_equals(candidate.sdpMid, 'audio', 'sdpMid');
+    assert_equals(candidate.sdpMLineIndex, null, 'sdpMLineIndex');
+    assert_equals(candidate.usernameFragment, null, 'usernameFragment');
</ins><span class="cx">   }, `new RTCIceCandidate({ sdpMid: 'audio' })`);
</span><span class="cx"> 
</span><span class="cx">   test(t => {
</span><span class="cx">     const candidate = new RTCIceCandidate({ sdpMLineIndex: 0 });
</span><span class="cx"> 
</span><del>-    assert_equals(candidate.candidate, '');
-    assert_equals(candidate.sdpMid, null);
-    assert_equals(candidate.sdpMLineIndex, 0);
-    assert_equals(candidate.usernameFragment, null);
</del><ins>+    assert_equals(candidate.candidate, '', 'candidate');
+    assert_equals(candidate.sdpMid, null, 'sdpMid');
+    assert_equals(candidate.sdpMLineIndex, 0, 'sdpMLineIndex');
+    assert_equals(candidate.usernameFragment, null, 'usernameFragment');
</ins><span class="cx">   }, 'new RTCIceCandidate({ sdpMLineIndex: 0 })');
</span><span class="cx"> 
</span><span class="cx">   test(t => {
</span><span class="lines">@@ -95,10 +96,10 @@
</span><span class="cx">       sdpMLineIndex: 0
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    assert_equals(candidate.candidate, '');
-    assert_equals(candidate.sdpMid, 'audio');
-    assert_equals(candidate.sdpMLineIndex, 0);
-    assert_equals(candidate.usernameFragment, null);
</del><ins>+    assert_equals(candidate.candidate, '', 'candidate');
+    assert_equals(candidate.sdpMid, 'audio', 'sdpMid');
+    assert_equals(candidate.sdpMLineIndex, 0, 'sdpMLineIndex');
+    assert_equals(candidate.usernameFragment, null, 'usernameFragment');
</ins><span class="cx">   }, `new RTCIceCandidate({ sdpMid: 'audio', sdpMLineIndex: 0 })`);
</span><span class="cx"> 
</span><span class="cx">   test(t => {
</span><span class="lines">@@ -107,10 +108,10 @@
</span><span class="cx">       sdpMid: 'audio'
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    assert_equals(candidate.candidate, '');
-    assert_equals(candidate.sdpMid, 'audio');
-    assert_equals(candidate.sdpMLineIndex, null);
-    assert_equals(candidate.usernameFragment, null);
</del><ins>+    assert_equals(candidate.candidate, '', 'candidate');
+    assert_equals(candidate.sdpMid, 'audio', 'sdpMid');
+    assert_equals(candidate.sdpMLineIndex, null, 'sdpMLineIndex');
+    assert_equals(candidate.usernameFragment, null, 'usernameFragment');
</ins><span class="cx">   }, `new RTCIceCandidate({ candidate: '', sdpMid: 'audio' }`);
</span><span class="cx"> 
</span><span class="cx">   test(t => {
</span><span class="lines">@@ -119,10 +120,10 @@
</span><span class="cx">       sdpMLineIndex: 0
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    assert_equals(candidate.candidate, '');
-    assert_equals(candidate.sdpMid, null);
-    assert_equals(candidate.sdpMLineIndex, 0);
-    assert_equals(candidate.usernameFragment, null);
</del><ins>+    assert_equals(candidate.candidate, '', 'candidate');
+    assert_equals(candidate.sdpMid, null, 'sdpMid', 'sdpMid');
+    assert_equals(candidate.sdpMLineIndex, 0, 'sdpMLineIndex');
+    assert_equals(candidate.usernameFragment, null, 'usernameFragment');
</ins><span class="cx">   }, `new RTCIceCandidate({ candidate: '', sdpMLineIndex: 0 }`);
</span><span class="cx"> 
</span><span class="cx">   test(t => {
</span><span class="lines">@@ -131,10 +132,10 @@
</span><span class="cx">       sdpMid: 'audio'
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    assert_equals(candidate.candidate, candidateString);
-    assert_equals(candidate.sdpMid, 'audio');
-    assert_equals(candidate.sdpMLineIndex, null);
-    assert_equals(candidate.usernameFragment, null);
</del><ins>+    assert_equals(candidate.candidate, candidateString, 'candidate');
+    assert_equals(candidate.sdpMid, 'audio', 'sdpMid');
+    assert_equals(candidate.sdpMLineIndex, null, 'sdpMLineIndex');
+    assert_equals(candidate.usernameFragment, null, 'usernameFragment');
</ins><span class="cx">   }, 'new RTCIceCandidate({ ... }) with valid candidate string and sdpMid');
</span><span class="cx"> 
</span><span class="cx">   test(t =>{
</span><span class="lines">@@ -144,10 +145,10 @@
</span><span class="cx">       sdpMid: 'audio'
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    assert_equals(candidate.candidate, arbitraryString);
-    assert_equals(candidate.sdpMid, 'audio');
-    assert_equals(candidate.sdpMLineIndex, null);
-    assert_equals(candidate.usernameFragment, null);
</del><ins>+    assert_equals(candidate.candidate, arbitraryString, 'candidate');
+    assert_equals(candidate.sdpMid, 'audio', 'sdpMid');
+    assert_equals(candidate.sdpMLineIndex, null, 'sdpMLineIndex');
+    assert_equals(candidate.usernameFragment, null, 'usernameFragment');
</ins><span class="cx">   }, 'new RTCIceCandidate({ ... }) with invalid candidate string and sdpMid');
</span><span class="cx"> 
</span><span class="cx">   test(t => {
</span><span class="lines">@@ -158,23 +159,60 @@
</span><span class="cx">       usernameFragment: 'test'
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    assert_equals(candidate.candidate, candidateString);
-    assert_equals(candidate.sdpMid, 'video');
-    assert_equals(candidate.sdpMLineIndex, 1);
-    assert_equals(candidate.usernameFragment, 'test');
-  }, 'new RTCIceCandidate({ ... }) with non default value for all fields');
</del><ins>+    assert_equals(candidate.candidate, candidateString, 'candidate');
+    assert_equals(candidate.sdpMid, 'video', 'sdpMid');
+    assert_equals(candidate.sdpMLineIndex, 1, 'sdpMLineIndex');
+    assert_equals(candidate.usernameFragment, 'test', 'usernameFragment');
</ins><span class="cx"> 
</span><ins>+    // The following fields should match those in the candidate field
+    assert_equals(candidate.foundation, '1905690388', 'foundation');
+    assert_equals(candidate.component, 'rtp', 'component');
+    assert_equals(candidate.priority, 2113937151, 'priority');
+    assert_equals(candidate.address, '192.168.0.1', 'address');
+    assert_equals(candidate.protocol, 'udp', 'protocol');
+    assert_equals(candidate.port, 58041, 'port');
+    assert_equals(candidate.type, 'host', 'type');
+    assert_equals(candidate.tcpType, '', 'tcpType');
+    assert_equals(candidate.relatedAddress, null, 'relatedAddress');
+    assert_equals(candidate.relatedPort, null, 'relatedPort');
+  }, 'new RTCIceCandidate({ ... }) with nondefault values for all fields');
</ins><span class="cx"> 
</span><span class="cx">   test(t => {
</span><ins>+    const candidate = new RTCIceCandidate({
+      candidate: candidateString2,
+      sdpMid: 'video',
+      sdpMLineIndex: 1,
+      usernameFragment: 'user1'
+    });
+
+    assert_equals(candidate.candidate, candidateString2, 'candidate');
+    assert_equals(candidate.sdpMid, 'video', 'sdpMid');
+    assert_equals(candidate.sdpMLineIndex, 1, 'sdpMLineIndex');
+    assert_equals(candidate.usernameFragment, 'user1', 'usernameFragment');
+
+    // The following fields should match those in the candidate field
+    assert_equals(candidate.foundation, '435653019', 'foundation');
+    assert_equals(candidate.component, 'rtcp', 'component');
+    assert_equals(candidate.priority, 1845501695, 'priority');
+    assert_equals(candidate.address, '192.168.0.196', 'address');
+    assert_equals(candidate.protocol, 'tcp', 'protocol');
+    assert_equals(candidate.port, 4444, 'port');
+    assert_equals(candidate.type, 'srflx', 'type');
+    assert_equals(candidate.tcpType, 'active', 'tcpType');
+    assert_equals(candidate.relatedAddress, 'www.example.com', 'relatedAddress');
+    assert_equals(candidate.relatedPort, 22222, 'relatedPort');
+  }, 'new RTCIceCandidate({ ... }) with nondefault values for all fields, tcp candidate');
+
+  test(t => {
</ins><span class="cx">     // sdpMid is not validated in RTCIceCandidate
</span><span class="cx">     const candidate = new RTCIceCandidate({
</span><span class="cx">       sdpMid: arbitraryString
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    assert_equals(candidate.candidate, '');
-    assert_equals(candidate.sdpMid, arbitraryString);
-    assert_equals(candidate.sdpMLineIndex, null);
-    assert_equals(candidate.usernameFragment, null);
</del><ins>+    assert_equals(candidate.candidate, '', 'candidate');
+    assert_equals(candidate.sdpMid, arbitraryString, 'sdpMid');
+    assert_equals(candidate.sdpMLineIndex, null, 'sdpMLineIndex');
+    assert_equals(candidate.usernameFragment, null, 'usernameFragment');
</ins><span class="cx">   }, 'new RTCIceCandidate({ ... }) with invalid sdpMid');
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -187,10 +225,10 @@
</span><span class="cx">       sdpMLineIndex: 65535
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    assert_equals(candidate.candidate, '');
-    assert_equals(candidate.sdpMid, null);
-    assert_equals(candidate.sdpMLineIndex, 65535);
-    assert_equals(candidate.usernameFragment, null);
</del><ins>+    assert_equals(candidate.candidate, '', 'candidate');
+    assert_equals(candidate.sdpMid, null, 'sdpMid');
+    assert_equals(candidate.sdpMLineIndex, 65535, 'sdpMLineIndex');
+    assert_equals(candidate.usernameFragment, null, 'usernameFragment');
</ins><span class="cx">   }, 'new RTCIceCandidate({ ... }) with invalid sdpMLineIndex');
</span><span class="cx"> 
</span><span class="cx"> </script>
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCIceConnectionStatecandidatepairhttpsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceConnectionState-candidate-pair.https-expected.txt (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceConnectionState-candidate-pair.https-expected.txt                         (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceConnectionState-candidate-pair.https-expected.txt    2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+
+Harness Error (TIMEOUT), message = null
+
+TIMEOUT On ICE connected, getStats() contains a connected candidate-pair Test timed out
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCIceConnectionStatecandidatepairhttpshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceConnectionState-candidate-pair.https.html (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceConnectionState-candidate-pair.https.html                         (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceConnectionState-candidate-pair.https.html    2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,33 @@
</span><ins>+<!doctype html>
+<meta charset=utf-8>
+<meta name="timeout" content="long">
+<title>RTCIceConnectionState and RTCIceCandidatePair</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="RTCPeerConnection-helper.js"></script>
+<script>
+'use strict';
+
+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 navigator.mediaDevices.getUserMedia({audio:true});
+  const [track] = stream.getTracks();
+  caller.addTrack(track, stream);
+  exchangeIceCandidates(caller, callee);
+  await doSignalingHandshake(caller, callee);
+  await listenToIceConnected(t, caller);
+
+  const report = await caller.getStats();
+  let succeededPairFound = false;
+  report.forEach(stats => {
+    if (stats.type == 'candidate-pair' && stats.state == 'succeeded')
+      succeededPairFound = true;
+  });
+  assert_true(succeededPairFound, 'A succeeded candidate-pair should exist');
+}, 'On ICE connected, getStats() contains a connected candidate-pair');
+
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCIceTransportextensionhttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceTransport-extension.https-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceTransport-extension.https-expected.txt    2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceTransport-extension.https-expected.txt       2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,7 +1,4 @@
</span><del>-CONSOLE MESSAGE: line 178: TypeError: Type error
</del><span class="cx"> 
</span><del>-Harness Error (FAIL), message = TypeError: Type error
-
</del><span class="cx"> FAIL RTCIceTransport constructor does not throw function is not a constructor (evaluating 'new RTCIceTransport()')
</span><span class="cx"> FAIL RTCIceTransport initial properties are set function is not a constructor (evaluating 'new RTCIceTransport()')
</span><span class="cx"> FAIL gather() with { iceServers: null } should throw TypeError function is not a constructor (evaluating 'new RTCIceTransport()')
</span><span class="lines">@@ -20,4 +17,15 @@
</span><span class="cx"> FAIL start() does not transition state to 'checking' if no remote candidates added function is not a constructor (evaluating 'new RTCIceTransport()')
</span><span class="cx"> FAIL start() with default role sets role attribute to 'controlled' function is not a constructor (evaluating 'new RTCIceTransport()')
</span><span class="cx"> FAIL start() sets role attribute to 'controlling' function is not a constructor (evaluating 'new RTCIceTransport()')
</span><ins>+FAIL addRemoteCandidate() throws if closed function is not a constructor (evaluating 'new RTCIceTransport()')
+FAIL addRemoteCandidate() throws on invalid candidate function is not a constructor (evaluating 'new RTCIceTransport()')
+FAIL start() transitions state to 'checking' if one remote candidate had been added function is not a constructor (evaluating 'new RTCIceTransport()')
+FAIL addRemoteCandidate() transitions state to 'checking' if start() had been called before function is not a constructor (evaluating 'new RTCIceTransport()')
+FAIL start() throws if later called with a different role function is not a constructor (evaluating 'new RTCIceTransport()')
+FAIL start() flushes remote candidates and transitions state to 'new' if later called with different remote parameters function is not a constructor (evaluating 'new RTCIceTransport()')
+FAIL Two RTCIceTransports connect to each other promise_test: Unhandled rejection with value: object "TypeError: function is not a constructor (evaluating 'new RTCIceTransport()')"
+FAIL Two RTCIceTransports configured with the controlling role resolve the conflict in band and still connect. promise_test: Unhandled rejection with value: object "TypeError: function is not a constructor (evaluating 'new RTCIceTransport()')"
+FAIL Two RTCIceTransports configured with the controlled role resolve the conflict in band and still connect. promise_test: Unhandled rejection with value: object "TypeError: function is not a constructor (evaluating 'new RTCIceTransport()')"
+FAIL Selected candidate pair changes once the RTCIceTransports connect. promise_test: Unhandled rejection with value: object "TypeError: function is not a constructor (evaluating 'new RTCIceTransport()')"
+FAIL getSelectedCandidatePair() returns null once the RTCIceTransport is stopped. promise_test: Unhandled rejection with value: object "TypeError: function is not a constructor (evaluating 'new RTCIceTransport()')"
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCIceTransportextensionhttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceTransport-extension.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceTransport-extension.https.html    2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceTransport-extension.https.html       2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -177,6 +177,7 @@
</span><span class="cx"> 
</span><span class="cx"> const candidate1 = new RTCIceCandidate({
</span><span class="cx">   candidate: 'candidate:1 1 udp 2113929471 203.0.113.100 10100 typ host',
</span><ins>+  sdpMid: '',
</ins><span class="cx"> });
</span><span class="cx"> 
</span><span class="cx"> test(() => {
</span><span class="lines">@@ -191,7 +192,7 @@
</span><span class="cx">   const iceTransport = new RTCIceTransport();
</span><span class="cx">   assert_throws('OperationError',
</span><span class="cx">     () => iceTransport.addRemoteCandidate(
</span><del>-      new RTCIceCandidate({ candidate: 'invalid' })));
</del><ins>+      new RTCIceCandidate({ candidate: 'invalid', sdpMid: '' })));
</ins><span class="cx">   assert_array_equals(iceTransport.getRemoteCandidates(), []);
</span><span class="cx"> }, 'addRemoteCandidate() throws on invalid candidate');
</span><span class="cx"> 
</span><span class="lines">@@ -254,14 +255,31 @@
</span><span class="cx">   ]);
</span><span class="cx"> }, 'Two RTCIceTransports connect to each other');
</span><span class="cx"> 
</span><ins>+['controlling', 'controlled'].forEach(role => {
+  promise_test(async t => {
+    const [ localTransport, remoteTransport ] =
+        makeAndGatherTwoIceTransports(t);
+    localTransport.start(remoteTransport.getLocalParameters(), role);
+    remoteTransport.start(localTransport.getLocalParameters(), role);
+    const localWatcher = new EventWatcher(t, localTransport, 'statechange');
+    const remoteWatcher = new EventWatcher(t, remoteTransport, 'statechange');
+    await Promise.all([
+      localWatcher.wait_for('statechange').then(() => {
+        assert_equals(localTransport.state, 'connected');
+      }),
+      remoteWatcher.wait_for('statechange').then(() => {
+        assert_equals(remoteTransport.state, 'connected');
+      }),
+    ]);
+  }, `Two RTCIceTransports configured with the ${role} role resolve the ` +
+      'conflict in band and still connect.');
+});
+
</ins><span class="cx"> promise_test(async t => {
</span><del>-  async function waitForConnectedThenSelectedCandidatePairChange(t, transport,
</del><ins>+  async function waitForSelectedCandidatePairChangeThenConnected(t, transport,
</ins><span class="cx">       transportName) {
</span><span class="cx">     const watcher = new EventWatcher(t, transport,
</span><span class="cx">         [ 'statechange', 'selectedcandidatepairchange' ]);
</span><del>-    await watcher.wait_for('statechange');
-    assert_equals(transport.state, 'connected',
-        `${transportName} state should be 'connected'`);
</del><span class="cx">     await watcher.wait_for('selectedcandidatepairchange');
</span><span class="cx">     const selectedCandidatePair = transport.getSelectedCandidatePair();
</span><span class="cx">     assert_not_equals(selectedCandidatePair, null,
</span><span class="lines">@@ -279,13 +297,16 @@
</span><span class="cx">                 candidate === selectedCandidatePair.remote.candidate),
</span><span class="cx">         `${transportName} selected candidate pair local should be in the ` +
</span><span class="cx">         'list of remote candidates');
</span><ins>+    await watcher.wait_for('statechange');
+    assert_equals(transport.state, 'connected',
+        `${transportName} state should be 'connected'`);
</ins><span class="cx">   }
</span><span class="cx">   const [ localTransport, remoteTransport ] =
</span><span class="cx">       makeGatherAndStartTwoIceTransports(t);
</span><span class="cx">   await Promise.all([
</span><del>-    waitForConnectedThenSelectedCandidatePairChange(t, localTransport,
</del><ins>+    waitForSelectedCandidatePairChangeThenConnected(t, localTransport,
</ins><span class="cx">         'local transport'),
</span><del>-    waitForConnectedThenSelectedCandidatePairChange(t, remoteTransport,
</del><ins>+    waitForSelectedCandidatePairChangeThenConnected(t, remoteTransport,
</ins><span class="cx">         'remote transport'),
</span><span class="cx">   ]);
</span><span class="cx"> }, 'Selected candidate pair changes once the RTCIceTransports connect.');
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionaddIceCandidateexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-addIceCandidate-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-addIceCandidate-expected.txt  2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-addIceCandidate-expected.txt     2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -3,8 +3,8 @@
</span><span class="cx"> FAIL Add ICE candidate before setting remote description should reject with InvalidStateError assert_unreached: Should have rejected: undefined Reached unreachable code
</span><span class="cx"> PASS Add ICE candidate after setting remote description should succeed 
</span><span class="cx"> PASS Add ICE candidate with RTCIceCandidate should succeed 
</span><del>-FAIL Add candidate with only valid sdpMid should succeed promise_test: Unhandled rejection with value: object "OperationError: Expect line: candidate:<candidate-str>"
-FAIL Add candidate with only valid sdpMLineIndex should succeed promise_test: Unhandled rejection with value: object "OperationError: Expect line: candidate:<candidate-str>"
</del><ins>+PASS Add candidate with only valid sdpMid should succeed 
+PASS Add candidate with only valid sdpMLineIndex should succeed 
</ins><span class="cx"> FAIL addIceCandidate with first sdpMid and sdpMLineIndex add candidate to first media stream assert_true: Expect candidate line to be found between media lines m=audio and m=video expected true got false
</span><span class="cx"> FAIL addIceCandidate with second sdpMid and sdpMLineIndex should add candidate to second media stream assert_true: Expect candidate line to be found after media line m=video expected true got false
</span><span class="cx"> FAIL Add candidate for first media stream with null usernameFragment should add candidate to first media stream assert_true: Expect candidate line to be found between media lines m=audio and m=video expected true got false
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionaddIceCandidatehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-addIceCandidate.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-addIceCandidate.html  2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-addIceCandidate.html     2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -61,9 +61,9 @@
</span><span class="cx">   const sessionDesc = { type: 'offer', sdp };
</span><span class="cx"> 
</span><span class="cx">   // valid candidate attributes
</span><del>-  const sdpMid = 'a1';
-  const sdpMLineIndex = 0;
-  const usernameFragment = 'ETEn';
</del><ins>+  const sdpMid1 = 'a1';
+  const sdpMLineIndex1 = 0;
+  const usernameFragment1 = 'ETEn';
</ins><span class="cx"> 
</span><span class="cx">   const sdpMid2 = 'v1';
</span><span class="cx">   const sdpMLineIndex2 = 1;
</span><span class="lines">@@ -138,7 +138,9 @@
</span><span class="cx">     return promise_rejects(t, 'InvalidStateError',
</span><span class="cx">       pc.addIceCandidate({
</span><span class="cx">         candidate: candidateStr1,
</span><del>-        sdpMid, sdpMLineIndex, usernameFragment
</del><ins>+        sdpMid: sdpMid1,
+        sdpMLineIndex: sdpMLineIndex1,
+        usernameFragment: usernameFragment1
</ins><span class="cx">       }));
</span><span class="cx">   }, 'Add ICE candidate before setting remote description should reject with InvalidStateError');
</span><span class="cx"> 
</span><span class="lines">@@ -153,7 +155,9 @@
</span><span class="cx">     return pc.setRemoteDescription(sessionDesc)
</span><span class="cx">     .then(() => pc.addIceCandidate({
</span><span class="cx">       candidate: candidateStr1,
</span><del>-      sdpMid, sdpMLineIndex, usernameFragment
</del><ins>+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      usernameFragement: usernameFragment1
</ins><span class="cx">     }));
</span><span class="cx">   }, 'Add ICE candidate after setting remote description should succeed');
</span><span class="cx"> 
</span><span class="lines">@@ -165,7 +169,9 @@
</span><span class="cx">     return pc.setRemoteDescription(sessionDesc)
</span><span class="cx">     .then(() => pc.addIceCandidate(new RTCIceCandidate({
</span><span class="cx">       candidate: candidateStr1,
</span><del>-      sdpMid, sdpMLineIndex, usernameFragment
</del><ins>+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      usernameFragement: usernameFragment1
</ins><span class="cx">     })));
</span><span class="cx">   }, 'Add ICE candidate with RTCIceCandidate should succeed');
</span><span class="cx"> 
</span><span class="lines">@@ -175,7 +181,9 @@
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><span class="cx"> 
</span><span class="cx">     return pc.setRemoteDescription(sessionDesc)
</span><del>-      .then(() => pc.addIceCandidate({ sdpMid }));
</del><ins>+      .then(() => pc.addIceCandidate({
+        candidate: candidateStr1,
+        sdpMid: sdpMid1 }));
</ins><span class="cx">   }, 'Add candidate with only valid sdpMid should succeed');
</span><span class="cx"> 
</span><span class="cx">   promise_test(t => {
</span><span class="lines">@@ -184,7 +192,9 @@
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><span class="cx"> 
</span><span class="cx">     return pc.setRemoteDescription(sessionDesc)
</span><del>-      .then(() => pc.addIceCandidate({ sdpMLineIndex }));
</del><ins>+      .then(() => pc.addIceCandidate({
+        candidate: candidateStr1,
+        sdpMLineIndex: sdpMLineIndex1 }));
</ins><span class="cx">   }, 'Add candidate with only valid sdpMLineIndex should succeed');
</span><span class="cx"> 
</span><span class="cx">   /*
</span><span class="lines">@@ -206,7 +216,9 @@
</span><span class="cx">     return pc.setRemoteDescription(sessionDesc)
</span><span class="cx">     .then(() => pc.addIceCandidate({
</span><span class="cx">       candidate: candidateStr1,
</span><del>-      sdpMid, sdpMLineIndex, usernameFragment
</del><ins>+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      usernameFragement: usernameFragment1
</ins><span class="cx">     }))
</span><span class="cx">     .then(() => {
</span><span class="cx">       assert_candidate_line_between(pc.remoteDescription.sdp,
</span><span class="lines">@@ -240,8 +252,9 @@
</span><span class="cx">     return pc.setRemoteDescription(sessionDesc)
</span><span class="cx">     .then(() => pc.addIceCandidate({
</span><span class="cx">       candidate: candidateStr1,
</span><del>-      sdpMid, sdpMLineIndex,
-      usernameFragment: null
</del><ins>+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      ufrag: null
</ins><span class="cx">     }))
</span><span class="cx">     .then(() => {
</span><span class="cx">       assert_candidate_line_between(pc.remoteDescription.sdp,
</span><span class="lines">@@ -257,7 +270,9 @@
</span><span class="cx">     return pc.setRemoteDescription(sessionDesc)
</span><span class="cx">     .then(() => pc.addIceCandidate({
</span><span class="cx">       candidate: candidateStr1,
</span><del>-      sdpMid, sdpMLineIndex, usernameFragment
</del><ins>+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      usernameFragement: usernameFragment1
</ins><span class="cx">     }))
</span><span class="cx">     .then(() => pc.addIceCandidate({
</span><span class="cx">       candidate: candidateStr2,
</span><span class="lines">@@ -296,12 +311,15 @@
</span><span class="cx">     return pc.setRemoteDescription(sessionDesc)
</span><span class="cx">     .then(() => pc.addIceCandidate({
</span><span class="cx">       candidate: candidateStr1,
</span><del>-      sdpMid, sdpMLineIndex, usernameFragment
</del><ins>+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      usernameFragement: usernameFragment1
</ins><span class="cx">     }))
</span><span class="cx">     .then(() => pc.addIceCandidate({
</span><span class="cx">       candidate: '',
</span><del>-      sdpMid, sdpMLineIndex,
-      usernameFragment
</del><ins>+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      usernameFragement: usernameFragment1
</ins><span class="cx">     }))
</span><span class="cx">     .then(() => {
</span><span class="cx">       assert_candidate_line_between(pc.remoteDescription.sdp,
</span><span class="lines">@@ -404,7 +422,9 @@
</span><span class="cx">       promise_rejects(t, 'OperationError',
</span><span class="cx">         pc.addIceCandidate({
</span><span class="cx">           candidate: candidateStr1,
</span><del>-          sdpMid: 'invalid', sdpMLineIndex, usernameFragment
</del><ins>+          sdpMid: 'invalid',
+          sdpMLineIndex: sdpMLineIndex1,
+          usernameFragement: usernameFragment1
</ins><span class="cx">         })));
</span><span class="cx">   }, 'Add candidate with invalid sdpMid should reject with OperationError');
</span><span class="cx"> 
</span><span class="lines">@@ -427,7 +447,7 @@
</span><span class="cx">         pc.addIceCandidate({
</span><span class="cx">           candidate: candidateStr1,
</span><span class="cx">           sdpMLineIndex: 2,
</span><del>-          usernameFragment
</del><ins>+          usernameFragement: usernameFragment1
</ins><span class="cx">         })));
</span><span class="cx">   }, 'Add candidate with invalid sdpMLineIndex should reject with OperationError');
</span><span class="cx"> 
</span><span class="lines">@@ -441,9 +461,9 @@
</span><span class="cx">     return pc.setRemoteDescription(sessionDesc)
</span><span class="cx">     .then(() => pc.addIceCandidate({
</span><span class="cx">       candidate: candidateStr1,
</span><del>-      sdpMid,
</del><ins>+      sdpMid: sdpMid1,
</ins><span class="cx">       sdpMLineIndex: 2,
</span><del>-      usernameFragment
</del><ins>+      usernameFragement: usernameFragment1
</ins><span class="cx">     }));
</span><span class="cx">   }, 'Invalid sdpMLineIndex should be ignored if valid sdpMid is provided');
</span><span class="cx"> 
</span><span class="lines">@@ -482,8 +502,9 @@
</span><span class="cx">       promise_rejects(t, 'OperationError',
</span><span class="cx">         pc.addIceCandidate({
</span><span class="cx">           candidate: candidateStr1,
</span><del>-          sdpMid, sdpMLineIndex,
-          usernameFragment: 'invalid'
</del><ins>+          sdpMid: sdpMid1,
+          sdpMLineIndex: sdpMLineIndex1,
+          ufrag: 'invalid'
</ins><span class="cx">         })));
</span><span class="cx">   }, 'Add candidate with invalid usernameFragment should reject with OperationError');
</span><span class="cx"> 
</span><span class="lines">@@ -504,7 +525,9 @@
</span><span class="cx">       promise_rejects(t, 'OperationError',
</span><span class="cx">         pc.addIceCandidate({
</span><span class="cx">           candidate: invalidCandidateStr,
</span><del>-          sdpMid, sdpMLineIndex, usernameFragment
</del><ins>+          sdpMid: sdpMid1,
+          sdpMLineIndex: sdpMLineIndex1,
+          usernameFragement: usernameFragment1
</ins><span class="cx">         })));
</span><span class="cx">   }, 'Add candidate with invalid candidate string should reject with OperationError');
</span><span class="cx"> 
</span><span class="lines">@@ -520,7 +543,7 @@
</span><span class="cx">           candidate: candidateStr2,
</span><span class="cx">           sdpMid: sdpMid2,
</span><span class="cx">           sdpMLineIndex: sdpMLineIndex2,
</span><del>-          usernameFragment
</del><ins>+          usernameFragement: usernameFragment1
</ins><span class="cx">         })));
</span><span class="cx">   }, 'Add candidate with sdpMid belonging to different usernameFragment should reject with OperationError');
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionconnectionStateexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-connectionState-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-connectionState-expected.txt  2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-connectionState-expected.txt     2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,4 +1,6 @@
</span><span class="cx"> 
</span><span class="cx"> PASS Initial connectionState should be new 
</span><del>-FAIL connection with one data channel should eventually have connected connection state undefined is not an object (evaluating 'sctpTransport.transport')
</del><ins>+PASS Closing the connection should set connectionState to closed 
+PASS connection with one data channel should eventually have connected connection state 
+FAIL connection with one data channel should eventually have transports in connected state undefined is not an object (evaluating 'sctpTransport.transport')
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionconnectionStatehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-connectionState.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-connectionState.html  2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-connectionState.html     2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -6,7 +6,6 @@
</span><span class="cx"> <script src="RTCPeerConnection-helper.js"></script>
</span><span class="cx"> <script>
</span><span class="cx">   'use strict';
</span><del>-
</del><span class="cx">   // Test is based on the following editor draft:
</span><span class="cx">   // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.htm
</span><span class="cx"> 
</span><span class="lines">@@ -76,6 +75,12 @@
</span><span class="cx">     assert_equals(pc.connectionState, 'new');
</span><span class="cx">   }, 'Initial connectionState should be new');
</span><span class="cx"> 
</span><ins>+  test(t => {
+    const pc = new RTCPeerConnection();
+    pc.close();
+    assert_equals(pc.connectionState, 'closed');
+  }, 'Closing the connection should set connectionState to closed');
+
</ins><span class="cx">   /*
</span><span class="cx">     4.4.3.  RTCPeerConnectionState Enum
</span><span class="cx">       connected
</span><span class="lines">@@ -105,16 +110,42 @@
</span><span class="cx">         pairs and found a connection. If consent checks [RFC7675] subsequently
</span><span class="cx">         fail on all successful candidate pairs, the state transitions to "failed".
</span><span class="cx">    */
</span><ins>+
</ins><span class="cx">   async_test(t => {
</span><span class="cx">     const pc1 = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     const pc2 = new RTCPeerConnection();
</span><ins>+    t.add_cleanup(() => pc2.close());
</ins><span class="cx"> 
</span><ins>+    let had_connecting = false;
+
+    const onConnectionStateChange = t.step_func(() => {
+      const {connectionState} = pc1;
+      if (connectionState === 'connecting') {
+        had_connecting = true;
+      } else if (connectionState === 'connected') {
+        assert_true(had_connecting, "state should pass connecting before reaching connected");
+        t.done();
+      }
+    });
+
+    pc1.createDataChannel('test');
+
+    pc1.addEventListener('connectionstatechange', onConnectionStateChange);
+
+    exchangeIceCandidates(pc1, pc2);
+    doSignalingHandshake(pc1, pc2);
+  }, 'connection with one data channel should eventually have connected connection state');
+
+  async_test(t => {
+    const pc1 = new RTCPeerConnection();
+    t.add_cleanup(() => pc1.close());
+    const pc2 = new RTCPeerConnection();
</ins><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><span class="cx">     const onConnectionStateChange = t.step_func(() => {
</span><del>-      const { connectionState } = pc1;
-      if(connectionState === 'connected') {
</del><ins>+      const {connectionState} = pc1;
+      if (connectionState === 'connected') {
</ins><span class="cx">         const sctpTransport = pc1.sctp;
</span><span class="cx"> 
</span><span class="cx">         const dtlsTransport = sctpTransport.transport;
</span><span class="lines">@@ -132,14 +163,11 @@
</span><span class="cx"> 
</span><span class="cx">     pc1.createDataChannel('test');
</span><span class="cx"> 
</span><del>-    assert_equals(pc1.onconnectionstatechange, null,
-      'Expect connection to have connectionstatechange event');
-
</del><span class="cx">     pc1.addEventListener('connectionstatechange', onConnectionStateChange);
</span><span class="cx"> 
</span><span class="cx">     exchangeIceCandidates(pc1, pc2);
</span><span class="cx">     doSignalingHandshake(pc1, pc2);
</span><del>-  }, 'connection with one data channel should eventually have connected connection state');
</del><ins>+  }, 'connection with one data channel should eventually have transports in connected state');
</ins><span class="cx"> 
</span><span class="cx">   /*
</span><span class="cx">     TODO
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiongetStatshttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-getStats.https-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-getStats.https-expected.txt   2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-getStats.https-expected.txt      2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,4 +1,6 @@
</span><span class="cx"> 
</span><ins>+Harness Error (TIMEOUT), message = null
+
</ins><span class="cx"> PASS getStats() with no argument should succeed 
</span><span class="cx"> PASS getStats(null) should succeed 
</span><span class="cx"> FAIL getStats() with track not added to connection should reject with InvalidAccessError assert_unreached: Should have rejected: undefined Reached unreachable code
</span><span class="lines">@@ -9,7 +11,7 @@
</span><span class="cx"> PASS getStats() with no argument should return stats report containing peer-connection stats on an empty PC 
</span><span class="cx"> FAIL getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats assert_true: Expect statsReport to contain stats object of type outbound-rtp expected true got false
</span><span class="cx"> FAIL getStats() with no argument should return stats for no-stream tracks assert_true: Expect statsReport to contain stats object of type outbound-rtp expected true got false
</span><del>-FAIL getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats assert_true: Expect statsReport to contain stats object of type outbound-rtp expected true got false
-FAIL getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats assert_true: Expect statsReport to contain stats object of type inbound-rtp expected true got false
</del><ins>+FAIL getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.ip to be string expected "string" but got "undefined"
+TIMEOUT getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats Test timed out
</ins><span class="cx"> FAIL getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats assert_unreached: test failed with error: Error: assert_true: Expect dictionary.dataChannelIdentifier to be integer expected true got false Reached unreachable code
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiongetStatshttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html   2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html      2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -173,19 +173,18 @@
</span><span class="cx">         - All stats objects referenced directly or indirectly by the RTCOutboundRTPStreamStats
</span><span class="cx">           objects added.
</span><span class="cx">    */
</span><del>-  promise_test(t => {
-    const pc = new RTCPeerConnection();
-    t.add_cleanup(() => pc.close());
-    return getTrackFromUserMedia('audio')
-    .then(([track, mediaStream]) => {
-      pc.addTrack(track, mediaStream);
</del><ins>+  promise_test(async t => {
+    const pc = createPeerConnectionWithCleanup(t);
+    const pc2 = createPeerConnectionWithCleanup(t);
</ins><span class="cx"> 
</span><del>-      return pc.getStats(track)
-      .then(statsReport => {
-        validateStatsReport(statsReport);
-        assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
-      });
-    });
</del><ins>+    let [track, mediaStream] = await getTrackFromUserMedia('audio');
+    pc.addTrack(track, mediaStream);
+    exchangeIceCandidates(pc, pc2);
+    await doSignalingHandshake(pc, pc2);
+    await listenToIceConnected(pc);
+    const stats = await pc.getStats(track);
+    validateStatsReport(stats);
+    assert_stats_report_has_stats(stats, ['outbound-rtp']);
</ins><span class="cx">   }, `getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats`);
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -197,16 +196,20 @@
</span><span class="cx">         - All stats objects referenced directly or indirectly by the RTCInboundRTPStreamStats
</span><span class="cx">           added.
</span><span class="cx">    */
</span><del>-  promise_test(t => {
-    const pc = new RTCPeerConnection();
-    t.add_cleanup(() => pc.close());
-    const transceiver = pc.addTransceiver('audio');
</del><ins>+  promise_test(async t => {
+    const pc = createPeerConnectionWithCleanup(t);
+    const pc2 = createPeerConnectionWithCleanup(t);
</ins><span class="cx"> 
</span><del>-    return pc.getStats(transceiver.receiver.track)
-    .then(statsReport => {
-      validateStatsReport(statsReport);
-      assert_stats_report_has_stats(statsReport, ['inbound-rtp']);
</del><ins>+    let [track, mediaStream] = await getTrackFromUserMedia('audio');
+    pc.addTrack(track, mediaStream);
+    exchangeIceCandidates(pc, pc2);
+    await doSignalingHandshake(pc, pc2);
+    await new Promise(resolve => {
+      pc2.getReceivers()[0].track.addEventListener('unmute', resolve);
</ins><span class="cx">     });
</span><ins>+    const stats = await pc2.getStats(track);
+    validateStatsReport(stats);
+    assert_stats_report_has_stats(stats, ['inbound-rtp']);
</ins><span class="cx">   }, `getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats`);
</span><span class="cx"> 
</span><span class="cx">   /*
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionhelperjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-helper.js (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-helper.js     2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-helper.js        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -182,18 +182,78 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // Helper function for doing one round of offer/answer exchange
</span><del>-// betweeen two local peer connections
-function doSignalingHandshake(localPc, remotePc) {
-  return localPc.createOffer()
-  .then(offer => Promise.all([
-    localPc.setLocalDescription(offer),
-    remotePc.setRemoteDescription(offer)]))
-  .then(() => remotePc.createAnswer())
-  .then(answer => Promise.all([
-    remotePc.setLocalDescription(answer),
-    localPc.setRemoteDescription(answer)]))
</del><ins>+// between two local peer connections
+async function doSignalingHandshake(localPc, remotePc, options={}) {
+  let offer = await localPc.createOffer();
+  // Modify offer if callback has been provided
+  if (options.modifyOffer) {
+    offer = await options.modifyOffer(offer);
+  }
+
+  // Apply offer
+  await localPc.setLocalDescription(offer);
+  await remotePc.setRemoteDescription(offer);
+
+  let answer = await remotePc.createAnswer();
+  // Modify answer if callback has been provided
+  if (options.modifyAnswer) {
+    answer = await options.modifyAnswer(answer);
+  }
+
+  // Apply answer
+  await remotePc.setLocalDescription(answer);
+  await localPc.setRemoteDescription(answer);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// Returns a promise that resolves when |pc.iceConnectionState| is 'connected'
+// or 'completed'.
+function listenToIceConnected(pc) {
+  return new Promise((resolve) => {
+    function isConnected(pc) {
+      return pc.iceConnectionState == 'connected' ||
+            pc.iceConnectionState == 'completed';
+    }
+    if (isConnected(pc)) {
+      resolve();
+      return;
+    }
+    pc.oniceconnectionstatechange = () => {
+      if (isConnected(pc))
+        resolve();
+    };
+  });
+}
+
+// Returns a promise that resolves when |pc.connectionState| is 'connected'.
+function listenToConnected(pc) {
+  return new Promise((resolve) => {
+    if (pc.connectionState == 'connected') {
+      resolve();
+      return;
+    }
+    pc.onconnectionstatechange = () => {
+      if (pc.connectionState == 'connected')
+        resolve();
+    };
+  });
+}
+
+// Resolves when RTP packets have been received.
+function listenForSSRCs(t, receiver) {
+  return new Promise((resolve) => {
+    function listen() {
+      const ssrcs = receiver.getSynchronizationSources();
+      assert_true(ssrcs != undefined);
+      if (ssrcs.length > 0) {
+        resolve(ssrcs);
+        return;
+      }
+      t.step_timeout(listen, 0);
+    };
+    listen();
+  });
+}
+
</ins><span class="cx"> // Helper function to create a pair of connected data channel.
</span><span class="cx"> // On success the promise resolves to an array with two data channels.
</span><span class="cx"> // It does the heavy lifting of performing signaling handshake,
</span><span class="lines">@@ -251,6 +311,8 @@
</span><span class="cx"> 
</span><span class="cx"> // Wait for RTP and RTCP stats to arrive
</span><span class="cx"> async function waitForRtpAndRtcpStats(pc) {
</span><ins>+  // If remote stats are never reported, return after 5 seconds.
+  const startTime = performance.now();
</ins><span class="cx">   while (true) {
</span><span class="cx">     const report = await pc.getStats();
</span><span class="cx">     const stats = [...report.values()].filter(({type}) => type.endsWith("bound-rtp"));
</span><span class="lines">@@ -259,6 +321,9 @@
</span><span class="cx">     if (stats.length && stats.every(({localId, remoteId}) => localId || remoteId)) {
</span><span class="cx">       break;
</span><span class="cx">     }
</span><ins>+    if (performance.now() > startTime + 5000) {
+      break;
+    }
</ins><span class="cx">   }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -290,23 +355,25 @@
</span><span class="cx">   });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// Assert that two ArrayBuffer objects have the same byte values
-function assert_equals_array_buffer(buffer1, buffer2) {
-  assert_true(buffer1 instanceof ArrayBuffer,
-    'Expect buffer to be instance of ArrayBuffer');
</del><ins>+// Assert that two TypedArray or ArrayBuffer objects have the same byte values
+function assert_equals_typed_array(array1, array2) {
+  const [view1, view2] = [array1, array2].map((array) => {
+    if (array instanceof ArrayBuffer) {
+      return new DataView(array);
+    } else {
+      assert_true(array.buffer instanceof ArrayBuffer,
+        'Expect buffer to be instance of ArrayBuffer');
+      return new DataView(array.buffer, array.byteOffset, array.byteLength);
+    }
+  });
</ins><span class="cx"> 
</span><del>-  assert_true(buffer2 instanceof ArrayBuffer,
-    'Expect buffer to be instance of ArrayBuffer');
</del><ins>+  assert_equals(view1.byteLength, view2.byteLength,
+    'Expect both arrays to be of the same byte length');
</ins><span class="cx"> 
</span><del>-  assert_equals(buffer1.byteLength, buffer2.byteLength,
-    'Expect both array buffers to be of the same byte length');
</del><ins>+  const byteLength = view1.byteLength;
</ins><span class="cx"> 
</span><del>-  const byteLength = buffer1.byteLength;
-  const byteArray1 = new Uint8Array(buffer1);
-  const byteArray2 = new Uint8Array(buffer2);
-
-  for(let i=0; i<byteLength; i++) {
-    assert_equals(byteArray1[i], byteArray2[i],
</del><ins>+  for (let i = 0; i < byteLength; ++i) {
+    assert_equals(view1.getUint8(i), view2.getUint8(i),
</ins><span class="cx">       `Expect byte at buffer position ${i} to be equal`);
</span><span class="cx">   }
</span><span class="cx"> }
</span><span class="lines">@@ -473,19 +540,46 @@
</span><span class="cx">   return ontrackPromise;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// The resolver has a |promise| that can be resolved or rejected using |resolve|
</del><ins>+// The resolver extends a |promise| that can be resolved or rejected using |resolve|
</ins><span class="cx"> // or |reject|.
</span><del>-class Resolver {
-  constructor() {
-    let promiseResolve;
-    let promiseReject;
-    this.promise = new Promise(function(resolve, reject) {
-      promiseResolve = resolve;
-      promiseReject = reject;
</del><ins>+class Resolver extends Promise {
+  constructor(executor) {
+    let resolve, reject;
+    super((resolve_, reject_) => {
+      resolve = resolve_;
+      reject = reject_;
+      if (executor) {
+        return executor(resolve_, reject_);
+      }
</ins><span class="cx">     });
</span><del>-    this.resolve = promiseResolve;
-    this.reject = promiseReject;
</del><ins>+
+    this._done = false;
+    this._resolve = resolve;
+    this._reject = reject;
</ins><span class="cx">   }
</span><ins>+
+  /**
+   * Return whether the promise is done (resolved or rejected).
+   */
+  get done() {
+    return this._done;
+  }
+
+  /**
+   * Resolve the promise.
+   */
+  resolve(...args) {
+    this._done = true;
+    return this._resolve(...args);
+  }
+
+  /**
+   * Reject the promise.
+   */
+  reject(...args) {
+    this._done = true;
+    return this._reject(...args);
+  }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function addEventListenerPromise(t, target, type, listener) {
</span><span class="lines">@@ -507,7 +601,7 @@
</span><span class="cx"> async function createTrackAndStreamWithCleanup(t, kind = 'audio') {
</span><span class="cx">   let constraints = {};
</span><span class="cx">   constraints[kind] = true;
</span><del>-  const stream = await navigator.mediaDevices.getUserMedia(constraints);
</del><ins>+  const stream = await getNoiseStream(constraints);
</ins><span class="cx">   const [track] = stream.getTracks();
</span><span class="cx">   t.add_cleanup(() => track.stop());
</span><span class="cx">   return [track, stream];
</span><span class="lines">@@ -521,3 +615,23 @@
</span><span class="cx">   }
</span><span class="cx">   return null;
</span><span class="cx"> }
</span><ins>+
+// Contains a set of values and will yell at you if you try to add a value twice.
+class UniqueSet extends Set {
+  constructor(items) {
+    super();
+    if (items !== undefined) {
+      for (const item of items) {
+        this.add(item);
+      }
+    }
+  }
+
+  add(value, message) {
+    if (message === undefined) {
+      message = `Value '${value}' needs to be unique but it is already in the set`;
+    }
+    assert_true(!this.has(value), message);
+    super.add(value);
+  }
+}
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectioniceConnectionStatehtml"></a>
<div class="delfile"><h4>Deleted: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.html       2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.html  2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,187 +0,0 @@
</span><del>-<!doctype html>
-<meta charset=utf-8>
-<title>RTCPeerConnection.prototype.iceConnectionState</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:
-  // exchangeIceCandidates
-  // doSignalingHandshake
-
-  /*
-    4.3.2.  Interface Definition
-      interface RTCPeerConnection : EventTarget {
-        ...
-        readonly  attribute RTCIceConnectionState  iceConnectionState;
-                  attribute EventHandler           oniceconnectionstatechange;
-      };
-
-    4.4.4 RTCIceConnectionState Enum
-      enum RTCIceConnectionState {
-        "new",
-        "checking",
-        "connected",
-        "completed",
-        "failed",
-        "disconnected",
-        "closed"
-      };
-
-    5.6.  RTCIceTransport Interface
-      interface RTCIceTransport {
-        readonly attribute RTCIceTransportState state;
-                 attribute EventHandler         onstatechange;
-
-        ...
-      };
-
-      enum RTCIceTransportState {
-        "new",
-        "checking",
-        "connected",
-        "completed",
-        "failed",
-        "disconnected",
-        "closed"
-      };
-   */
-
-  /*
-    4.4.4 RTCIceConnectionState Enum
-      new
-        Any of the RTCIceTransports are in the new state and none of them
-        are in the checking, failed or disconnected state, or all
-        RTCIceTransport s are in the closed state.
-   */
-  test(t => {
-    const pc = new RTCPeerConnection();
-    assert_equals(pc.iceConnectionState, 'new');
-  }, 'Initial iceConnectionState should be new');
-
-  /*
-    4.4.4 RTCIceConnectionState Enum
-      checking
-        Any of the RTCIceTransport s are in the checking state and none of
-        them are in the failed or disconnected state.
-
-      connected
-        All RTCIceTransport s are in the connected, completed or closed state
-        and at least one of them is in the connected state.
-
-      completed
-        All RTCIceTransport s are in the completed or closed state and at least
-        one of them is in the completed state.
-
-      checking
-        The RTCIceTransport has received at least one remote candidate and
-        is checking candidate pairs and has either not yet found a connection
-        or consent checks [RFC7675] have failed on all previously successful
-        candidate pairs. In addition to checking, it may also still be gathering.
-
-    5.6.  enum RTCIceTransportState
-      connected
-        The RTCIceTransport has found a usable connection, but is still
-        checking other candidate pairs to see if there is a better connection.
-        It may also still be gathering and/or waiting for additional remote
-        candidates. If consent checks [RFC7675] fail on the connection in use,
-        and there are no other successful candidate pairs available, then the
-        state transitions to "checking" (if there are candidate pairs remaining
-        to be checked) or "disconnected" (if there are no candidate pairs to
-        check, but the peer is still gathering and/or waiting for additional
-        remote candidates).
-
-      completed
-        The RTCIceTransport has finished gathering, received an indication that
-        there are no more remote candidates, finished checking all candidate
-        pairs and found a connection. If consent checks [RFC7675] subsequently
-        fail on all successful candidate pairs, the state transitions to "failed".
-   */
-  async_test(t => {
-    const pc1 = new RTCPeerConnection();
-    t.add_cleanup(() => pc1.close());
-    const pc2 = new RTCPeerConnection();
-
-    t.add_cleanup(() => pc2.close());
-
-    const onIceConnectionStateChange = t.step_func(() => {
-      const { iceConnectionState } = pc1;
-
-      if(iceConnectionState === 'checking') {
-        const iceTransport = pc1.sctp.transport.transport;
-
-        assert_equals(iceTransport.state, 'checking',
-          'Expect ICE transport to be in checking state when iceConnectionState is checking');
-
-      } else if(iceConnectionState === 'connected') {
-        const iceTransport = pc1.sctp.transport.transport;
-
-        assert_equals(iceTransport.state, 'connected',
-          'Expect ICE transport to be in connected state when iceConnectionState is connected');
-
-      } else if(iceConnectionState === 'completed') {
-        const iceTransport = pc1.sctp.transport.transport;
-
-        assert_equals(iceTransport.state, 'completed',
-          'Expect ICE transport to be in connected state when iceConnectionState is completed');
-      }
-    });
-
-    pc1.createDataChannel('test');
-
-    assert_equals(pc1.oniceconnectionstatechange, null,
-      'Expect connection to have iceconnectionstatechange event');
-
-    pc1.addEventListener('iceconnectionstatechange', onIceConnectionStateChange);
-
-    exchangeIceCandidates(pc1, pc2);
-    doSignalingHandshake(pc1, pc2);
-  }, 'connection with one data channel should eventually have connected connection state');
-
-  /*
-    TODO
-    4.4.4 RTCIceConnectionState Enum
-      failed
-        Any of the RTCIceTransport s are in the failed state.
-
-      disconnected
-        Any of the RTCIceTransport s are in the disconnected state and none of
-        them are in the failed state.
-
-      closed
-        The RTCPeerConnection object's [[ isClosed]] slot is true.
-
-    5.6.  enum RTCIceTransportState
-      new
-        The RTCIceTransport is gathering candidates and/or waiting for
-        remote candidates to be supplied, and has not yet started checking.
-
-      failed
-        The RTCIceTransport has finished gathering, received an indication that
-        there are no more remote candidates, finished checking all candidate pairs,
-        and all pairs have either failed connectivity checks or have lost consent.
-
-      disconnected
-        The ICE Agent has determined that connectivity is currently lost for this
-        RTCIceTransport . This is more aggressive than failed, and may trigger
-        intermittently (and resolve itself without action) on a flaky network.
-        The way this state is determined is implementation dependent.
-
-        Examples include:
-          Losing the network interface for the connection in use.
-          Repeatedly failing to receive a response to STUN requests.
-
-        Alternatively, the RTCIceTransport has finished checking all existing
-        candidates pairs and failed to find a connection (or consent checks
-        [RFC7675] once successful, have now failed), but it is still gathering
-        and/or waiting for additional remote candidates.
-
-      closed
-        The RTCIceTransport has shut down and is no longer responding to STUN requests.
-   */
-</script>
</del></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectioniceConnectionStatehttpsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.https-expected.txt (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.https-expected.txt                         (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.https-expected.txt    2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+
+PASS Initial iceConnectionState should be new 
+PASS Closing the connection should set iceConnectionState to closed 
+PASS connection with one data channel should eventually have connected or completed connection state 
+FAIL connection with one data channel should eventually have connected connection state undefined is not an object (evaluating 'pc1.sctp.transport')
+PASS ICE can connect in a recvonly usecase 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectioniceConnectionStatehttpshtmlfromrev243040trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectioniceConnectionStatehtml"></a>
<div class="copfile"><h4>Copied: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.https.html (from rev 243040, trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.html) (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.https.html                         (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.https.html    2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,246 @@
</span><ins>+<!doctype html>
+<meta charset=utf-8>
+<title>RTCPeerConnection.prototype.iceConnectionState</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:
+  // exchangeIceCandidates
+  // doSignalingHandshake
+
+  /*
+    4.3.2.  Interface Definition
+      interface RTCPeerConnection : EventTarget {
+        ...
+        readonly  attribute RTCIceConnectionState  iceConnectionState;
+                  attribute EventHandler           oniceconnectionstatechange;
+      };
+
+    4.4.4 RTCIceConnectionState Enum
+      enum RTCIceConnectionState {
+        "new",
+        "checking",
+        "connected",
+        "completed",
+        "failed",
+        "disconnected",
+        "closed"
+      };
+
+    5.6.  RTCIceTransport Interface
+      interface RTCIceTransport {
+        readonly attribute RTCIceTransportState state;
+                 attribute EventHandler         onstatechange;
+
+        ...
+      };
+
+      enum RTCIceTransportState {
+        "new",
+        "checking",
+        "connected",
+        "completed",
+        "failed",
+        "disconnected",
+        "closed"
+      };
+   */
+
+  /*
+    4.4.4 RTCIceConnectionState Enum
+      new
+        Any of the RTCIceTransports are in the new state and none of them
+        are in the checking, failed or disconnected state, or all
+        RTCIceTransport s are in the closed state.
+   */
+  test(t => {
+    const pc = new RTCPeerConnection();
+    assert_equals(pc.iceConnectionState, 'new');
+  }, 'Initial iceConnectionState should be new');
+
+  test(t => {
+    const pc = new RTCPeerConnection();
+    pc.close();
+    assert_equals(pc.iceConnectionState, 'closed');
+  }, 'Closing the connection should set iceConnectionState to closed');
+
+  /*
+    4.4.4 RTCIceConnectionState Enum
+      checking
+        Any of the RTCIceTransport s are in the checking state and none of
+        them are in the failed or disconnected state.
+
+      connected
+        All RTCIceTransport s are in the connected, completed or closed state
+        and at least one of them is in the connected state.
+
+      completed
+        All RTCIceTransport s are in the completed or closed state and at least
+        one of them is in the completed state.
+
+      checking
+        The RTCIceTransport has received at least one remote candidate and
+        is checking candidate pairs and has either not yet found a connection
+        or consent checks [RFC7675] have failed on all previously successful
+        candidate pairs. In addition to checking, it may also still be gathering.
+
+    5.6.  enum RTCIceTransportState
+      connected
+        The RTCIceTransport has found a usable connection, but is still
+        checking other candidate pairs to see if there is a better connection.
+        It may also still be gathering and/or waiting for additional remote
+        candidates. If consent checks [RFC7675] fail on the connection in use,
+        and there are no other successful candidate pairs available, then the
+        state transitions to "checking" (if there are candidate pairs remaining
+        to be checked) or "disconnected" (if there are no candidate pairs to
+        check, but the peer is still gathering and/or waiting for additional
+        remote candidates).
+
+      completed
+        The RTCIceTransport has finished gathering, received an indication that
+        there are no more remote candidates, finished checking all candidate
+        pairs and found a connection. If consent checks [RFC7675] subsequently
+        fail on all successful candidate pairs, the state transitions to "failed".
+   */
+  async_test(t => {
+    const pc1 = new RTCPeerConnection();
+    t.add_cleanup(() => pc1.close());
+    const pc2 = new RTCPeerConnection();
+    t.add_cleanup(() => pc2.close());
+
+    let had_checking = false;
+
+    const onIceConnectionStateChange = t.step_func(() => {
+      const {iceConnectionState} = pc1;
+      if (iceConnectionState === 'checking') {
+        had_checking = true;
+      } else if (iceConnectionState === 'connected' ||
+                 iceConnectionState === 'completed') {
+        assert_true(had_checking, 'state should pass checking before' +
+                                  ' reaching connected or completed');
+        t.done();
+      }
+    });
+
+    pc1.createDataChannel('test');
+
+    pc1.addEventListener('iceconnectionstatechange', onIceConnectionStateChange);
+
+    exchangeIceCandidates(pc1, pc2);
+    doSignalingHandshake(pc1, pc2);
+  }, 'connection with one data channel should eventually have connected or ' +
+     'completed connection state');
+
+async_test(t => {
+    const pc1 = new RTCPeerConnection();
+    t.add_cleanup(() => pc1.close());
+    const pc2 = new RTCPeerConnection();
+
+    t.add_cleanup(() => pc2.close());
+
+    const onIceConnectionStateChange = t.step_func(() => {
+      const { iceConnectionState } = pc1;
+
+      if(iceConnectionState === 'checking') {
+        const iceTransport = pc1.sctp.transport.transport;
+
+        assert_equals(iceTransport.state, 'checking',
+          'Expect ICE transport to be in checking state when' +
+          ' iceConnectionState is checking');
+
+      } else if(iceConnectionState === 'connected') {
+        const iceTransport = pc1.sctp.transport.transport;
+
+        assert_equals(iceTransport.state, 'connected',
+          'Expect ICE transport to be in connected state when' +
+          ' iceConnectionState is connected');
+
+      } else if(iceConnectionState === 'completed') {
+        const iceTransport = pc1.sctp.transport.transport;
+
+        assert_equals(iceTransport.state, 'completed',
+          'Expect ICE transport to be in connected state when' +
+          ' iceConnectionState is completed');
+      }
+    });
+
+    pc1.createDataChannel('test');
+
+    assert_equals(pc1.oniceconnectionstatechange, null,
+      'Expect connection to have iceconnectionstatechange event');
+
+    pc1.addEventListener('iceconnectionstatechange', onIceConnectionStateChange);
+
+    exchangeIceCandidates(pc1, pc2);
+    doSignalingHandshake(pc1, pc2);
+  }, 'connection with one data channel should eventually ' +
+     'have connected connection state');
+
+  promise_test(async t => {
+    const caller = new RTCPeerConnection();
+    t.add_cleanup(() => caller.close());
+    const callee = new RTCPeerConnection();
+    t.add_cleanup(() => callee.close());
+
+    caller.addTransceiver('audio', {direction:'recvonly'});
+    const stream = await navigator.mediaDevices.getUserMedia({audio:true});
+    const [track] = stream.getTracks();
+    callee.addTrack(track, stream);
+    exchangeIceCandidates(caller, callee);
+    await doSignalingHandshake(caller, callee);
+
+    assert_equals(caller.getTransceivers().length, 1);
+    const [transceiver] = caller.getTransceivers();
+    assert_equals(transceiver.currentDirection, 'recvonly');
+
+    await listenToIceConnected(caller);
+  }, 'ICE can connect in a recvonly usecase');
+
+  /*
+    TODO
+    4.4.4 RTCIceConnectionState Enum
+      failed
+        Any of the RTCIceTransport s are in the failed state.
+
+      disconnected
+        Any of the RTCIceTransport s are in the disconnected state and none of
+        them are in the failed state.
+
+      closed
+        The RTCPeerConnection object's [[ isClosed]] slot is true.
+
+    5.6.  enum RTCIceTransportState
+      new
+        The RTCIceTransport is gathering candidates and/or waiting for
+        remote candidates to be supplied, and has not yet started checking.
+
+      failed
+        The RTCIceTransport has finished gathering, received an indication that
+        there are no more remote candidates, finished checking all candidate pairs,
+        and all pairs have either failed connectivity checks or have lost consent.
+
+      disconnected
+        The ICE Agent has determined that connectivity is currently lost for this
+        RTCIceTransport . This is more aggressive than failed, and may trigger
+        intermittently (and resolve itself without action) on a flaky network.
+        The way this state is determined is implementation dependent.
+
+        Examples include:
+          Losing the network interface for the connection in use.
+          Repeatedly failing to receive a response to STUN requests.
+
+        Alternatively, the RTCIceTransport has finished checking all existing
+        candidates pairs and failed to find a connection (or consent checks
+        [RFC7675] once successful, have now failed), but it is still gathering
+        and/or waiting for additional remote candidates.
+
+      closed
+        The RTCIceTransport has shut down and is no longer responding to STUN requests.
+   */
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectioniceGatheringStateexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceGatheringState-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceGatheringState-expected.txt        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceGatheringState-expected.txt   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,7 +1,5 @@
</span><span class="cx"> 
</span><del>-Harness Error (TIMEOUT), message = null
-
</del><span class="cx"> PASS Initial iceGatheringState should be new 
</span><del>-TIMEOUT iceGatheringState should eventually become complete after setLocalDescription Test timed out
</del><ins>+PASS iceGatheringState should eventually become complete after setLocalDescription 
</ins><span class="cx"> FAIL connection with one data channel should eventually have connected connection state undefined is not an object (evaluating 'pc2.sctp.transport')
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectioniceGatheringStatehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceGatheringState.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceGatheringState.html        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceGatheringState.html   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -11,8 +11,9 @@
</span><span class="cx">   // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
</span><span class="cx"> 
</span><span class="cx">   // The following helper functions are called from RTCPeerConnection-helper.js:
</span><ins>+  // doSignalingHandshake
</ins><span class="cx">   // exchangeIceCandidates
</span><del>-  // doSignalingHandshake
</del><ins>+  // generateAudioReceiveOnlyOffer
</ins><span class="cx"> 
</span><span class="cx">   /*
</span><span class="cx">     4.3.2.  Interface Definition
</span><span class="lines">@@ -72,7 +73,7 @@
</span><span class="cx"> 
</span><span class="cx">     pc.addEventListener('icegatheringstatechange', onIceGatheringStateChange);
</span><span class="cx"> 
</span><del>-    pc.createOffer({ offerToReceiveAudio: true })
</del><ins>+    generateAudioReceiveOnlyOffer(pc)
</ins><span class="cx">     .then(offer => pc.setLocalDescription(offer))
</span><span class="cx">     .then(err => t.step_func(err =>
</span><span class="cx">       assert_unreached(`Unhandled rejection ${err.name}: ${err.message}`)));
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiononnegotiationneededexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt      2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt 2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -6,6 +6,6 @@
</span><span class="cx"> PASS addTransceiver() should fire negotiationneeded event 
</span><span class="cx"> FAIL Calling addTransceiver() twice should fire negotiationneeded event once assert_unreached: Pending promise should never be resolved. Instead it is fulfilled with: [object Object] Reached unreachable code
</span><span class="cx"> FAIL Calling both addTransceiver() and createDataChannel() should fire negotiationneeded event once assert_unreached: Pending promise should never be resolved. Instead it is fulfilled with: [object Object] Reached unreachable code
</span><del>-PASS negotiationneeded event should not fire if signaling state is not stable 
</del><ins>+FAIL negotiationneeded event should not fire if signaling state is not stable assert_unreached: Pending promise should never be resolved. Instead it is rejected with: Error: assert_equals: expected "have-local-offer" but got "stable" Reached unreachable code
</ins><span class="cx"> TIMEOUT negotiationneeded event should fire only after signaling state go back to stable Test timed out
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiononnegotiationneededhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onnegotiationneeded.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onnegotiationneeded.html      2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onnegotiationneeded.html 2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -12,6 +12,7 @@
</span><span class="cx"> 
</span><span class="cx">   // The following helper functions are called from RTCPeerConnection-helper.js:
</span><span class="cx">   //   generateAnswer
</span><ins>+  //   generateAudioReceiveOnlyOffer
</ins><span class="cx">   //   test_never_resolve
</span><span class="cx"> 
</span><span class="cx">   // Listen to the negotiationneeded event on a peer connection
</span><span class="lines">@@ -163,10 +164,13 @@
</span><span class="cx">    */
</span><span class="cx">   test_never_resolve(t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><del>-    const negotiated = awaitNegotiation(pc);
</del><ins>+    let negotiated;
</ins><span class="cx"> 
</span><del>-    return pc.createOffer({ offerToReceiveAudio: true })
-    .then(offer => pc.setLocalDescription(offer))
</del><ins>+    return generateAudioReceiveOnlyOffer(pc)
+    .then(offer => {
+      pc.setLocalDescription(offer);
+      negotiated = awaitNegotiation(pc);
+    })
</ins><span class="cx">     .then(() => negotiated)
</span><span class="cx">     .then(({nextPromise}) => {
</span><span class="cx">       assert_equals(pc.signalingState, 'have-local-offer');
</span><span class="lines">@@ -183,22 +187,21 @@
</span><span class="cx">         2.  If connection's [[NegotiationNeeded]] slot is false, abort these steps.
</span><span class="cx">         3.  Fire a simple event named negotiationneeded at connection.
</span><span class="cx">    */
</span><del>-  promise_test(t => {
</del><ins>+  promise_test(async t => {
</ins><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx"> 
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><span class="cx"> 
</span><del>-    return assert_first_promise_fulfill_after_second(
-      awaitNegotiation(pc),
-      pc.createOffer({ offerToReceiveAudio: true })
-      .then(offer =>
-        pc.setLocalDescription(offer)
-        .then(() => {
-          pc.createDataChannel('test');
-          return generateAnswer(offer);
-        }))
-      .then(answer => pc.setRemoteDescription(answer)),
-      'Expect negotiationneeded promise to resolve after pc has set remote answer and go back to stable state');
</del><ins>+    pc.addTransceiver('audio');
+    const offer = await pc.createOffer();
+    await pc.setLocalDescription(offer);
+    let fired = false;
+    pc.onnegotiationneeded = e => fired = true;
+    pc.createDataChannel('test');
+    const answer = await generateAnswer(offer);
+    await pc.setRemoteDescription(answer);
+    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);
</ins><span class="cx">   }, 'negotiationneeded event should fire only after signaling state go back to stable');
</span><span class="cx"> 
</span><span class="cx">   /*
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiononsignalingstatechangedhttpsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https-expected.txt (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https-expected.txt                            (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https-expected.txt       2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,3 @@
</span><ins>+
+PASS RTCPeerConnection onsignalingstatechanged 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiononsignalingstatechangedhttpshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https.html (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https.html                            (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https.html       2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+<!doctype html>
+<meta charset=utf-8>
+<title>RTCPeerConnection onsignalingstatechanged</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="RTCPeerConnection-helper.js"></script>
+<script>
+
+promise_test(async t => {
+  const [track] = (await navigator.mediaDevices.getUserMedia({video: true})).getTracks();
+  t.add_cleanup(() => track.stop());
+  const pc1 = new RTCPeerConnection();
+  t.add_cleanup(() => pc1.close());
+  const pc2 = new RTCPeerConnection();
+  t.add_cleanup(() => pc2.close());
+  pc1.addTrack(track, new MediaStream());
+  await pc1.setLocalDescription(await pc1.createOffer());
+  await pc2.setRemoteDescription(pc1.localDescription);
+  const signalingStateChangeResolver = new Resolver();
+  pc2.onsignalingstatechange = t.step_func(e => {
+    const transceiver = pc2.getTransceivers()[0];
+    assert_equals(pc2.signalingState, "stable");
+    assert_equals(transceiver.currentDirection, "recvonly");
+    signalingStateChangeResolver.resolve();
+  });
+  await pc2.setLocalDescription(await pc2.createAnswer());
+  await signalingStateChangeResolver;
+});
+
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionremotetrackmutehttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-remote-track-mute.https-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-remote-track-mute.https-expected.txt  2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-remote-track-mute.https-expected.txt     2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -2,7 +2,7 @@
</span><span class="cx"> Harness Error (TIMEOUT), message = null
</span><span class="cx"> 
</span><span class="cx"> FAIL ontrack: track goes from muted to unmuted assert_true: track is muted in ontrack expected true got false
</span><del>-PASS Changing transceiver direction to 'inactive' mutes the remote track 
-PASS Changing transceiver direction to 'sendrecv' unmutes the remote track 
-TIMEOUT pc.close() mutes remote tracks Test timed out
</del><ins>+TIMEOUT Changing transceiver direction to 'inactive' mutes the remote track Test timed out
+NOTRUN Changing transceiver direction to 'sendrecv' unmutes the remote track 
+NOTRUN pc.close() mutes remote tracks 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionremotetrackmutehttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-remote-track-mute.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-remote-track-mute.https.html  2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-remote-track-mute.https.html     2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx">     });
</span><span class="cx">   });
</span><span class="cx">   await exchangeOfferAnswer(pc1, pc2);
</span><del>-  await unmuteResolver.promise;
</del><ins>+  await unmuteResolver;
</ins><span class="cx"> }, 'ontrack: track goes from muted to unmuted');
</span><span class="cx"> 
</span><span class="cx"> promise_test(async t => {
</span><span class="lines">@@ -50,9 +50,13 @@
</span><span class="cx">   exchangeIceCandidates(pc1, pc2);
</span><span class="cx"> 
</span><span class="cx">   const e = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
</span><ins>+  // Need to wait for the initial unmute event before renegotiating, otherwise
+  // there will be no transition from unmuted->muted.
+  const muteWatcher = new EventWatcher(t, e.track, ['mute', 'unmute']);
+  const unmutePromise = muteWatcher.wait_for('unmute');
</ins><span class="cx">   await exchangeAnswer(pc1, pc2);
</span><ins>+  await unmutePromise;
</ins><span class="cx"> 
</span><del>-  const muteWatcher = new EventWatcher(t, e.track, ['mute']);
</del><span class="cx">   const mutePromise = muteWatcher.wait_for('mute');
</span><span class="cx">   localTransceiver.direction = 'inactive';
</span><span class="cx">   await exchangeOfferAnswer(pc1, pc2);
</span><span class="lines">@@ -88,8 +92,13 @@
</span><span class="cx">   exchangeIceCandidates(pc1, pc2);
</span><span class="cx"> 
</span><span class="cx">   const e = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
</span><ins>+  // Need to wait for the initial unmute event before closing, otherwise
+  // there will be no transition from unmuted->muted.
+  const muteWatcher = new EventWatcher(t, e.track, ['mute', 'unmute']);
+  const unmutePromise = muteWatcher.wait_for('unmute');
</ins><span class="cx">   await exchangeAnswer(pc1, pc2);
</span><del>-  const muteWatcher = new EventWatcher(t, e.track, ['mute']);
</del><ins>+  await unmutePromise;
+
</ins><span class="cx">   const mutePromise = muteWatcher.wait_for('mute');
</span><span class="cx">   pc2.close();
</span><span class="cx">   await mutePromise;
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionremoveTrackhttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-removeTrack.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-removeTrack.https.html        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-removeTrack.https.html   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -61,6 +61,7 @@
</span><span class="cx"> 
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><ins>+    t.add_cleanup(() => pc.close());
</ins><span class="cx">     const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</span><span class="cx">     t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track] = stream.getTracks();
</span><span class="lines">@@ -92,6 +93,7 @@
</span><span class="cx">    */
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><ins>+    t.add_cleanup(() => pc.close());
</ins><span class="cx">     const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</span><span class="cx">     t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track] = stream.getTracks();
</span><span class="lines">@@ -99,6 +101,7 @@
</span><span class="cx">     const { sender } = transceiver;
</span><span class="cx"> 
</span><span class="cx">     const pc2 = new RTCPeerConnection();
</span><ins>+    t.add_cleanup(() => pc2.close());
</ins><span class="cx">     assert_throws('InvalidAccessError', () => pc2.removeTrack(sender));
</span><span class="cx">   }, 'addTransceiver - Calling removeTrack on different connection should throw InvalidAccessError');
</span><span class="cx"> 
</span><span class="lines">@@ -112,6 +115,7 @@
</span><span class="cx">     const sender = pc.addTrack(track, stream);
</span><span class="cx"> 
</span><span class="cx">     const pc2 = new RTCPeerConnection();
</span><ins>+    t.add_cleanup(() => pc2.close());
</ins><span class="cx">     assert_throws('InvalidAccessError', () => pc2.removeTrack(sender));
</span><span class="cx">   }, 'addTrack - Calling removeTrack on different connection should throw InvalidAccessError')
</span><span class="cx"> 
</span><span class="lines">@@ -121,6 +125,7 @@
</span><span class="cx">    */
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><ins>+    t.add_cleanup(() => pc.close());
</ins><span class="cx">     const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</span><span class="cx">     t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track] = stream.getTracks();
</span><span class="lines">@@ -175,7 +180,7 @@
</span><span class="cx">     const offer = await caller.createOffer();
</span><span class="cx">     await caller.setLocalDescription(offer);
</span><span class="cx">     await callee.setRemoteDescription(offer);
</span><del>-    callee.addTrack(track);
</del><ins>+    callee.addTrack(track, stream);
</ins><span class="cx">     const answer = await callee.createAnswer();
</span><span class="cx">     await callee.setLocalDescription(answer);
</span><span class="cx">     await caller.setRemoteDescription(answer);
</span><span class="lines">@@ -244,7 +249,7 @@
</span><span class="cx">     const offer = await caller.createOffer();
</span><span class="cx">     await caller.setLocalDescription(offer);
</span><span class="cx">     await callee.setRemoteDescription(offer);
</span><del>-    callee.addTrack(track);
</del><ins>+    callee.addTrack(track, stream);
</ins><span class="cx">     const answer = await callee.createAnswer();
</span><span class="cx">     await callee.setLocalDescription(answer);
</span><span class="cx">     await caller.setRemoteDescription(answer);
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionanswerexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt       2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt  2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> 
</span><span class="cx"> PASS setLocalDescription() with valid answer should succeed 
</span><span class="cx"> FAIL setLocalDescription() with type answer and null sdp should use lastAnswer generated from createAnswer promise_test: Unhandled rejection with value: object "OperationError: Expect line: v="
</span><del>-FAIL setLocalDescription() with answer not created by own createAnswer() should reject with InvalidModificationError assert_throws: function "function () { throw e }" threw object "OperationError: Failed to set local answer sdp: Failed to apply the description for 0: Local fingerprint does not match identity. Expected: sha-256 FD:12:D4:3F:20:8C:37:A8:9A:C0:CB:03:84:DF:97:20:40:24:C8:DB:B8:88:6C:8D:99:B6:25:48:5C:29:1E:0B Got: sha-256 CC:EB:A3:0C:D3:6C:7C:66:8B:E2:C8:A7:7B:00:92:56:A6:C8:C9:3E:D8:B9:CB:D0:5A:C9:7F:AE:10:4E:C7:CA" that is not a DOMException InvalidModificationError: property "code" is equal to 0, expected 13
</del><ins>+FAIL setLocalDescription() with answer not created by own createAnswer() should reject with InvalidModificationError assert_throws: function "function () { throw e }" threw object "OperationError: Failed to set local answer sdp: Failed to apply the description for 0: Local fingerprint does not match identity. Expected: sha-256 B8:FF:F5:1A:10:AE:9F:0F:19:5C:02:FC:AB:BD:65:CB:5A:EB:DC:70:C9:D9:6C:96:21:2D:68:88:A3:D8:4E:22 Got: sha-256 1F:7E:2D:05:21:41:BE:F0:4C:70:43:EC:E6:E1:79:F1:D9:BD:36:F7:63:5E:63:88:29:22:49:AB:42:1C:F2:D8" that is not a DOMException InvalidModificationError: property "code" is equal to 0, expected 13
</ins><span class="cx"> PASS Calling setLocalDescription(answer) from stable state should reject with InvalidStateError 
</span><span class="cx"> PASS Calling setLocalDescription(answer) from have-local-offer state should reject with InvalidStateError 
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionofferexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> 
</span><span class="cx"> PASS setLocalDescription with valid offer should succeed 
</span><span class="cx"> FAIL setLocalDescription with type offer and null sdp should use lastOffer generated from createOffer promise_test: Unhandled rejection with value: object "OperationError: Expect line: v="
</span><del>-FAIL setLocalDescription() with offer not created by own createOffer() should reject with InvalidModificationError assert_throws: function "function () { throw e }" threw object "OperationError: Failed to set local offer sdp: Failed to apply the description for 0: Local fingerprint does not match identity. Expected: sha-256 55:AE:C9:0F:29:DE:0A:3F:C9:E9:D5:F5:54:FB:67:74:DB:2E:A8:40:8E:A0:22:7E:BE:DA:57:F9:53:1B:27:3E Got: sha-256 3A:DD:42:84:B0:04:62:C1:58:6B:DE:C5:D1:91:45:B8:87:57:26:31:C0:E8:40:91:36:3B:E8:7B:15:EF:F7:5D" that is not a DOMException InvalidModificationError: property "code" is equal to 0, expected 13
</del><ins>+FAIL setLocalDescription() with offer not created by own createOffer() should reject with InvalidModificationError assert_throws: function "function () { throw e }" threw object "OperationError: Failed to set local offer sdp: Failed to apply the description for 0: Local fingerprint does not match identity. Expected: sha-256 E6:E8:76:7F:DE:42:8F:0E:00:46:2E:18:43:C7:6F:85:04:B8:BE:C7:18:39:8E:12:1F:69:24:2C:26:0F:DA:A4 Got: sha-256 FC:1E:43:7D:F6:B9:B2:57:2E:FE:F4:12:4F:17:EC:20:DB:0F:70:A7:72:10:84:4D:10:3B:8B:D1:12:0C:80:FA" that is not a DOMException InvalidModificationError: property "code" is equal to 0, expected 13
</ins><span class="cx"> FAIL Set created offer other than last offer should reject with InvalidModificationError assert_unreached: Should have rejected: undefined Reached unreachable code
</span><span class="cx"> PASS Creating and setting offer multiple times should succeed 
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionrollbackhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-rollback.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-rollback.html     2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-rollback.html        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -12,6 +12,7 @@
</span><span class="cx"> 
</span><span class="cx">   // The following helper functions are called from RTCPeerConnection-helper.js:
</span><span class="cx">   //   assert_session_desc_similar
</span><ins>+  //   generateAudioReceiveOnlyOffer
</ins><span class="cx"> 
</span><span class="cx">   /*
</span><span class="cx">     4.3.2.  Interface Definition
</span><span class="lines">@@ -105,7 +106,7 @@
</span><span class="cx">   promise_test(t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><del>-    return pc.createOffer({ offerToReceiveAudio: true })
</del><ins>+    return generateAudioReceiveOnlyOffer(pc)
</ins><span class="cx">     .then(offer =>
</span><span class="cx">       pc.setRemoteDescription(offer)
</span><span class="cx">       .then(() => pc.createAnswer()))
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetLocalDescriptionhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription.html      2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription.html 2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -72,29 +72,55 @@
</span><span class="cx">         })));
</span><span class="cx">   }, 'Calling createOffer() and setLocalDescription() again after one round of local-offer/remote-answer should succeed');
</span><span class="cx"> 
</span><del>-  promise_test(t => {
-    const pc = new RTCPeerConnection();
-    t.add_cleanup(() => pc.close());
</del><ins>+  promise_test(async t => {
+    const pc1 = new RTCPeerConnection();
+    t.add_cleanup(() => pc1.close());
</ins><span class="cx"> 
</span><ins>+    const pc2 = new RTCPeerConnection();
+    t.add_cleanup(() => pc2.close());
+
</ins><span class="cx">     const states = [];
</span><del>-    pc.addEventListener('signalingstatechange', () => states.push(pc.signalingState));
</del><ins>+    pc1.addEventListener('signalingstatechange', () => states.push(pc1.signalingState));
</ins><span class="cx"> 
</span><del>-    return generateDataChannelOffer(pc)
-    .then(offer => pc.setRemoteDescription(offer))
-    .then(() => pc.createAnswer())
-    .then(answer =>
-      pc.setLocalDescription(answer)
-      .then(() => generateVideoReceiveOnlyOffer(pc))
-      .then(offer =>
-        pc.setLocalDescription(offer)
-        .then(() => {
-          assert_equals(pc.signalingState, 'have-local-offer');
-          assert_session_desc_similar(pc.localDescription, offer);
-          assert_session_desc_similar(pc.currentLocalDescription, answer);
-          assert_session_desc_similar(pc.pendingLocalDescription, offer);
</del><ins>+    assert_equals(pc1.localDescription, null);
+    assert_equals(pc1.currentLocalDescription, null);
+    assert_equals(pc1.pendingLocalDescription, null);
</ins><span class="cx"> 
</span><del>-          assert_array_equals(states, ['have-remote-offer', 'stable', 'have-local-offer']);
-        })));
</del><ins>+    pc1.createDataChannel('test');
+    const offer = await pc1.createOffer();
+
+    assert_equals(pc1.localDescription, null);
+    assert_equals(pc1.currentLocalDescription, null);
+    assert_equals(pc1.pendingLocalDescription, null);
+
+    await pc1.setLocalDescription(offer);
+
+    assert_session_desc_similar(pc1.localDescription, offer);
+    assert_equals(pc1.currentLocalDescription, null);
+    assert_session_desc_similar(pc1.pendingLocalDescription, offer);
+
+    await pc2.setRemoteDescription(offer);
+    const answer = await pc2.createAnswer();
+    await pc2.setLocalDescription(answer);
+    await pc1.setRemoteDescription(answer);
+
+    assert_equals(pc1.signalingState, 'stable');
+    assert_session_desc_similar(pc1.localDescription, offer);
+    assert_session_desc_similar(pc1.currentLocalDescription, offer);
+    assert_equals(pc1.pendingLocalDescription, null);
+
+    const stream = await getNoiseStream({audio:true});
+    pc2.addTrack(stream.getTracks()[0], stream);
+
+    const reoffer = await pc2.createOffer();
+    await pc2.setLocalDescription(reoffer);
+    await pc1.setRemoteDescription(reoffer);
+    const reanswer = await pc1.createAnswer();
+    await pc1.setLocalDescription(reanswer);
+
+    assert_session_desc_similar(pc1.localDescription, reanswer);
+    assert_session_desc_similar(pc1.currentLocalDescription, reanswer);
+    assert_equals(pc1.pendingLocalDescription, null);
</ins><span class="cx">   }, 'Switching role from answerer to offerer after going back to stable state should succeed');
</span><span class="cx"> 
</span><span class="cx">   promise_test(async t => {
</span><span class="lines">@@ -108,7 +134,7 @@
</span><span class="cx">     };
</span><span class="cx">     await pc.setLocalDescription(offer);
</span><span class="cx">     eventSequence += 'setLocalDescription;';
</span><del>-    await signalingstatechangeResolver.promise;
</del><ins>+    await signalingstatechangeResolver;
</ins><span class="cx">     assert_equals(eventSequence, 'onsignalingstatechange;setLocalDescription;');
</span><span class="cx">   }, 'onsignalingstatechange fires before setLocalDescription resolves');
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionnomsidexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid-expected.txt (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid-expected.txt                              (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid-expected.txt 2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,3 @@
</span><ins>+
+PASS setRemoteDescription with an SDP without a=msid lines triggers ontrack with a default stream. 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionnomsidhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid.html (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid.html                              (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid.html 2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+<!doctype html>
+<meta charset=utf-8>
+<title>RTCPeerConnection.prototype.setRemoteDescription - legacy streams without a=msid lines</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict';
+
+const FINGERPRINT_SHA256 = '00:00:00:00:00:00:00:00:00:00:00:00:00' +
+    ':00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00';
+const ICEUFRAG = 'someufrag';
+const ICEPWD = 'somelongpwdwithenoughrandomness';
+const SDP_BOILERPLATE = 'v=0\r\n' +
+    'o=- 166855176514521964 2 IN IP4 127.0.0.1\r\n' +
+    's=-\r\n' +
+    't=0 0\r\n';
+const MINIMAL_AUDIO_MLINE =
+    'm=audio 9 UDP/TLS/RTP/SAVPF 111\r\n' +
+    'c=IN IP4 0.0.0.0\r\n' +
+    'a=rtcp:9 IN IP4 0.0.0.0\r\n' +
+    'a=ice-ufrag:' + ICEUFRAG + '\r\n' +
+    'a=ice-pwd:' + ICEPWD + '\r\n' +
+    'a=fingerprint:sha-256 ' + FINGERPRINT_SHA256 + '\r\n' +
+    'a=setup:actpass\r\n' +
+    'a=mid:0\r\n' +
+    'a=sendrecv\r\n' +
+    'a=rtcp-mux\r\n' +
+    'a=rtcp-rsize\r\n' +
+    'a=rtpmap:111 opus/48000/2\r\n';
+
+  promise_test(async t => {
+    const pc = new RTCPeerConnection();
+    t.add_cleanup(() => pc.close());
+
+    const haveOntrack = new Promise(r => pc.ontrack = r);
+    await pc.setRemoteDescription({type: 'offer', sdp: SDP_BOILERPLATE + MINIMAL_AUDIO_MLINE});
+    assert_equals((await haveOntrack).streams.length, 1);
+  }, 'setRemoteDescription with an SDP without a=msid lines triggers ontrack with a default stream.');
+
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionofferexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt       2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt  2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> 
</span><span class="cx"> PASS setRemoteDescription with valid offer should succeed 
</span><span class="cx"> PASS setRemoteDescription multiple times should succeed 
</span><del>-FAIL setRemoteDescription multiple times with different offer should succeed assert_false: Expect both session descriptions to have different count of media lines expected false got true
</del><ins>+PASS setRemoteDescription multiple times with different offer should succeed 
</ins><span class="cx"> FAIL setRemoteDescription(offer) with invalid SDP should reject with RTCError assert_equals: Expect error detail field to set to sdp-syntax-error expected (string) "sdp-syntax-error" but got (undefined) undefined
</span><span class="cx"> PASS setRemoteDescription(offer) from have-local-offer state should reject with InvalidStateError 
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionofferhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer.html       2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer.html  2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -12,6 +12,7 @@
</span><span class="cx"> 
</span><span class="cx">   // The following helper functions are called from RTCPeerConnection-helper.js:
</span><span class="cx">   //   assert_session_desc_similar()
</span><ins>+  //   generateAudioReceiveOnlyOffer
</ins><span class="cx"> 
</span><span class="cx">   /*
</span><span class="cx">     4.3.2.  Interface Definition
</span><span class="lines">@@ -115,7 +116,7 @@
</span><span class="cx">     .then(offer1 => {
</span><span class="cx">       return pc1.setLocalDescription(offer1)
</span><span class="cx">        .then(()=> {
</span><del>-        return pc1.createOffer({ offerToReceiveAudio: true })
</del><ins>+        return generateAudioReceiveOnlyOffer(pc1)
</ins><span class="cx">         .then(offer2 => {
</span><span class="cx">           assert_session_desc_not_similar(offer1, offer2);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionrollbackexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-rollback-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-rollback-expected.txt    2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-rollback-expected.txt       2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -2,4 +2,5 @@
</span><span class="cx"> FAIL setRemoteDescription(rollback) in have-remote-offer state should revert to stable state promise_test: Unhandled rejection with value: object "InvalidStateError: Description type incompatible with current signaling state"
</span><span class="cx"> PASS setRemoteDescription(rollback) from stable state should reject with InvalidStateError 
</span><span class="cx"> FAIL setRemoteDescription(rollback) should ignore invalid sdp content and succeed promise_test: Unhandled rejection with value: object "InvalidStateError: Description type incompatible with current signaling state"
</span><ins>+FAIL local offer created before setRemoteDescription(remote offer) then rollback should still be usable promise_test: Unhandled rejection with value: object "InvalidStateError: Description type incompatible with current signaling state"
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionrollbackhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html    2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-rollback.html       2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -11,8 +11,9 @@
</span><span class="cx">   // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
</span><span class="cx"> 
</span><span class="cx">   // The following helper functions are called from RTCPeerConnection-helper.js:
</span><ins>+  //   assert_session_desc_similar
+  //   generateAudioReceiveOnlyOffer
</ins><span class="cx">   //   generateDataChannelOffer
</span><del>-  //   assert_session_desc_similar
</del><span class="cx"> 
</span><span class="cx">   /*
</span><span class="cx">     4.3.2.  Interface Definition
</span><span class="lines">@@ -105,7 +106,7 @@
</span><span class="cx">   promise_test(t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><del>-    return pc.createOffer({ offerToReceiveAudio: true })
</del><ins>+    return generateAudioReceiveOnlyOffer(pc)
</ins><span class="cx">     .then(offer => pc.setRemoteDescription(offer))
</span><span class="cx">     .then(() => pc.setRemoteDescription({
</span><span class="cx">       type: 'rollback',
</span><span class="lines">@@ -113,4 +114,22 @@
</span><span class="cx">     }));
</span><span class="cx">   }, `setRemoteDescription(rollback) should ignore invalid sdp content and succeed`);
</span><span class="cx"> 
</span><ins>+  promise_test(async t => {
+    const pc1 = new RTCPeerConnection();
+    const pc2 = new RTCPeerConnection();
+    t.add_cleanup(() => pc1.close());
+    t.add_cleanup(() => pc2.close());
+
+    // We don't use this right away
+    const offer1 = await pc1.createOffer({offerToReceiveAudio: true});
+
+    // Create offer from pc2, apply and rollback on pc1
+    const offer2 = await pc2.createOffer({offerToReceiveAudio: true});
+    await pc1.setRemoteDescription(offer2);
+    await pc1.setRemoteDescription({type: "rollback"});
+
+    // Then try applying pc1's old offer
+    await pc1.setLocalDescription(offer1);
+  }, `local offer created before setRemoteDescription(remote offer) then rollback should still be usable`);
+
</ins><span class="cx"> </script>
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptiontrackshttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -95,7 +95,7 @@
</span><span class="cx">       ontrackEventResolvers[ontrackEventsFired++].resolve(e);
</span><span class="cx">     });
</span><span class="cx">     await exchangeOffer(caller, callee);
</span><del>-    let firstTrackEvent = await ontrackEventResolvers[0].promise;
</del><ins>+    let firstTrackEvent = await ontrackEventResolvers[0];
</ins><span class="cx">     assert_equals(firstTrackEvent.track.id,
</span><span class="cx">                   localStreams[0].getTracks()[0].id,
</span><span class="cx">                   'First ontrack\'s track ID matches first local track.');
</span><span class="lines">@@ -104,7 +104,7 @@
</span><span class="cx">     assert_equals(firstTrackEvent.streams[0].id,
</span><span class="cx">                   localStreams[0].id,
</span><span class="cx">                   'First ontrack\'s stream ID matches local stream.');
</span><del>-    let secondTrackEvent = await ontrackEventResolvers[1].promise;
</del><ins>+    let secondTrackEvent = await ontrackEventResolvers[1];
</ins><span class="cx">     assert_equals(secondTrackEvent.track.id,
</span><span class="cx">                   localStreams[1].getTracks()[0].id,
</span><span class="cx">                   'Second ontrack\'s track ID matches second local track.');
</span><span class="lines">@@ -142,6 +142,7 @@
</span><span class="cx">       if (!remoteStreams.includes(e.streams[0]))
</span><span class="cx">         remoteStreams.push(e.streams[0]);
</span><span class="cx">     };
</span><ins>+    exchangeIceCandidates(caller, callee);
</ins><span class="cx">     await exchangeOfferAnswer(caller, callee);
</span><span class="cx">     assert_equals(remoteStreams.length, 1, 'One remote stream created.');
</span><span class="cx">     assert_equals(remoteStreams[0].getTracks()[0].id,
</span><span class="lines">@@ -176,6 +177,7 @@
</span><span class="cx">       if (!remoteStreams.includes(e.streams[0]))
</span><span class="cx">         remoteStreams.push(e.streams[0]);
</span><span class="cx">     };
</span><ins>+    exchangeIceCandidates(caller, callee);
</ins><span class="cx">     await exchangeOfferAnswer(caller, callee);
</span><span class="cx">     assert_equals(remoteStreams.length, 1, 'One remote stream created.');
</span><span class="cx">     const onaddtrackPromise =
</span><span class="lines">@@ -228,7 +230,7 @@
</span><span class="cx">     const localStream =
</span><span class="cx">         await getNoiseStream({audio: true});
</span><span class="cx">     t.add_cleanup(() => localStream.getTracks().forEach(track => track.stop()));
</span><del>-    caller.addTrack(localStream.getTracks()[0]);
</del><ins>+    caller.addTrack(localStream.getTracks()[0], localStream);
</ins><span class="cx">     const ontrackPromise = addEventListenerPromise(t, callee, 'track', e => {
</span><span class="cx">       assert_array_equals(callee.getReceivers(), [e.receiver],
</span><span class="cx">                           'getReceivers() == [e.receiver].');
</span><span class="lines">@@ -245,8 +247,9 @@
</span><span class="cx">     const localStream =
</span><span class="cx">         await getNoiseStream({audio: true});
</span><span class="cx">     t.add_cleanup(() => localStream.getTracks().forEach(track => track.stop()));
</span><del>-    const sender = caller.addTrack(localStream.getTracks()[0]);
</del><ins>+    const sender = caller.addTrack(localStream.getTracks()[0], localStream);
</ins><span class="cx">     const ontrackPromise = addEventListenerPromise(t, callee, 'track');
</span><ins>+    exchangeIceCandidates(caller, callee);
</ins><span class="cx">     await exchangeOfferAnswer(caller, callee);
</span><span class="cx">     await ontrackPromise;
</span><span class="cx">     assert_equals(callee.getReceivers().length, 1, 'One receiver created.');
</span><span class="lines">@@ -269,6 +272,7 @@
</span><span class="cx">       assert_equals(e.streams.length, 1);
</span><span class="cx">       return e.streams[0];
</span><span class="cx">     });
</span><ins>+    exchangeIceCandidates(caller, callee);
</ins><span class="cx">     await exchangeOfferAnswer(caller, callee);
</span><span class="cx">     const remoteStream = await ontrackPromise;
</span><span class="cx">     const remoteTrack = remoteStream.getTracks()[0];
</span><span class="lines">@@ -297,6 +301,7 @@
</span><span class="cx">       assert_equals(e.streams.length, 1);
</span><span class="cx">       return e.streams[0];
</span><span class="cx">     });
</span><ins>+    exchangeIceCandidates(caller, callee);
</ins><span class="cx">     await exchangeOfferAnswer(caller, callee);
</span><span class="cx">     const remoteStream = await ontrackPromise;
</span><span class="cx">     const remoteTrack = remoteStream.getTracks()[0];
</span><span class="lines">@@ -320,13 +325,19 @@
</span><span class="cx">         await getNoiseStream({audio: true});
</span><span class="cx">     t.add_cleanup(() => localStream.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const sender = caller.addTrack(localStream.getTracks()[0], localStream);
</span><del>-    const ontrackPromise = addEventListenerPromise(t, callee, 'track', e => {
-      assert_equals(e.streams.length, 1);
-      return e.streams[0];
</del><ins>+    exchangeIceCandidates(caller, callee);
+    const e = await exchangeOfferAndListenToOntrack(t, caller, callee);
+    const remoteTrack = e.track;
+
+    // Need to wait for unmute, otherwise there's no event for the transition
+    // back to muted.
+    const onunmutePromise =
+        addEventListenerPromise(t, remoteTrack, 'unmute', () => {
+      assert_false(remoteTrack.muted);
</ins><span class="cx">     });
</span><del>-    await exchangeOfferAnswer(caller, callee);
-    const remoteStream = await ontrackPromise;
-    const remoteTrack = remoteStream.getTracks()[0];
</del><ins>+    await exchangeAnswer(caller, callee);
+    await onunmutePromise;
+
</ins><span class="cx">     const onmutePromise =
</span><span class="cx">         addEventListenerPromise(t, remoteTrack, 'mute', () => {
</span><span class="cx">       assert_true(remoteTrack.muted);
</span><span class="lines">@@ -350,9 +361,19 @@
</span><span class="cx">       assert_equals(e.streams.length, 1);
</span><span class="cx">       return e.streams[0];
</span><span class="cx">     });
</span><del>-    await exchangeOfferAnswer(caller, callee);
-    const remoteStream = await ontrackPromise;
-    const remoteTrack = remoteStream.getTracks()[0];
</del><ins>+    exchangeIceCandidates(caller, callee);
+    const e = await exchangeOfferAndListenToOntrack(t, caller, callee);
+    const remoteTrack = e.track;
+
+    // Need to wait for unmute, otherwise there's no event for the transition
+    // back to muted.
+    const onunmutePromise =
+        addEventListenerPromise(t, remoteTrack, 'unmute', () => {
+      assert_false(remoteTrack.muted);
+    });
+    await exchangeAnswer(caller, callee);
+    await onunmutePromise;
+
</ins><span class="cx">     const onmutePromise =
</span><span class="cx">         addEventListenerPromise(t, remoteTrack, 'mute', () => {
</span><span class="cx">       eventSequence += 'track.onmute;';
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectionsetRemoteDescriptionhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription.html     2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription.html        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -96,10 +96,9 @@
</span><span class="cx">     await pc.setLocalDescription(offer);
</span><span class="cx">     assert_state('have-local-offer');
</span><span class="cx">     await pc2.setRemoteDescription(offer);
</span><del>-    await pc2.setLocalDescription(await pc2.createAnswer());
-    await pc.setRemoteDescription(pc2.localDescription);
</del><ins>+    await exchangeAnswer(pc, pc2);
</ins><span class="cx">     assert_state('stable');
</span><del>-    await pc.setRemoteDescription(await pc2.createOffer());
</del><ins>+    await exchangeOffer(pc2, pc);
</ins><span class="cx">     assert_state('have-remote-offer');
</span><span class="cx">   }, 'Negotiation should fire signalingsstate events');
</span><span class="cx"> 
</span><span class="lines">@@ -112,9 +111,11 @@
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><span class="cx">     const offer1 = await generateAudioReceiveOnlyOffer(pc2);
</span><ins>+    await pc2.setLocalDescription(offer1);
</ins><span class="cx">     await pc.setRemoteDescription(offer1);
</span><del>-    await pc.setLocalDescription(await pc.createAnswer());
</del><ins>+    await exchangeAnswer(pc2, pc);
</ins><span class="cx">     const offer2 = await generateVideoReceiveOnlyOffer(pc2);
</span><ins>+    await pc2.setLocalDescription(offer2);
</ins><span class="cx">     await pc.setRemoteDescription(offer2);
</span><span class="cx">     assert_session_desc_not_similar(offer1, offer2);
</span><span class="cx">     assert_session_desc_similar(pc.remoteDescription, offer2);
</span><span class="lines">@@ -134,7 +135,7 @@
</span><span class="cx">     const answer = await pc2.createAnswer();
</span><span class="cx">     await pc2.setLocalDescription(answer);
</span><span class="cx">     await pc.setRemoteDescription(answer);
</span><del>-    await pc.setRemoteDescription(await pc2.createOffer());
</del><ins>+    await exchangeOffer(pc2, pc);
</ins><span class="cx">     assert_equals(pc.remoteDescription.sdp, pc.pendingRemoteDescription.sdp);
</span><span class="cx">     assert_session_desc_similar(pc.remoteDescription, offer);
</span><span class="cx">     assert_session_desc_similar(pc.currentRemoteDescription, answer);
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiontrackstatshttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-track-stats.https-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-track-stats.https-expected.txt        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-track-stats.https-expected.txt   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,12 +1,10 @@
</span><span class="cx"> 
</span><del>-Harness Error (TIMEOUT), message = null
-
</del><span class="cx"> PASS addTrack() without setLocalDescription() yields track stats 
</span><span class="cx"> FAIL addTrack() without setLocalDescription() yields media stream stats assert_true: Has stats for stream expected true got false
</span><span class="cx"> PASS addTrack() with setLocalDescription() yields track stats 
</span><span class="cx"> FAIL addTrack() with setLocalDescription() yields media stream stats assert_true: Has stats for stream expected true got false
</span><span class="cx"> FAIL addTrack(): Media stream stats references track stats assert_true: Has stats for track and stream expected true got false
</span><del>-FAIL Legacy addStream(): Media stream stats references track stats pc.addStream is not a function. (In 'pc.addStream(stream)', 'pc.addStream' is undefined)
</del><ins>+FAIL Media stream stats references track stats assert_true: Has stats for track and stream expected true got false
</ins><span class="cx"> PASS O/A exchange yields outbound RTP stream stats for sending track 
</span><span class="cx"> PASS O/A exchange yields inbound RTP stream stats for receiving track 
</span><span class="cx"> FAIL replaceTrack() before offer: new track attachment stats present assert_true: Has stats for replaced track expected true got false
</span><span class="lines">@@ -15,8 +13,8 @@
</span><span class="cx"> FAIL replaceTrack(): original track attachment stats present after replacing assert_true: expected true got undefined
</span><span class="cx"> FAIL RTCRtpSender.getStats() contains only outbound-rtp and related stats promise_test: Unhandled rejection with value: object "TypeError: null is not an object (evaluating 'inboundTrackStats.id')"
</span><span class="cx"> FAIL RTCRtpReceiver.getStats() contains only inbound-rtp and related stats promise_test: Unhandled rejection with value: object "TypeError: null is not an object (evaluating 'inboundTrackStats.id')"
</span><del>-TIMEOUT RTCPeerConnection.getStats(sendingTrack) is the same as RTCRtpSender.getStats() Test timed out
-NOTRUN RTCPeerConnection.getStats(receivingTrack) is the same as RTCRtpReceiver.getStats() 
-NOTRUN RTCPeerConnection.getStats(track) throws InvalidAccessError when there are zero senders or receivers for the track 
-NOTRUN RTCPeerConnection.getStats(track) throws InvalidAccessError when there are multiple senders for the track 
</del><ins>+PASS RTCPeerConnection.getStats(sendingTrack) is the same as RTCRtpSender.getStats() 
+PASS RTCPeerConnection.getStats(receivingTrack) is the same as RTCRtpReceiver.getStats() 
+FAIL RTCPeerConnection.getStats(track) throws InvalidAccessError when there are zero senders or receivers for the track assert_unreached: Should have rejected: undefined Reached unreachable code
+FAIL RTCPeerConnection.getStats(track) throws InvalidAccessError when there are multiple senders for the track assert_unreached: Should have rejected: undefined Reached unreachable code
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiontrackstatshttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-track-stats.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-track-stats.https.html        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-track-stats.https.html   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -25,8 +25,9 @@
</span><span class="cx">     let track;
</span><span class="cx">     return getUserMediaTracksAndStreams(1)
</span><span class="cx">     .then(t.step_func(([tracks, streams]) => {
</span><ins>+      t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">       track = tracks[0];
</span><del>-      pc.addTrack(track);
</del><ins>+      pc.addTrack(track, streams[0]);
</ins><span class="cx">       return pc.getStats();
</span><span class="cx">     }))
</span><span class="cx">     .then(t.step_func(report => {
</span><span class="lines">@@ -50,6 +51,7 @@
</span><span class="cx">     let stream;
</span><span class="cx">     return getUserMediaTracksAndStreams(1)
</span><span class="cx">     .then(t.step_func(([tracks, streams]) => {
</span><ins>+      t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">       let track = tracks[0];
</span><span class="cx">       stream = streams[0];
</span><span class="cx">       pc.addTrack(track, stream);
</span><span class="lines">@@ -72,8 +74,9 @@
</span><span class="cx">     let track;
</span><span class="cx">     return getUserMediaTracksAndStreams(1)
</span><span class="cx">     .then(t.step_func(([tracks, streams]) => {
</span><ins>+      t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">       track = tracks[0];
</span><del>-      pc.addTrack(track);
</del><ins>+      pc.addTrack(track, streams[0]);
</ins><span class="cx">       return pc.createOffer();
</span><span class="cx">     }))
</span><span class="cx">     .then(t.step_func(offer => {
</span><span class="lines">@@ -99,6 +102,7 @@
</span><span class="cx">     let stream;
</span><span class="cx">     return getUserMediaTracksAndStreams(1)
</span><span class="cx">     .then(t.step_func(([tracks, streams]) => {
</span><ins>+      t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">       let track = tracks[0];
</span><span class="cx">       stream = streams[0];
</span><span class="cx">       pc.addTrack(track, stream);
</span><span class="lines">@@ -128,6 +132,7 @@
</span><span class="cx">     let stream;
</span><span class="cx">     return getUserMediaTracksAndStreams(1)
</span><span class="cx">     .then(t.step_func(([tracks, streams]) => {
</span><ins>+      t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">       track = tracks[0];
</span><span class="cx">       stream = streams[0];
</span><span class="cx">       pc.addTrack(track, stream);
</span><span class="lines">@@ -155,11 +160,6 @@
</span><span class="cx">     }));
</span><span class="cx">   }, 'addTrack(): Media stream stats references track stats');
</span><span class="cx"> 
</span><del>-  // TODO(hbos): addStream() is legacy API not in the spec. Based on discussion
-  // whether to standardize in legacy section, consider removing this test or
-  // keeping it until addTrack() has wide support.
-  // https://github.com/w3c/webrtc-pc/issues/1705
-  // https://github.com/w3c/webrtc-pc/issues/1125
</del><span class="cx">   async_test(t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><span class="lines">@@ -167,10 +167,12 @@
</span><span class="cx">     let stream;
</span><span class="cx">     return getUserMediaTracksAndStreams(1)
</span><span class="cx">     .then(t.step_func(([tracks, streams]) => {
</span><ins>+      t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">       track = tracks[0];
</span><span class="cx">       stream = streams[0];
</span><span class="cx">       stream.addTrack(track);
</span><del>-      pc.addStream(stream);
</del><ins>+      for (const track of stream.getTracks())
+        pc.addTrack(track, stream);
</ins><span class="cx">       return pc.createOffer();
</span><span class="cx">     }))
</span><span class="cx">     .then(t.step_func(offer => {
</span><span class="lines">@@ -193,7 +195,7 @@
</span><span class="cx">     .catch(t.step_func(reason => {
</span><span class="cx">       assert_unreached(reason);
</span><span class="cx">     }));
</span><del>-  }, 'Legacy addStream(): Media stream stats references track stats');
</del><ins>+  }, 'Media stream stats references track stats');
</ins><span class="cx"> 
</span><span class="cx">   async_test(t => {
</span><span class="cx">     const caller = new RTCPeerConnection();
</span><span class="lines">@@ -203,8 +205,9 @@
</span><span class="cx">     let sendingTrack;
</span><span class="cx">     return getUserMediaTracksAndStreams(1)
</span><span class="cx">     .then(t.step_func(([tracks, streams]) => {
</span><ins>+      t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">       sendingTrack = tracks[0];
</span><del>-      caller.addTrack(sendingTrack);
</del><ins>+      caller.addTrack(sendingTrack, streams[0]);
</ins><span class="cx">       return doSignalingHandshake(caller, callee);
</span><span class="cx">     }))
</span><span class="cx">     .then(t.step_func(() => {
</span><span class="lines">@@ -237,7 +240,8 @@
</span><span class="cx">     };
</span><span class="cx">     return getUserMediaTracksAndStreams(1)
</span><span class="cx">     .then(t.step_func(([tracks, streams]) => {
</span><del>-      caller.addTrack(tracks[0]);
</del><ins>+      t.add_cleanup(() => tracks.forEach(track => track.stop()));
+      caller.addTrack(tracks[0], streams[0]);
</ins><span class="cx">       return doSignalingHandshake(caller, callee);
</span><span class="cx">     }))
</span><span class="cx">     .then(t.step_func(() => {
</span><span class="lines">@@ -269,9 +273,10 @@
</span><span class="cx">     let sender;
</span><span class="cx">     return getUserMediaTracksAndStreams(2)
</span><span class="cx">     .then(t.step_func(([tracks, streams]) => {
</span><ins>+      t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">       sendingTrack1 = tracks[0];
</span><span class="cx">       sendingTrack2 = tracks[1];
</span><del>-      sender = caller.addTrack(sendingTrack1);
</del><ins>+      sender = caller.addTrack(sendingTrack1, streams[0]);
</ins><span class="cx">       return sender.replaceTrack(sendingTrack2);
</span><span class="cx">     }))
</span><span class="cx">     .then(t.step_func(() => {
</span><span class="lines">@@ -298,9 +303,10 @@
</span><span class="cx">     let sender;
</span><span class="cx">     return getUserMediaTracksAndStreams(2)
</span><span class="cx">     .then(t.step_func(([tracks, streams]) => {
</span><ins>+      t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">       sendingTrack1 = tracks[0];
</span><span class="cx">       sendingTrack2 = tracks[1];
</span><del>-      sender = caller.addTrack(sendingTrack1);
</del><ins>+      sender = caller.addTrack(sendingTrack1, streams[0]);
</ins><span class="cx">       return exchangeOffer(caller, callee);
</span><span class="cx">     }))
</span><span class="cx">     .then(t.step_func(() => {
</span><span class="lines">@@ -335,9 +341,10 @@
</span><span class="cx">     let sender;
</span><span class="cx">     return getUserMediaTracksAndStreams(2)
</span><span class="cx">     .then(t.step_func(([tracks, streams]) => {
</span><ins>+      t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">       sendingTrack1 = tracks[0];
</span><span class="cx">       sendingTrack2 = tracks[1];
</span><del>-      sender = caller.addTrack(sendingTrack1);
</del><ins>+      sender = caller.addTrack(sendingTrack1, streams[0]);
</ins><span class="cx">       return doSignalingHandshake(caller, callee);
</span><span class="cx">     }))
</span><span class="cx">     .then(t.step_func(() => {
</span><span class="lines">@@ -371,9 +378,10 @@
</span><span class="cx">     let sender;
</span><span class="cx">     return getUserMediaTracksAndStreams(2)
</span><span class="cx">     .then(t.step_func(([tracks, streams]) => {
</span><ins>+      t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">       sendingTrack1 = tracks[0];
</span><span class="cx">       sendingTrack2 = tracks[1];
</span><del>-      sender = caller.addTrack(sendingTrack1);
</del><ins>+      sender = caller.addTrack(sendingTrack1, streams[0]);
</ins><span class="cx">       return doSignalingHandshake(caller, callee);
</span><span class="cx">     }))
</span><span class="cx">     .then(t.step_func(() => {
</span><span class="lines">@@ -404,11 +412,12 @@
</span><span class="cx">     const callee = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => callee.close());
</span><span class="cx">     let [tracks, streams] = await getUserMediaTracksAndStreams(2);
</span><ins>+    t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">     let sender = caller.addTrack(tracks[0], streams[0]);
</span><span class="cx">     callee.addTrack(tracks[1], streams[1]);
</span><span class="cx">     exchangeIceCandidates(caller, callee);
</span><span class="cx">     await doSignalingHandshake(caller, callee);
</span><del>-    await onIceConnectionStateCompleted(caller);
</del><ins>+    await listenToConnected(caller);
</ins><span class="cx">     let receiver = caller.getReceivers()[0];
</span><span class="cx"> 
</span><span class="cx">     // Obtain inbound and outbound RTP stream stats on a full stats report.
</span><span class="lines">@@ -452,11 +461,12 @@
</span><span class="cx">     const callee = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => callee.close());
</span><span class="cx">     let [tracks, streams] = await getUserMediaTracksAndStreams(2);
</span><ins>+    t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">     let sender = caller.addTrack(tracks[0], streams[0]);
</span><span class="cx">     callee.addTrack(tracks[1], streams[1]);
</span><span class="cx">     exchangeIceCandidates(caller, callee);
</span><span class="cx">     await doSignalingHandshake(caller, callee);
</span><del>-    await onIceConnectionStateCompleted(caller);
</del><ins>+    await listenToConnected(caller);
</ins><span class="cx">     let receiver = caller.getReceivers()[0];
</span><span class="cx"> 
</span><span class="cx">     // Obtain inbound and outbound RTP stream stats on a full stats report.
</span><span class="lines">@@ -500,11 +510,12 @@
</span><span class="cx">     const callee = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => callee.close());
</span><span class="cx">     let [tracks, streams] = await getUserMediaTracksAndStreams(2);
</span><ins>+    t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">     let sender = caller.addTrack(tracks[0], streams[0]);
</span><span class="cx">     callee.addTrack(tracks[1], streams[1]);
</span><span class="cx">     exchangeIceCandidates(caller, callee);
</span><span class="cx">     await doSignalingHandshake(caller, callee);
</span><del>-    await onIceConnectionStateCompleted(caller);
</del><ins>+    await listenToIceConnected(caller);
</ins><span class="cx"> 
</span><span class="cx">     // Wait until RTCP has arrived so that it can not arrive between
</span><span class="cx">     // the two get stats calls.
</span><span class="lines">@@ -531,11 +542,12 @@
</span><span class="cx">     const callee = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => callee.close());
</span><span class="cx">     let [tracks, streams] = await getUserMediaTracksAndStreams(2);
</span><ins>+    t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">     let sender = caller.addTrack(tracks[0], streams[0]);
</span><span class="cx">     callee.addTrack(tracks[1], streams[1]);
</span><span class="cx">     exchangeIceCandidates(caller, callee);
</span><span class="cx">     await doSignalingHandshake(caller, callee);
</span><del>-    await onIceConnectionStateCompleted(caller);
</del><ins>+    await listenToIceConnected(caller);
</ins><span class="cx">     let receiver = caller.getReceivers()[0];
</span><span class="cx"> 
</span><span class="cx">     // Wait until RTCP has arrived so that it can not arrive between
</span><span class="lines">@@ -561,6 +573,7 @@
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><span class="cx">     let [tracks, streams] = await getUserMediaTracksAndStreams(1);
</span><ins>+    t.add_cleanup(() => tracks.forEach(track => track.stop()));
</ins><span class="cx">     await promise_rejects(t, 'InvalidAccessError', pc.getStats(tracks[0]));
</span><span class="cx">   }, 'RTCPeerConnection.getStats(track) throws InvalidAccessError when there ' +
</span><span class="cx">      'are zero senders or receivers for the track');
</span><span class="lines">@@ -569,8 +582,9 @@
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><span class="cx">     let [tracks, streams] = await getUserMediaTracksAndStreams(2);
</span><del>-    let sender1 = pc.addTrack(tracks[0]);
-    let sender2 = pc.addTrack(tracks[1]);
</del><ins>+    t.add_cleanup(() => tracks.forEach(track => track.stop()));
+    let sender1 = pc.addTrack(tracks[0], streams[0]);
+    let sender2 = pc.addTrack(tracks[1], streams[1]);
</ins><span class="cx">     await sender2.replaceTrack(sender1.track);
</span><span class="cx">     await promise_rejects(t, 'InvalidAccessError', pc.getStats(sender1.track));
</span><span class="cx">   }, 'RTCPeerConnection.getStats(track) throws InvalidAccessError when there ' +
</span><span class="lines">@@ -607,24 +621,6 @@
</span><span class="cx">     return stats;
</span><span class="cx">   }
</span><span class="cx"> 
</span><del>-  // Returns a promise that is resolved when pc.iceConnectionState reaches the
-  // 'connected' or 'completed' state. This is when transport stats can be
-  // expected to have its selectedCandidatePairId defined.
-  async function onIceConnectionStateCompleted(pc) {
-    if (pc.iceConnectionState == 'connected' ||
-        pc.iceConnectionState == 'completed') {
-      return Promise.resolve();
-    }
-    let resolver = new Resolver();
-    pc.oniceconnectionstatechange = e => {
-      if (pc.iceConnectionState == 'connected' ||
-          pc.iceConnectionState == 'completed') {
-        resolver.resolve();
-      }
-    };
-    return resolver.promise;
-  }
-
</del><span class="cx">   // Explores the stats graph starting from |stat|, validating each stat
</span><span class="cx">   // (validateRtcStats) and asserting that all stats of the report were visited.
</span><span class="cx">   function validateStatsGraph(report, stat) {
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiontransceivershttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-transceivers.https-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-transceivers.https-expected.txt       2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-transceivers.https-expected.txt  2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -11,7 +11,7 @@
</span><span class="cx"> PASS setLocalDescription(offer): transceiver gets associated with an m-section 
</span><span class="cx"> PASS setLocalDescription(offer): transceiver.mid matches the offer SDP 
</span><span class="cx"> PASS setRemoteDescription(offer): ontrack fires with a track 
</span><del>-PASS setRemoteDescription(offer): ontrack's track.id is the same as track.id 
</del><ins>+PASS setRemoteDescription(offer): ontrack's stream.id is the same as stream.id 
</ins><span class="cx"> PASS setRemoteDescription(offer): ontrack fires with a transceiver. 
</span><span class="cx"> PASS setRemoteDescription(offer): transceiver.mid is the same on both ends 
</span><span class="cx"> PASS setRemoteDescription(offer): "transceiver == {sender,receiver}" 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCPeerConnectiontransceivershttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-transceivers.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-transceivers.https.html       2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-transceivers.https.html  2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,4 +1,5 @@
</span><span class="cx"> <!doctype html>
</span><ins>+<meta name="timeout" content="long"/>
</ins><span class="cx"> <meta charset=utf-8>
</span><span class="cx"> <title>RTCPeerConnection-transceivers.https.html</title>
</span><span class="cx"> <script src="/resources/testharness.js"></script>
</span><span class="lines">@@ -138,9 +139,13 @@
</span><span class="cx">   const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
</span><span class="cx">   assert_true(trackEvent.track instanceof MediaStreamTrack,
</span><span class="cx">               'trackEvent.track instanceof MediaStreamTrack');
</span><del>-  assert_equals(trackEvent.track.id, track.id,
-                'trackEvent.track.id == track.id');
-}, 'setRemoteDescription(offer): ontrack\'s track.id is the same as track.id');
</del><ins>+  assert_equals(trackEvent.streams.length, 1,
+                'trackEvent contains a single stream');
+  assert_true(trackEvent.streams[0] instanceof MediaStream,
+              'trackEvent has a MediaStream');
+  assert_equals(trackEvent.streams[0].id, stream.id,
+                'trackEvent.streams[0].id == stream.id');
+}, 'setRemoteDescription(offer): ontrack\'s stream.id is the same as stream.id');
</ins><span class="cx"> 
</span><span class="cx"> promise_test(async t => {
</span><span class="cx">   const pc1 = createPeerConnectionWithCleanup(t);
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpParametersencodingsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-encodings-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-encodings-expected.txt 2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-encodings-expected.txt    2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -15,6 +15,8 @@
</span><span class="cx"> FAIL setParameters() with modified encoding.active should succeed without RTCRtpTransceiverInit assert_equals: Expect dictionary.rtcp to be plain object expected "object" but got "undefined"
</span><span class="cx"> FAIL setParameters() with modified encoding.priority should succeed with RTCRtpTransceiverInit assert_equals: Expect dictionary.rtcp to be plain object expected "object" but got "undefined"
</span><span class="cx"> FAIL setParameters() with modified encoding.priority should succeed without RTCRtpTransceiverInit assert_equals: Expect dictionary.rtcp to be plain object expected "object" but got "undefined"
</span><ins>+FAIL setParameters() with modified encoding.networkPriority should succeed with RTCRtpTransceiverInit assert_equals: Expect dictionary.rtcp to be plain object expected "object" but got "undefined"
+FAIL setParameters() with modified encoding.networkPriority should succeed without RTCRtpTransceiverInit assert_equals: Expect dictionary.rtcp to be plain object expected "object" but got "undefined"
</ins><span class="cx"> FAIL setParameters() with modified encoding.ptime should succeed with RTCRtpTransceiverInit assert_equals: Expect dictionary.rtcp to be plain object expected "object" but got "undefined"
</span><span class="cx"> FAIL setParameters() with modified encoding.ptime should succeed without RTCRtpTransceiverInit assert_equals: Expect dictionary.rtcp to be plain object expected "object" but got "undefined"
</span><span class="cx"> FAIL setParameters() with modified encoding.maxBitrate should succeed with RTCRtpTransceiverInit assert_equals: Expect dictionary.rtcp to be plain object expected "object" but got "undefined"
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpParametersencodingshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-encodings.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-encodings.html 2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-encodings.html    2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx">         RTCDtxStatus        dtx;
</span><span class="cx">         boolean             active;
</span><span class="cx">         RTCPriorityType     priority;
</span><ins>+        RTCPriorityType     networkPriority;
</ins><span class="cx">         unsigned long       ptime;
</span><span class="cx">         unsigned long       maxBitrate;
</span><span class="cx">         double              maxFramerate;
</span><span class="lines">@@ -146,6 +147,7 @@
</span><span class="cx">         dtx: 'enabled',
</span><span class="cx">         active: false,
</span><span class="cx">         priority: 'low',
</span><ins>+        networkPriority: 'low',
</ins><span class="cx">         ptime: 5,
</span><span class="cx">         maxBitrate: 8,
</span><span class="cx">         maxFramerate: 25,
</span><span class="lines">@@ -161,6 +163,7 @@
</span><span class="cx">     assert_equals(encoding.dtx, 'enabled');
</span><span class="cx">     assert_equals(encoding.active, false);
</span><span class="cx">     assert_equals(encoding.priority, 'low');
</span><ins>+    assert_equals(encoding.networkPriority, 'low');
</ins><span class="cx">     assert_equals(encoding.ptime, 5);
</span><span class="cx">     assert_equals(encoding.maxBitrate, 8);
</span><span class="cx">     assert_equals(encoding.maxFramerate, 25);
</span><span class="lines">@@ -217,8 +220,8 @@
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><del>-    const { sender } = pc.addTransceiver('audio', {
-      sendEncodings: [{ rid: 'foo' }],
</del><ins>+    const { sender } = pc.addTransceiver('video', {
+      sendEncodings: [{ rid: 'foo' }, { rid: 'baz' }],
</ins><span class="cx">     });
</span><span class="cx">     await doOfferAnswerExchange(t, pc);
</span><span class="cx"> 
</span><span class="lines">@@ -250,7 +253,7 @@
</span><span class="cx">     const encoding = getFirstEncoding(param);
</span><span class="cx"> 
</span><span class="cx">     encoding.scaleResolutionDownBy = 0.5;
</span><del>-    return promise_rejects(t, 'RangeError',
</del><ins>+    return promise_rejects(t, new RangeError(),
</ins><span class="cx">       sender.setParameters(param));
</span><span class="cx">   }, `setParameters() with encoding.scaleResolutionDownBy field set to less than 1.0 should reject with RangeError`);
</span><span class="cx"> 
</span><span class="lines">@@ -339,6 +342,9 @@
</span><span class="cx">   test_modified_encoding('audio', 'priority', 'very-low', 'high',
</span><span class="cx">     'setParameters() with modified encoding.priority should succeed');
</span><span class="cx"> 
</span><ins>+  test_modified_encoding('audio', 'networkPriority', 'very-low', 'high',
+    'setParameters() with modified encoding.networkPriority should succeed');
+
</ins><span class="cx">   test_modified_encoding('audio', 'ptime', 2, 4,
</span><span class="cx">     'setParameters() with modified encoding.ptime should succeed');
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpParametershelperjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-helper.js (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-helper.js      2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-helper.js 2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -19,6 +19,8 @@
</span><span class="cx">   const answer = await callee.createAnswer();
</span><span class="cx">   await callee.setLocalDescription(answer);
</span><span class="cx">   await caller.setRemoteDescription(answer);
</span><ins>+
+  return callee;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /*
</span><span class="lines">@@ -142,6 +144,7 @@
</span><span class="cx">     RTCDtxStatus        dtx;
</span><span class="cx">     boolean             active;
</span><span class="cx">     RTCPriorityType     priority;
</span><ins>+    RTCPriorityType     networkPriority;
</ins><span class="cx">     unsigned long       ptime;
</span><span class="cx">     unsigned long       maxBitrate;
</span><span class="cx">     double              maxFramerate;
</span><span class="lines">@@ -171,6 +174,8 @@
</span><span class="cx">   assert_optional_boolean_field(encoding, 'active');
</span><span class="cx">   assert_optional_enum_field(encoding, 'priority',
</span><span class="cx">     ['very-low', 'low', 'medium', 'high']);
</span><ins>+  assert_optional_enum_field(encoding, 'networkPriority',
+    ['very-low', 'low', 'medium', 'high']);
</ins><span class="cx"> 
</span><span class="cx">   assert_optional_unsigned_int_field(encoding, 'ptime');
</span><span class="cx">   assert_optional_unsigned_int_field(encoding, 'maxBitrate');
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetContributingSourceshttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getContributingSources.https-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getContributingSources.https-expected.txt        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getContributingSources.https-expected.txt   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,3 +1,4 @@
</span><span class="cx"> 
</span><del>-FAIL getContributingSources() should return list of CSRC after connection is established assert_greater_than: Expect CSRCs to be available after RTP connection is established expected a number greater than 0 but got 0
</del><ins>+PASS [audio] getContributingSources() returns an empty list in loopback call 
+PASS [video] getContributingSources() returns an empty list in loopback call 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetContributingSourceshttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getContributingSources.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getContributingSources.https.html        2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getContributingSources.https.html   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -5,85 +5,31 @@
</span><span class="cx"> <script src="/resources/testharnessreport.js"></script>
</span><span class="cx"> <script src="RTCPeerConnection-helper.js"></script>
</span><span class="cx"> <script>
</span><del>-  'use strict';
</del><ins>+'use strict';
</ins><span class="cx"> 
</span><del>-  // Test is based on the following editor draft:
-  // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
</del><ins>+async function connectAndExpectNoCsrcs(t, kind) {
+  const pc1 = new RTCPeerConnection();
+  t.add_cleanup(() => pc1.close());
+  const pc2 = new RTCPeerConnection();
+  t.add_cleanup(() => pc2.close());
</ins><span class="cx"> 
</span><del>-  // The following helper function is called from RTCPeerConnection-helper.js
-  //   getTrackFromUserMedia
-  //   exchangeIceCandidates
-  //   doSignalingHandshake
</del><ins>+  const stream = await navigator.mediaDevices.getUserMedia({[kind]:true});
+  const [track] = stream.getTracks();
+  t.add_cleanup(() => track.stop());
+  pc1.addTrack(track, stream);
</ins><span class="cx"> 
</span><del>-  /*
-    5.3.  RTCRtpReceiver Interface
-      interface RTCRtpReceiver {
-        ...
-        sequence<RTCRtpContributingSource>    getContributingSources();
-      };
</del><ins>+  exchangeIceCandidates(pc1, pc2);
+  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
+  await exchangeAnswer(pc1, pc2);
</ins><span class="cx"> 
</span><del>-      interface RTCRtpContributingSource {
-        readonly attribute DOMHighResTimeStamp timestamp;
-        readonly attribute unsigned long       source;
-        readonly attribute byte?               audioLevel;
-      };
</del><ins>+  assert_array_equals(trackEvent.receiver.getContributingSources(), []);
+}
</ins><span class="cx"> 
</span><del>-      audioLevel
-        The audio level contained in the last RTP packet played from this source.
-        audioLevel will be the level value defined in [RFC6465] if the RFC 6465
-        header extension is present, and otherwise null. RFC 6465 defines the
-        level as a integral value from 0 to 127 representing the audio level in
-        negative decibels relative to the loudest signal that the system could
-        possibly encode. Thus, 0 represents the loudest signal the system could
-        possibly encode, and 127 represents silence.
-   */
</del><ins>+promise_test(async t => {
+  await connectAndExpectNoCsrcs(t, 'audio');
+}, '[audio] getContributingSources() returns an empty list in loopback call');
</ins><span class="cx"> 
</span><del>-  promise_test(t => {
-    const pc1 = new RTCPeerConnection();
-    t.add_cleanup(() => pc1.close());
-    const pc2 = new RTCPeerConnection();
-
-    t.add_cleanup(() => pc2.close());
-
-    const ontrackPromise = new Promise(resolve => {
-      pc2.addEventListener('track', trackEvent => {
-        const { receiver } = trackEvent;
-        assert_true(receiver instanceof RTCRtpReceiver,
-          'Expect trackEvent.receiver to be instance of RTCRtpReceiver');
-
-        resolve(receiver);
-      });
-    });
-
-    return getTrackFromUserMedia('audio')
-    .then(([track, mediaStream]) => {
-      pc1.addTrack(track, mediaStream);
-      exchangeIceCandidates(pc1, pc2);
-      return doSignalingHandshake(pc1, pc2);
-    })
-    .then(() => ontrackPromise)
-    .then(receiver => {
-      const contributingSources = receiver.getContributingSources();
-      assert_greater_than(contributingSources.length, 0,
-        'Expect CSRCs to be available after RTP connection is established');
-
-      for(const csrc of contributingSources) {
-        assert_true(csrc instanceof RTCRtpContributingSource,
-          'Expect contributingSources elements to be instance of RTCRtpContributingSource');
-
-        assert_equals(typeof csrc.timestamp, 'number',
-          'Expect csrc.timestamp attribute to be DOMHighResTimeStamp');
-
-        assert_true(Number.isInteger(csrc.source) && csrc.source > 0,
-          'Expect CSRC identifier to be unsigned long');
-
-        if(csrc.audioLevel !== null) {
-          assert_true(Number.isInteger(csrc.audioLevel) &&
-             csrc.audioLevel >= 0 && csrc.audioLevel <= 127,
-            'Expect csrc.audioLevel to be either null or byte value from 0-127.');
-        }
-      }
-    });
-  }, `getContributingSources() should return list of CSRC after connection is established`);
-
</del><ins>+promise_test(async t => {
+  await connectAndExpectNoCsrcs(t, 'video');
+}, '[video] getContributingSources() returns an empty list in loopback call');
</ins><span class="cx"> </script>
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetParametersexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getParameters-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getParameters-expected.txt       2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getParameters-expected.txt  2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,3 +1,5 @@
</span><span class="cx"> 
</span><del>-FAIL RTCRtpReceiver.prototype.getParameters assert_true: Expect dictionary.encodings to be array expected true got false
</del><ins>+FAIL getParameters() with audio receiver assert_true: Expect dictionary.encodings to be array expected true got false
+FAIL getParameters() with video receiver assert_true: Expect dictionary.encodings to be array expected true got false
+FAIL getParameters() with simulcast video receiver assert_true: Expect dictionary.encodings to be array expected true got false
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetParametershtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getParameters.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getParameters.html       2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getParameters.html  2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -33,10 +33,51 @@
</span><span class="cx"> 
</span><span class="cx">         - transactionId and degradationPreference are left undefined.
</span><span class="cx">    */
</span><del>-  test(t => {
</del><ins>+  promise_test(async t => {
</ins><span class="cx">     const pc = new RTCPeerConnection();
</span><del>-    const { receiver } = pc.addTransceiver('audio');
-    const param = receiver.getParameters();
</del><ins>+    t.add_cleanup(() => pc.close());
+    pc.addTransceiver('audio');
+    const callee = await doOfferAnswerExchange(t, pc);
+    const param = callee.getReceivers()[0].getParameters();
</ins><span class="cx">     validateReceiverRtpParameters(param);
</span><del>-  });
</del><ins>+
+    assert_greater_than(param.headerExtensions.length, 0);
+    assert_greater_than(param.codecs.length, 0);
+    assert_equals(param.encodings.length, 1);
+  }, 'getParameters() with audio receiver');
+
+  promise_test(async t => {
+    const pc = new RTCPeerConnection();
+    t.add_cleanup(() => pc.close());
+    pc.addTransceiver('video');
+    const callee = await doOfferAnswerExchange(t, pc);
+    const param = callee.getReceivers()[0].getParameters();
+    validateReceiverRtpParameters(param);
+
+    assert_greater_than(param.headerExtensions.length, 0);
+    assert_greater_than(param.codecs.length, 0);
+    assert_equals(param.encodings.length, 1);
+  }, 'getParameters() with video receiver');
+
+  promise_test(async t => {
+    const pc = new RTCPeerConnection();
+    t.add_cleanup(() => pc.close());
+    pc.addTransceiver('video', {
+      sendEncodings: [
+        { rid: "rid1" },
+        { rid: "rid2" }
+      ]
+    });
+    const callee = await doOfferAnswerExchange(t, pc);
+    const param = callee.getReceivers()[0].getParameters();
+    validateReceiverRtpParameters(param);
+
+    assert_greater_than(param.headerExtensions.length, 0);
+    assert_greater_than(param.codecs.length, 0);
+    assert_equals(param.encodings.length, 2, 'layer count must match');
+    assert_equals(param.encodings[0].rid, "rid1",
+      'simulcast rids must match');
+    assert_equals(param.encodings[1].rid, "rid2",
+      'simulcast rids must match');
+  }, 'getParameters() with simulcast video receiver');
</ins><span class="cx"> </script>
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetStatshttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getStats.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getStats.https.html      2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getStats.https.html 2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx">     const stream = await getNoiseStream({audio:true});
</span><span class="cx">     t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track] = stream.getTracks();
</span><del>-    callee.addTrack(track);
</del><ins>+    callee.addTrack(track, stream);
</ins><span class="cx"> 
</span><span class="cx">     const { receiver } = caller.addTransceiver('audio');
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetSynchronizationSourceshttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https-expected.txt     2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https-expected.txt        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><span class="cx"> 
</span><del>-FAIL getContributingSources() should return list of CSRC after connection is established assert_greater_than: Expect SSRCs to be available after RTP connection is established expected a number greater than 0 but got 0
</del><ins>+PASS [audio] getSynchronizationSources() eventually returns a non-empty list 
+PASS [audio] RTCRtpSynchronizationSource.timestamp is a number 
+PASS [audio] getSynchronizationSources() does not contain SSRCs older than 10 seconds 
+FAIL [audio] RTCRtpSynchronizationSource.timestamp is comparable to performance.timeOrigin + performance.now() assert_true: expected true got false
+PASS [audio] RTCRtpSynchronizationSource.source is a number 
+PASS [video] getSynchronizationSources() eventually returns a non-empty list 
+PASS [video] RTCRtpSynchronizationSource.timestamp is a number 
+PASS [video] getSynchronizationSources() does not contain SSRCs older than 10 seconds 
+FAIL [video] RTCRtpSynchronizationSource.timestamp is comparable to performance.timeOrigin + performance.now() assert_true: expected true got false
+PASS [video] RTCRtpSynchronizationSource.source is a number 
+FAIL [audio-only] RTCRtpSynchronizationSource.audioLevel is a number [0, 1] assert_less_than_equal: expected a number less than or equal to 1 but got 23
+FAIL [audio-only] RTCRtpSynchronizationSource.voiceActivityFlag is a boolean assert_equals: expected "boolean" but got "undefined"
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpReceivergetSynchronizationSourceshttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html     2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,79 +1,96 @@
</span><span class="cx"> <!doctype html>
</span><span class="cx"> <meta charset=utf-8>
</span><ins>+<!-- This file contains two tests that wait for 10 seconds each. -->
+<meta name="timeout" content="long">
</ins><span class="cx"> <title>RTCRtpReceiver.prototype.getSynchronizationSources</title>
</span><span class="cx"> <script src="/resources/testharness.js"></script>
</span><span class="cx"> <script src="/resources/testharnessreport.js"></script>
</span><span class="cx"> <script src="RTCPeerConnection-helper.js"></script>
</span><span class="cx"> <script>
</span><del>-  'use strict';
</del><ins>+'use strict';
</ins><span class="cx"> 
</span><del>-  // Test is based on the following editor draft:
-  // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
</del><ins>+async function initiateSingleTrackCallAndReturnReceiver(t, kind) {
+  const pc1 = new RTCPeerConnection();
+  t.add_cleanup(() => pc1.close());
+  const pc2 = new RTCPeerConnection();
+  t.add_cleanup(() => pc2.close());
</ins><span class="cx"> 
</span><del>-  /*
-    5.3.  RTCRtpReceiver Interface
-      interface RTCRtpReceiver {
-        ...
-        sequence<RTCRtpSynchronizationSource> getSynchronizationSources();
-      };
</del><ins>+  const stream = await navigator.mediaDevices.getUserMedia({[kind]:true});
+  const [track] = stream.getTracks();
+  t.add_cleanup(() => track.stop());
+  pc1.addTrack(track, stream);
</ins><span class="cx"> 
</span><del>-      interface RTCRtpSynchronizationSource {
-        readonly attribute DOMHighResTimeStamp timestamp;
-        readonly attribute unsigned long       source;
-        readonly attribute byte                audioLevel;
-        readonly attribute boolean?            voiceActivityFlag;
-      };
-   */
</del><ins>+  exchangeIceCandidates(pc1, pc2);
+  const trackEvent = await exchangeOfferAndListenToOntrack(t, pc1, pc2);
+  await exchangeAnswer(pc1, pc2);
+  return trackEvent.receiver;
+}
</ins><span class="cx"> 
</span><del>-  promise_test(t => {
-    const pc1 = new RTCPeerConnection();
-    t.add_cleanup(() => pc1.close());
-    const pc2 = new RTCPeerConnection();
</del><ins>+for (const kind of ['audio', 'video']) {
+  promise_test(async t => {
+    const receiver = await initiateSingleTrackCallAndReturnReceiver(t, kind);
+    await listenForSSRCs(t, receiver);
+  }, '[' + kind + '] getSynchronizationSources() eventually returns a ' +
+     'non-empty list');
</ins><span class="cx"> 
</span><del>-    t.add_cleanup(() => pc2.close());
</del><ins>+  promise_test(async t => {
+    const startTime = performance.now();
+    const receiver = await initiateSingleTrackCallAndReturnReceiver(t, kind);
+    const [ssrc] = await listenForSSRCs(t, receiver);
+    assert_equals(typeof ssrc.timestamp, 'number');
+    assert_true(ssrc.timestamp >= startTime);
+  }, '[' + kind + '] RTCRtpSynchronizationSource.timestamp is a number');
</ins><span class="cx"> 
</span><del>-    const ontrackPromise = new Promise(resolve => {
-      pc2.addEventListener('track', trackEvent => {
-        const { receiver } = trackEvent;
-        assert_true(receiver instanceof RTCRtpReceiver,
-          'Expect trackEvent.receiver to be instance of RTCRtpReceiver');
</del><ins>+  promise_test(async t => {
+    const receiver = await initiateSingleTrackCallAndReturnReceiver(t, kind);
+    // Wait for packets to start flowing.
+    await listenForSSRCs(t, receiver);
+    // Wait for 10 seconds.
+    await new Promise(resolve => t.step_timeout(resolve, 10000));
+    let earliestTimestamp = undefined;
+    let latestTimestamp = undefined;
+    for (const ssrc of await listenForSSRCs(t, receiver)) {
+      if (earliestTimestamp == undefined || earliestTimestamp > ssrc.timestamp)
+        earliestTimestamp = ssrc.timestamp;
+      if (latestTimestamp == undefined || latestTimestamp < ssrc.timestamp)
+        latestTimestamp = ssrc.timestamp;
+    }
+    assert_true(latestTimestamp - earliestTimestamp <= 10000);
+  }, '[' + kind + '] getSynchronizationSources() does not contain SSRCs ' +
+     'older than 10 seconds');
</ins><span class="cx"> 
</span><del>-        resolve(receiver);
-      });
-    });
</del><ins>+  promise_test(async t => {
+    const startTime = performance.timeOrigin + performance.now();
+    const receiver = await initiateSingleTrackCallAndReturnReceiver(t, kind);
+    const [ssrc] = await listenForSSRCs(t, receiver);
+    const endTime = performance.timeOrigin + performance.now();
+    assert_true(startTime <= ssrc.timestamp && ssrc.timestamp <= endTime);
+  }, '[' + kind + '] RTCRtpSynchronizationSource.timestamp is comparable to ' +
+     'performance.timeOrigin + performance.now()');
</ins><span class="cx"> 
</span><del>-    return getTrackFromUserMedia('audio')
-    .then(([track, mediaStream]) => {
-      pc1.addTrack(track, mediaStream);
-      exchangeIceCandidates(pc1, pc2);
-      return doSignalingHandshake(pc1, pc2);
-    })
-    .then(() => ontrackPromise)
-    .then(receiver => {
-      const syncSources = receiver.getSynchronizationSources();
-      assert_greater_than(syncSources.length, 0,
-        'Expect SSRCs to be available after RTP connection is established');
</del><ins>+  promise_test(async t => {
+    const receiver = await initiateSingleTrackCallAndReturnReceiver(t, kind);
+    const [ssrc] = await listenForSSRCs(t, receiver);
+    assert_equals(typeof ssrc.source, 'number');
+  }, '[' + kind + '] RTCRtpSynchronizationSource.source is a number');
+}
</ins><span class="cx"> 
</span><del>-      for(const ssrc of syncSources) {
-        assert_true(ssrc instanceof RTCRtpSynchronizationSource,
-          'Expect synchronizationSources elements to be instance of RTCSynchronizationSource');
</del><ins>+promise_test(async t => {
+  const receiver = await initiateSingleTrackCallAndReturnReceiver(t, 'audio');
+  const [ssrc] = await listenForSSRCs(t, receiver);
+  assert_equals(typeof ssrc.audioLevel, 'number');
+  assert_greater_than_equal(ssrc.audioLevel, 0);
+  assert_less_than_equal(ssrc.audioLevel, 1);
+}, '[audio-only] RTCRtpSynchronizationSource.audioLevel is a number [0, 1]');
</ins><span class="cx"> 
</span><del>-        assert_equals(typeof ssrc.timestamp, 'number',
-          'Expect ssrc.timestamp attribute to be DOMHighResTimeStamp');
</del><ins>+// This test only passes if the implementation is sending the RFC 6464 extension
+// header and the "vad" extension attribute is not "off", otherwise
+// voiceActivityFlag is absent. TODO: Consider moving this test to an
+// optional-to-implement subfolder?
+promise_test(async t => {
+  const receiver = await initiateSingleTrackCallAndReturnReceiver(t, 'audio');
+  const [ssrc] = await listenForSSRCs(t, receiver);
+  assert_equals(typeof ssrc.voiceActivityFlag, 'boolean');
+}, '[audio-only] RTCRtpSynchronizationSource.voiceActivityFlag is a boolean');
</ins><span class="cx"> 
</span><del>-        assert_true(Number.isInteger(ssrc.source) && ssrc.source > 0,
-          'Expect SSRC identifier to be unsigned long');
-
-        assert_true(Number.isInteger(ssrc.audioLevel) &&
-          ssrc.audioLevel >= 0 && ssrc.audioLevel <= 127,
-          'Expect ssrc.audioLevel to be byte value from 0-127.');
-
-        if(ssrc.voiceActivityFlag !== null) {
-          assert_equals(typeof ssrc.voiceActivityFlag, 'boolean',
-            'Expect ssrc.voiceActivity to be either null or boolean');
-        }
-      }
-    });
-  }, `getContributingSources() should return list of CSRC after connection is established`);
-
</del><span class="cx"> </script>
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpSenderreplaceTrackhttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-replaceTrack.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-replaceTrack.https.html    2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-replaceTrack.https.html       2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -3,6 +3,7 @@
</span><span class="cx"> <title>RTCRtpSender.prototype.replaceTrack</title>
</span><span class="cx"> <script src="/resources/testharness.js"></script>
</span><span class="cx"> <script src="/resources/testharnessreport.js"></script>
</span><ins>+<script src="RTCPeerConnection-helper.js"></script>
</ins><span class="cx"> <script>
</span><span class="cx">   'use strict';
</span><span class="cx"> 
</span><span class="lines">@@ -30,7 +31,7 @@
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track] = stream.getTracks();
</span><span class="cx"> 
</span><span class="lines">@@ -51,7 +52,7 @@
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({video: true});
</del><ins>+    const stream = await getNoiseStream({video: true});
</ins><span class="cx">     t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track] = stream.getTracks();
</span><span class="cx"> 
</span><span class="lines">@@ -70,7 +71,7 @@
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track] = stream.getTracks();
</span><span class="cx"> 
</span><span class="lines">@@ -91,7 +92,7 @@
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track] = stream.getTracks();
</span><span class="cx"> 
</span><span class="lines">@@ -108,10 +109,10 @@
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><del>-    const stream1 = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream1 = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stream1.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track1] = stream1.getTracks();
</span><del>-    const stream2 = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream2 = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stream2.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track2] = stream2.getTracks();
</span><span class="cx"> 
</span><span class="lines">@@ -129,7 +130,7 @@
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track] = stream.getTracks();
</span><span class="cx"> 
</span><span class="lines">@@ -158,7 +159,7 @@
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track] = stream.getTracks();
</span><span class="cx"> 
</span><span class="lines">@@ -190,10 +191,10 @@
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><del>-    const stream1 = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream1 = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stream1.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track1] = stream1.getTracks();
</span><del>-    const stream2 = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream2 = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stream2.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track2] = stream1.getTracks();
</span><span class="cx"> 
</span><span class="lines">@@ -226,10 +227,10 @@
</span><span class="cx">   promise_test(async t => {
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><del>-    const stream1 = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream1 = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stream1.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track1] = stream1.getTracks();
</span><del>-    const stream2 = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream2 = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stream2.getTracks().forEach(track => track.stop()));
</span><span class="cx">     const [track2] = stream1.getTracks();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpSendertransporthttpsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-transport.https-expected.txt (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-transport.https-expected.txt                               (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-transport.https-expected.txt  2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+
+FAIL RTCRtpSender.transport is null when unconnected assert_equals: expected (object) null but got (undefined) undefined
+FAIL RTCRtpSender/receiver.transport has a value when connected promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'sender.transport.iceTransport')"
+FAIL RTCRtpSender/receiver.transport at the right time, with bundle policy balanced assert_equals: expected (object) null but got (undefined) undefined
+FAIL RTCRtpSender/receiver.transport at the right time, with bundle policy max-bundle assert_equals: expected (object) null but got (undefined) undefined
+FAIL RTCRtpSender/receiver.transport at the right time, with bundle policy max-compat assert_equals: expected (object) null but got (undefined) undefined
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpSendertransporthttpshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-transport.https.html (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-transport.https.html                               (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-transport.https.html  2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,90 @@
</span><ins>+<!doctype html>
+<meta charset=utf-8>
+<meta name="timeout" content="long">
+<title>RTCRtpSender.transport</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="dictionary-helper.js"></script>
+<script src="RTCPeerConnection-helper.js"></script>
+<script>
+  'use strict';
+
+  // Spec link: http://w3c.github.io/webrtc-pc/#dom-rtcrtpsender-transport
+  promise_test(async t => {
+    const caller = new RTCPeerConnection();
+    t.add_cleanup(() => caller.close());
+    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
+    const [track] = stream.getTracks();
+    const sender = caller.addTrack(track);
+    assert_equals(sender.transport, null);
+  }, 'RTCRtpSender.transport is null when unconnected');
+
+  // Test for the simple/happy path of connecting a single track
+  promise_test(async t => {
+    const caller = new RTCPeerConnection();
+    t.add_cleanup(() => caller.close());
+    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
+    const [track] = stream.getTracks();
+    const sender = caller.addTrack(track);
+    const callee = new RTCPeerConnection();
+    t.add_cleanup(() => callee.close());
+    exchangeIceCandidates(caller, callee);
+    await exchangeOfferAndListenToOntrack(t, caller, callee);
+    assert_not_equals(sender.transport, null);
+    const [transceiver] = caller.getTransceivers();
+    assert_equals(transceiver.sender.transport,
+                  transceiver.receiver.transport);
+    assert_not_equals(sender.transport.iceTransport, null);
+  }, 'RTCRtpSender/receiver.transport has a value when connected');
+
+  // Test with multiple tracks, and checking details of when things show up
+  // for different bundle policies.
+  for (let bundle_policy of ['balanced', 'max-bundle', 'max-compat']) {
+    promise_test(async t => {
+        const caller = new RTCPeerConnection({bundlePolicy: bundle_policy});
+      t.add_cleanup(() => caller.close());
+      const stream = await navigator.mediaDevices.getUserMedia(
+          {audio: true, video:true});
+      t.add_cleanup(() => stream.getTracks().forEach(track => track.stop()));
+      const [track1, track2] = stream.getTracks();
+      const sender1 = caller.addTrack(track1);
+      const sender2 = caller.addTrack(track2);
+      const callee = new RTCPeerConnection();
+      t.add_cleanup(() => callee.close());
+      exchangeIceCandidates(caller, callee);
+      const offer = await caller.createOffer();
+      assert_equals(sender1.transport, null);
+      assert_equals(sender2.transport, null);
+      await caller.setLocalDescription(offer);
+      assert_not_equals(sender1.transport, null);
+      assert_not_equals(sender2.transport, null);
+      const [caller_transceiver1, caller_transceiver2] = caller.getTransceivers();
+      assert_equals(sender1.transport, caller_transceiver1.sender.transport);
+      if (bundle_policy == 'max-bundle') {
+        assert_equals(caller_transceiver1.sender.transport,
+                      caller_transceiver2.sender.transport);
+      } else {
+        assert_not_equals(caller_transceiver1.sender.transport,
+                          caller_transceiver2.sender.transport);
+      }
+      await callee.setRemoteDescription(offer);
+      const [callee_transceiver1, callee_transceiver2] = callee.getTransceivers();
+      // According to spec, setRemoteDescription only updates the transports
+      // if the remote description is an answer.
+      assert_equals(callee_transceiver1.receiver.transport, null);
+      assert_equals(callee_transceiver2.receiver.transport, null);
+      const answer = await callee.createAnswer();
+      await callee.setLocalDescription(answer);
+      assert_not_equals(callee_transceiver1.receiver.transport, null);
+      assert_not_equals(callee_transceiver2.receiver.transport, null);
+      // At this point, bundle should have kicked in.
+      assert_equals(callee_transceiver1.receiver.transport,
+                    callee_transceiver2.receiver.transport);
+      await caller.setRemoteDescription(answer);
+      assert_equals(caller_transceiver1.receiver.transport,
+                    caller_transceiver2.receiver.transport);
+    }, 'RTCRtpSender/receiver.transport at the right time, with bundle policy ' + bundle_policy);
+  }
+ </script>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpTransceiverstopexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver-stop-expected.txt (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver-stop-expected.txt                             (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver-stop-expected.txt        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+
+PASS A transceiver added and stopped before the initial offer generation should not trigger an offer m-section generation 
+PASS During renegotiation, adding and stopping a transceiver should not trigger a renegotiated offer m-section generation 
+PASS A stopped sendonly transceiver should generate an inactive m-section in the offer 
+PASS A stopped inactive transceiver should generate an inactive m-section in the offer 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpTransceiverstophtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver-stop.html (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver-stop.html                             (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver-stop.html        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+<!doctype html>
+<meta charset=utf-8>
+<title>RTCRtpTransceiver.prototype.stop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="RTCPeerConnection-helper.js"></script>
+<script>
+// FIXME: Add a test adding a transceiver, stopping it and trying to create an empty offer.
+
+promise_test(async (t)=> {
+    const pc1 = new RTCPeerConnection();
+    t.add_cleanup(() => pc1.close());
+
+    pc1.addTransceiver("audio", { direction: "sendonly" });
+    pc1.addTransceiver("video");
+    pc1.getTransceivers()[0].stop();
+
+    const offer = await pc1.createOffer();
+
+    assert_false(offer.sdp.includes("m=audio"), "offer should not contain an audio m-section");
+    assert_true(offer.sdp.includes("m=video"), "offer should contain a video m-section");
+}, "A transceiver added and stopped before the initial offer generation should not trigger an offer m-section generation");
+
+promise_test(async (t)=> {
+    const pc1 = new RTCPeerConnection();
+    const pc2 = new RTCPeerConnection();
+    t.add_cleanup(() => pc1.close());
+    t.add_cleanup(() => pc2.close());
+
+    pc1.addTransceiver("audio");
+
+    await exchangeOfferAnswer(pc1, pc2);
+
+    pc1.addTransceiver("video");
+
+    pc1.getTransceivers()[0].stop();
+    pc1.getTransceivers()[1].stop();
+
+    const offer = await pc1.createOffer();
+
+    assert_true(offer.sdp.includes("m=audio"), "offer should contain an audio m-section");
+    assert_true(offer.sdp.includes("m=audio 0"), "The audio m-section should be rejected");
+
+    assert_false(offer.sdp.includes("m=video"), "offer should not contain a video m-section");
+}, "During renegotiation, adding and stopping a transceiver should not trigger a renegotiated offer m-section generation");
+
+promise_test(async (t)=> {
+    const pc1 = new RTCPeerConnection();
+    const pc2 = new RTCPeerConnection();
+    t.add_cleanup(() => pc1.close());
+    t.add_cleanup(() => pc2.close());
+
+    pc1.addTransceiver("audio");
+
+    await exchangeOfferAnswer(pc1, pc2);
+
+    pc1.getTransceivers()[0].direction = "sendonly";
+    pc1.getTransceivers()[0].stop();
+
+    const offer = await pc1.createOffer();
+
+    assert_true(offer.sdp.includes("a=sendonly"), "The audio m-section should be sendonly");
+}, "A stopped sendonly transceiver should generate an inactive m-section in the offer");
+
+promise_test(async (t)=> {
+    const pc1 = new RTCPeerConnection();
+    const pc2 = new RTCPeerConnection();
+    t.add_cleanup(() => pc1.close());
+    t.add_cleanup(() => pc2.close());
+
+    pc1.addTransceiver("audio");
+
+    await exchangeOfferAnswer(pc1, pc2);
+
+    pc1.getTransceivers()[0].direction = "inactive";
+    pc1.getTransceivers()[0].stop();
+
+    const offer = await pc1.createOffer();
+
+    assert_true(offer.sdp.includes("a=inactive"), "The audio m-section should be inactive");
+}, "A stopped inactive transceiver should generate an inactive m-section in the offer");
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpTransceiverhttpsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver.https-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver.https-expected.txt    2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver.https-expected.txt       2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -5,10 +5,12 @@
</span><span class="cx"> PASS checkAddTransceiverWithTrack 
</span><span class="cx"> PASS checkAddTransceiverWithAddTrack 
</span><span class="cx"> PASS checkAddTransceiverWithDirection 
</span><ins>+FAIL checkMsidNoTrackId promise_test: Unhandled rejection with value: object "SyntaxError: Expects 2 fields."
</ins><span class="cx"> PASS checkAddTransceiverWithSetRemoteOfferSending 
</span><span class="cx"> PASS checkAddTransceiverWithSetRemoteOfferNoSend 
</span><span class="cx"> PASS checkAddTransceiverBadKind 
</span><span class="cx"> PASS checkNoMidOffer 
</span><ins>+PASS checkNoMidAnswer 
</ins><span class="cx"> PASS checkSetDirection 
</span><span class="cx"> PASS checkCurrentDirection 
</span><span class="cx"> PASS checkSendrecvWithNoSendTrack 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCRtpTransceiverhttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver.https.html    2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver.https.html       2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -215,7 +215,7 @@
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true, video: true});
</del><ins>+    const stream = await getNoiseStream({audio: true, video: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const audio = stream.getAudioTracks()[0];
</span><span class="cx">     const video = stream.getVideoTracks()[0];
</span><span class="lines">@@ -248,7 +248,7 @@
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true, video: true});
</del><ins>+    const stream = await getNoiseStream({audio: true, video: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const audio = stream.getAudioTracks()[0];
</span><span class="cx">     const video = stream.getVideoTracks()[0];
</span><span class="lines">@@ -311,7 +311,7 @@
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTransceiver(track, {streams: [stream]});
</span><span class="lines">@@ -346,7 +346,7 @@
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTransceiver(track);
</span><span class="lines">@@ -387,6 +387,26 @@
</span><span class="cx">     hasProps(pc.getTransceivers(), []);
</span><span class="cx">   };
</span><span class="cx"> 
</span><ins>+  const checkMsidNoTrackId = async t => {
+    const pc1 = new RTCPeerConnection();
+    const pc2 = new RTCPeerConnection();
+    t.add_cleanup(() => pc1.close());
+    t.add_cleanup(() => pc2.close());
+    const stream = await getNoiseStream({audio: true});
+    t.add_cleanup(() => stopTracks(stream));
+    const track = stream.getAudioTracks()[0];
+    pc1.addTrack(track, stream);
+    const offer = await pc1.createOffer();
+    await pc1.setLocalDescription(offer);
+    // Remove track-id from msid
+    offer.sdp = offer.sdp.replace(/(a=msid:[^ \t]+).*\r\n/g, "$1\r\n");
+    assert_true(offer.sdp.includes(`a=msid:${stream.id}\r\n`));
+    await pc2.setRemoteDescription(offer);
+    const answer = await pc2.createAnswer();
+    await pc1.setRemoteDescription(answer);
+    await pc2.setLocalDescription(answer);
+  };
+
</ins><span class="cx">   const checkNoMidOffer = async t => {
</span><span class="cx">     const pc1 = new RTCPeerConnection();
</span><span class="cx">     const pc2 = new RTCPeerConnection();
</span><span class="lines">@@ -393,7 +413,7 @@
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track, stream);
</span><span class="lines">@@ -421,6 +441,42 @@
</span><span class="cx">     await pc1.setRemoteDescription(answer);
</span><span class="cx">   };
</span><span class="cx"> 
</span><ins>+  const checkNoMidAnswer = async t => {
+    const pc1 = new RTCPeerConnection();
+    const pc2 = new RTCPeerConnection();
+    t.add_cleanup(() => pc1.close());
+    t.add_cleanup(() => pc2.close());
+
+    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
+    t.add_cleanup(() => stopTracks(stream));
+    const track = stream.getAudioTracks()[0];
+    pc1.addTrack(track, stream);
+
+    const offer = await pc1.createOffer();
+    await pc1.setLocalDescription(offer);
+    await pc2.setRemoteDescription(offer);
+    let answer = await pc2.createAnswer();
+    // Remove mid attr
+    answer.sdp = answer.sdp.replace("a=mid:", "a=unknownattr:");
+    // Remove group attr also
+    answer.sdp = answer.sdp.replace("a=group:", "a=unknownattr:");
+    await pc1.setRemoteDescription(answer);
+
+    hasPropsAndUniqueMids(pc1.getTransceivers(),
+      [
+        {
+          receiver: {track: {kind: "audio"}},
+          sender: {track: {kind: "audio"}},
+          direction: "sendrecv",
+          currentDirection: "sendonly",
+          stopped: false
+        }
+      ]);
+
+    const reoffer = await pc1.createOffer();
+    await pc1.setLocalDescription(reoffer);
+  };
+
</ins><span class="cx">   const checkAddTransceiverNoTrackDoesntPair = async t => {
</span><span class="cx">     const pc1 = new RTCPeerConnection();
</span><span class="cx">     const pc2 = new RTCPeerConnection();
</span><span class="lines">@@ -454,7 +510,7 @@
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx">     pc1.addTransceiver("audio");
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc2.addTransceiver(track);
</span><span class="lines">@@ -484,10 +540,10 @@
</span><span class="cx">     pc1.addTransceiver("audio");
</span><span class="cx">     pc2.addTransceiver("audio");
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><del>-    pc2.getTransceivers()[0].sender.replaceTrack(track);
</del><ins>+    await pc2.getTransceivers()[0].sender.replaceTrack(track);
</ins><span class="cx"> 
</span><span class="cx">     const offer = await pc1.createOffer();
</span><span class="cx">     const trackEvents = await setRemoteDescriptionReturnTrackEvents(pc2, offer);
</span><span class="lines">@@ -514,7 +570,7 @@
</span><span class="cx">     pc1.addTransceiver("audio");
</span><span class="cx">     pc2.addTransceiver("audio");
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc2.addTrack(track, stream);
</span><span class="lines">@@ -542,7 +598,7 @@
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx">     pc1.addTransceiver("audio");
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc2.addTrack(track, stream);
</span><span class="lines">@@ -570,11 +626,11 @@
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx">     pc1.addTransceiver("audio");
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc2.addTrack(track, stream);
</span><del>-    pc2.getTransceivers()[0].sender.replaceTrack(null);
</del><ins>+    await pc2.getTransceivers()[0].sender.replaceTrack(null);
</ins><span class="cx"> 
</span><span class="cx">     const offer = await pc1.createOffer();
</span><span class="cx">     const trackEvents = await setRemoteDescriptionReturnTrackEvents(pc2, offer);
</span><span class="lines">@@ -597,7 +653,7 @@
</span><span class="cx">     const pc2 = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track, stream);
</span><span class="lines">@@ -665,7 +721,7 @@
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><span class="cx">     pc.addTransceiver("audio");
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     const audio = stream.getAudioTracks()[0];
</span><span class="cx">     let sender = pc.addTrack(audio, stream);
</span><span class="cx">     pc.removeTrack(sender);
</span><span class="lines">@@ -685,7 +741,7 @@
</span><span class="cx">     const pc2 = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true, video: true});
</del><ins>+    const stream = await getNoiseStream({audio: true, video: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const audio = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(audio, stream);
</span><span class="lines">@@ -840,7 +896,7 @@
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track, stream);
</span><span class="lines">@@ -942,7 +998,7 @@
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTransceiver("audio");
</span><span class="lines">@@ -1006,7 +1062,7 @@
</span><span class="cx">   const checkMute = async t => {
</span><span class="cx">     const pc1 = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><del>-    const stream1 = await navigator.mediaDevices.getUserMedia({audio: true, video: true});
</del><ins>+    const stream1 = await getNoiseStream({audio: true, video: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream1));
</span><span class="cx">     const audio1 = stream1.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(audio1, stream1);
</span><span class="lines">@@ -1020,7 +1076,7 @@
</span><span class="cx"> 
</span><span class="cx">     const pc2 = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><del>-    const stream2 = await navigator.mediaDevices.getUserMedia({audio: true, video: true});
</del><ins>+    const stream2 = await getNoiseStream({audio: true, video: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream2));
</span><span class="cx">     const audio2 = stream2.getAudioTracks()[0];
</span><span class="cx">     pc2.addTrack(audio2, stream2);
</span><span class="lines">@@ -1132,7 +1188,7 @@
</span><span class="cx">   const checkStop = async t => {
</span><span class="cx">     const pc1 = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track, stream);
</span><span class="lines">@@ -1177,7 +1233,7 @@
</span><span class="cx">                         transceiver.sender.getParameters()),
</span><span class="cx">                 "InvalidStateError", "setParameters on stopped transceiver");
</span><span class="cx"> 
</span><del>-    const stream2 = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream2 = await getNoiseStream({audio: true});
</ins><span class="cx">     const track2 = stream.getAudioTracks()[0];
</span><span class="cx">     checkThrows(() => transceiver.sender.replaceTrack(track2),
</span><span class="cx">                 "InvalidStateError", "replaceTrack on stopped transceiver");
</span><span class="lines">@@ -1231,7 +1287,7 @@
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track, stream);
</span><span class="lines">@@ -1301,7 +1357,7 @@
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track, stream);
</span><span class="lines">@@ -1371,7 +1427,7 @@
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track, stream);
</span><span class="lines">@@ -1406,7 +1462,7 @@
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track, stream);
</span><span class="lines">@@ -1476,7 +1532,7 @@
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track, stream);
</span><span class="lines">@@ -1546,7 +1602,7 @@
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track, stream);
</span><span class="lines">@@ -1569,7 +1625,7 @@
</span><span class="cx">     const pc = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc.addTrack(track, stream);
</span><span class="lines">@@ -1590,7 +1646,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Verify that rollback doesn't stomp things it should not
</span><span class="cx">     pc.getTransceivers()[0].direction = "sendonly";
</span><del>-    const stream2 = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream2 = await getNoiseStream({audio: true});
</ins><span class="cx">     const track2 = stream2.getAudioTracks()[0];
</span><span class="cx">     await pc.getTransceivers()[0].sender.replaceTrack(track2);
</span><span class="cx"> 
</span><span class="lines">@@ -1621,7 +1677,7 @@
</span><span class="cx">     const pc1 = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx"> 
</span><del>-    const audioStream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const audioStream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(audioStream));
</span><span class="cx">     const audioTrack = audioStream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(audioTrack, audioStream);
</span><span class="lines">@@ -1629,7 +1685,7 @@
</span><span class="cx">     const pc2 = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const videoStream = await navigator.mediaDevices.getUserMedia({video: true});
</del><ins>+    const videoStream = await getNoiseStream({video: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(videoStream));
</span><span class="cx">     const videoTrack = videoStream.getVideoTracks()[0];
</span><span class="cx">     pc2.addTrack(videoTrack, videoStream);
</span><span class="lines">@@ -1700,7 +1756,7 @@
</span><span class="cx">     const pc1 = new RTCPeerConnection();
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track, stream);
</span><span class="lines">@@ -1757,7 +1813,7 @@
</span><span class="cx">     const mid0 = pc2.getTransceivers()[0].mid;
</span><span class="cx"> 
</span><span class="cx">     // Give pc2 a track with replaceTrack
</span><del>-    const stream2 = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream2 = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream2));
</span><span class="cx">     const track2 = stream2.getAudioTracks()[0];
</span><span class="cx">     await pc2.getTransceivers()[0].sender.replaceTrack(track2);
</span><span class="lines">@@ -1917,7 +1973,7 @@
</span><span class="cx">     t.add_cleanup(() => pc1.close());
</span><span class="cx">     t.add_cleanup(() => pc2.close());
</span><span class="cx"> 
</span><del>-    const stream = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream));
</span><span class="cx">     const track = stream.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track, stream);
</span><span class="lines">@@ -1953,7 +2009,7 @@
</span><span class="cx">       ]);
</span><span class="cx"> 
</span><span class="cx">     // Check that m-section is reused on both ends
</span><del>-    const stream2 = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream2 = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream2));
</span><span class="cx">     const track2 = stream2.getAudioTracks()[0];
</span><span class="cx"> 
</span><span class="lines">@@ -2024,7 +2080,7 @@
</span><span class="cx">     // new one for the new track)
</span><span class="cx">     const stoppedMid1 = pc1.getTransceivers()[1].mid;
</span><span class="cx">     pc1.getTransceivers()[1].stop();
</span><del>-    const stream3 = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream3 = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream3));
</span><span class="cx">     const track3 = stream3.getAudioTracks()[0];
</span><span class="cx">     pc1.addTrack(track3, stream3);
</span><span class="lines">@@ -2094,7 +2150,7 @@
</span><span class="cx">       ]);
</span><span class="cx"> 
</span><span class="cx">     // Add _another_ track; this should reuse the disabled m-section
</span><del>-    const stream4 = await navigator.mediaDevices.getUserMedia({audio: true});
</del><ins>+    const stream4 = await getNoiseStream({audio: true});
</ins><span class="cx">     t.add_cleanup(() => stopTracks(stream4));
</span><span class="cx">     const track4 = stream4.getAudioTracks()[0];
</span><span class="cx">     pc2.addTrack(track4, stream4);
</span><span class="lines">@@ -2131,10 +2187,12 @@
</span><span class="cx">   checkAddTransceiverWithTrack,
</span><span class="cx">   checkAddTransceiverWithAddTrack,
</span><span class="cx">   checkAddTransceiverWithDirection,
</span><ins>+  checkMsidNoTrackId,
</ins><span class="cx">   checkAddTransceiverWithSetRemoteOfferSending,
</span><span class="cx">   checkAddTransceiverWithSetRemoteOfferNoSend,
</span><span class="cx">   checkAddTransceiverBadKind,
</span><span class="cx">   checkNoMidOffer,
</span><ins>+  checkNoMidAnswer,
</ins><span class="cx">   checkSetDirection,
</span><span class="cx">   checkCurrentDirection,
</span><span class="cx">   checkSendrecvWithNoSendTrack,
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCTrackEventconstructorhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-constructor.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-constructor.html  2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-constructor.html     2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -41,7 +41,7 @@
</span><span class="cx">     assert_equals(trackEvent.receiver, receiver);
</span><span class="cx">     assert_equals(trackEvent.track, track);
</span><span class="cx">     assert_array_equals(trackEvent.streams, []);
</span><del>-    assert_equals(trackEvent.streams, trackEvent.streams); // [SameObject]
</del><ins>+    assert_equals(trackEvent.streams, trackEvent.streams, '[SameObject]');
</ins><span class="cx">     assert_equals(trackEvent.transceiver, transceiver);
</span><span class="cx"> 
</span><span class="cx">     assert_equals(trackEvent.type, 'track');
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCTrackEventfireexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-fire-expected.txt (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-fire-expected.txt                         (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-fire-expected.txt    2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+
+Harness Error (TIMEOUT), message = null
+
+TIMEOUT Applying a remote description with removed msid should trigger firing a removetrack event on the corresponding stream Test timed out
+NOTRUN Applying a remote description with a new msid should trigger firing an event with populated streams 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcRTCTrackEventfirehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-fire.html (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-fire.html                         (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-fire.html    2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,80 @@
</span><ins>+<!doctype html>
+<meta charset=utf-8>
+<title>Change of msid in remote description should trigger related track events</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const sdpBase =`v=0
+o=- 5511237691691746 2 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=group:BUNDLE 0
+a=ice-options:trickle
+a=ice-lite
+a=msid-semantic:WMS *
+m=audio 9 UDP/TLS/RTP/SAVPF 111 103 9 102 0 8 105 13 110 113 126
+c=IN IP6 ::
+a=rtcp:9 IN IP6 ::
+a=rtcp-mux
+a=mid:0
+a=sendrecv
+a=ice-ufrag:z0i8R3C9C4hPRWls
+a=ice-pwd:O7bPpOFAqasqoidV4yxnFVbc
+a=ice-lite
+a=fingerprint:sha-256 B7:9C:0D:C9:D1:42:57:97:82:4D:F9:B7:93:75:49:C3:42:21:5A:DD:9C:B5:ED:53:53:F0:B4:C8:AE:88:7A:E7
+a=setup:actpass
+a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
+a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
+a=rtpmap:0 PCMU/8000`;
+
+const sdp0 = sdpBase + `
+`;
+
+const sdp1 = sdpBase + `
+a=msid:1 2
+a=ssrc:3 cname:4
+a=ssrc:3 msid:1 2
+`;
+
+async function applyRemoteDescriptionAndReturnRemoteTrackAndStreams(pc, sdp)
+{
+    const testTrackPromise = new Promise(resolve  => {
+        pc.ontrack = (event) => { resolve([event.track, event.streams]); };
+    });
+    await pc.setRemoteDescription({type: 'offer', sdp: sdp});
+    return testTrackPromise;
+}
+
+promise_test(async test => {
+    const pc = new RTCPeerConnection();
+    test.add_cleanup(() => pc.close());
+
+    const [track, streams] = await applyRemoteDescriptionAndReturnRemoteTrackAndStreams(pc, sdp1);
+    assert_equals(streams.length, 1, "track event has a stream");
+    assert_equals(streams[0].id, "1", "msid should match");
+    const stream = streams[0];
+
+    await pc.setLocalDescription(await pc.createAnswer());
+
+    const testTrackPromise = new Promise((resolve) => { stream.onremovetrack = resolve; });
+    await pc.setRemoteDescription({type: 'offer', 'sdp': sdp0});
+    await testTrackPromise;
+
+    assert_equals(stream.getAudioTracks().length, 0, "stream should be empty");
+}, "Applying a remote description with removed msid should trigger firing a removetrack event on the corresponding stream");
+
+promise_test(async test => {
+    const pc = new RTCPeerConnection();
+    test.add_cleanup(() => pc.close());
+
+    let [track0, streams0] = await applyRemoteDescriptionAndReturnRemoteTrackAndStreams(pc, sdp0);
+
+    await pc.setLocalDescription(await pc.createAnswer());
+
+    let [track1, streams1] = await applyRemoteDescriptionAndReturnRemoteTrackAndStreams(pc, sdp1);
+
+    assert_equals(streams1.length, 1, "track event has a stream");
+    assert_equals(streams1[0].id, "1", "msid should match");
+    assert_equals(streams1[0].getTracks()[0], track0, "track should match");
+}, "Applying a remote description with a new msid should trigger firing an event with populated streams");
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcgetstatsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/getstats-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/getstats-expected.txt   2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/getstats-expected.txt      2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -3,125 +3,8 @@
</span><span class="cx"> Retrieved stats info
</span><span class="cx"> 
</span><span class="cx">   
</span><del>-{
-  "RTCCertificate_E6:B4:F7:7C:4A:9E:86:FB:65:54:55:DE:E7:04:81:CA:A5:FD:21:9F:B2:92:EE:21:EF:C2:44:E7:1D:4E:E8:86": {
-    "id": "RTCCertificate_E6:B4:F7:7C:4A:9E:86:FB:65:54:55:DE:E7:04:81:CA:A5:FD:21:9F:B2:92:EE:21:EF:C2:44:E7:1D:4E:E8:86",
-    "timestamp": 1542138647360.0002,
-    "type": "certificate",
-    "base64Certificate": "MIIBFzCBvaADAgECAgkAmUOKhXabECcwCgYIKoZIzj0EAwIwETEPMA0GA1UEAwwGV2ViUlRDMB4XDTE4MTExMjE5NTA0N1oXDTE4MTIxMzE5NTA0N1owETEPMA0GA1UEAwwGV2ViUlRDMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpv51bCUk/FtnnFXwLUaHKwVoBX/fjpq0wXV5QuxjLd4GLBJb1nD014bmUlw63Pizl4nRoQBIfyOFAdbW9UUKHzAKBggqhkjOPQQDAgNJADBGAiEAjhJk8wni+BCZZeHqX0nGwANgtIm1ZwAywWaa5+selbICIQCwGDEehbP+MfZ62tfej4avrohy4ykO5xC1+5fL0zmZQQ==",
-    "fingerprint": "E6:B4:F7:7C:4A:9E:86:FB:65:54:55:DE:E7:04:81:CA:A5:FD:21:9F:B2:92:EE:21:EF:C2:44:E7:1D:4E:E8:86",
-    "fingerprintAlgorithm": "sha-256"
-  },
-  "RTCCertificate_FF:81:96:D2:F0:D3:75:95:AE:08:99:64:8A:95:F3:1F:27:51:38:3E:83:C5:2D:17:1D:41:5B:F5:36:1E:22:AC": {
-    "id": "RTCCertificate_FF:81:96:D2:F0:D3:75:95:AE:08:99:64:8A:95:F3:1F:27:51:38:3E:83:C5:2D:17:1D:41:5B:F5:36:1E:22:AC",
-    "timestamp": 1542138647360.0002,
-    "type": "certificate",
-    "base64Certificate": "MIIBFjCBvaADAgECAgkA0YyL/axVxyUwCgYIKoZIzj0EAwIwETEPMA0GA1UEAwwGV2ViUlRDMB4XDTE4MTExMjE5NTA0N1oXDTE4MTIxMzE5NTA0N1owETEPMA0GA1UEAwwGV2ViUlRDMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHUTz7lUs8fxFqSOEMl04JHlyj2PItG98Q6C/W2+vwKlflcVRV3wGUsRLwwENbuDEH95U4VY0F7KWNgqG8W5eEzAKBggqhkjOPQQDAgNIADBFAiBiJZQlXIgiIsCUAoJv8uzAsUl/US6MiknEkA9OABXDbwIhANaTPbugE7/Ly/9R0zqlu21V1YfF/v6H34oX/wiOyf2p",
-    "fingerprint": "FF:81:96:D2:F0:D3:75:95:AE:08:99:64:8A:95:F3:1F:27:51:38:3E:83:C5:2D:17:1D:41:5B:F5:36:1E:22:AC",
-    "fingerprintAlgorithm": "sha-256"
-  },
-  "RTCDataChannel_1": {
-    "id": "RTCDataChannel_1",
-    "timestamp": 1542138647360.0002,
-    "type": "data-channel",
-    "bytesReceived": 0,
-    "bytesSent": 0,
-    "datachannelid": 1,
-    "label": "channel",
-    "messagesReceived": 0,
-    "messagesSent": 0,
-    "protocol": "",
-    "state": "open"
-  },
-  "RTCIceCandidatePair_z6z3iTpo_9P4G3ojB": {
-    "id": "RTCIceCandidatePair_z6z3iTpo_9P4G3ojB",
-    "timestamp": 1542138647360.0002,
-    "type": "candidate-pair",
-    "bytesReceived": 694,
-    "bytesSent": 1309,
-    "currentRoundTripTime": 0.003,
-    "localCandidateId": "RTCIceCandidate_z6z3iTpo",
-    "nominated": true,
-    "priority": 9079290933572287000,
-    "remoteCandidateId": "RTCIceCandidate_9P4G3ojB",
-    "requestsReceived": 1,
-    "requestsSent": 1,
-    "responsesReceived": 1,
-    "responsesSent": 1,
-    "state": "succeeded",
-    "totalRoundTripTime": 0.003,
-    "transportId": "RTCTransport_0_1",
-    "writable": true
-  },
-  "RTCIceCandidatePair_z6z3iTpo_OlinD0xX": {
-    "id": "RTCIceCandidatePair_z6z3iTpo_OlinD0xX",
-    "timestamp": 1542138647360.0002,
-    "type": "candidate-pair",
-    "bytesReceived": 0,
-    "bytesSent": 0,
-    "localCandidateId": "RTCIceCandidate_z6z3iTpo",
-    "nominated": false,
-    "priority": 9079290933572287000,
-    "remoteCandidateId": "RTCIceCandidate_OlinD0xX",
-    "requestsReceived": 0,
-    "requestsSent": 0,
-    "responsesReceived": 0,
-    "responsesSent": 0,
-    "state": "waiting",
-    "totalRoundTripTime": 0,
-    "transportId": "RTCTransport_0_1",
-    "writable": false
-  },
-  "RTCIceCandidate_9P4G3ojB": {
-    "id": "RTCIceCandidate_9P4G3ojB",
-    "timestamp": 1542138647360.0002,
-    "type": "remote-candidate",
-    "candidateType": "host",
-    "deleted": false,
-    "port": 62426,
-    "priority": 2113937151,
-    "protocol": "udp",
-    "transportId": "RTCTransport_0_1"
-  },
-  "RTCIceCandidate_OlinD0xX": {
-    "id": "RTCIceCandidate_OlinD0xX",
-    "timestamp": 1542138647360.0002,
-    "type": "remote-candidate",
-    "candidateType": "host",
-    "deleted": false,
-    "port": 54933,
-    "priority": 2113937151,
-    "protocol": "udp",
-    "transportId": "RTCTransport_0_1"
-  },
-  "RTCIceCandidate_z6z3iTpo": {
-    "id": "RTCIceCandidate_z6z3iTpo",
-    "timestamp": 1542138647360.0002,
-    "type": "local-candidate",
-    "candidateType": "host",
-    "deleted": false,
-    "port": 53616,
-    "priority": 2113937151,
-    "protocol": "udp",
-    "transportId": "RTCTransport_0_1"
-  },
-  "RTCPeerConnection": {
-    "id": "RTCPeerConnection",
-    "timestamp": 1542138647360.0002,
-    "type": "peer-connection",
-    "dataChannelsClosed": 0,
-    "dataChannelsOpened": 1
-  },
-  "RTCTransport_0_1": {
-    "id": "RTCTransport_0_1",
-    "timestamp": 1542138647360.0002,
-    "type": "transport",
-    "bytesReceived": 694,
-    "bytesSent": 1309,
-    "localCertificateId": "RTCCertificate_E6:B4:F7:7C:4A:9E:86:FB:65:54:55:DE:E7:04:81:CA:A5:FD:21:9F:B2:92:EE:21:EF:C2:44:E7:1D:4E:E8:86",
-    "remoteCertificateId": "RTCCertificate_FF:81:96:D2:F0:D3:75:95:AE:08:99:64:8A:95:F3:1F:27:51:38:3E:83:C5:2D:17:1D:41:5B:F5:36:1E:22:AC",
-    "selectedCandidatePairId": "RTCIceCandidatePair_z6z3iTpo_9P4G3ojB"
-  }
-}
</del><ins>+  
</ins><span class="cx"> 
</span><span class="cx">   
</span><ins>+
+  
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcgetstatshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/getstats.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/getstats.html   2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/getstats.html      2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -12,6 +12,7 @@
</span><span class="cx">   <div id="log"></div>
</span><span class="cx">   <h2>Retrieved stats info</h2>
</span><span class="cx">   <pre>
</span><ins>+  <input type="button" onclick="showStats()" value="Show stats"></input>
</ins><span class="cx">   <div id="stats">
</span><span class="cx">   </div>
</span><span class="cx">   </pre>
</span><span class="lines">@@ -21,7 +22,7 @@
</span><span class="cx">   <script src="/resources/testharnessreport.js"></script>
</span><span class="cx">   <script type="text/javascript">
</span><span class="cx">   var test = async_test('Can get stats from a basic WebRTC call.');
</span><del>-
</del><ins>+  var statsToShow;
</ins><span class="cx">   var gFirstConnection = null;
</span><span class="cx">   var gSecondConnection = null;
</span><span class="cx"> 
</span><span class="lines">@@ -56,13 +57,11 @@
</span><span class="cx">     }
</span><span class="cx">     gFirstConnection.getStats()
</span><span class="cx">     .then(function(report) {
</span><del>-      // Show the retrieved stats info
-      var showStats = document.getElementById('stats');
</del><span class="cx">       let reportDictionary = {};
</span><span class="cx">       for (let stats of report.values()) {
</span><span class="cx">         reportDictionary[stats.id] = stats;
</span><span class="cx">       }
</span><del>-      showStats.innerHTML = JSON.stringify(reportDictionary, null, 2);
</del><ins>+      statsToShow = JSON.stringify(reportDictionary, null, 2);
</ins><span class="cx">       // Check the stats properties.
</span><span class="cx">       assert_not_equals(report, null, 'No report');
</span><span class="cx">       let sessionStat = getStatsRecordByType(report, 'peer-connection');
</span><span class="lines">@@ -121,6 +120,13 @@
</span><span class="cx">                        ' happened at step ' + atStep);
</span><span class="cx">     }));
</span><span class="cx">   });
</span><ins>+
+  function showStats() {
+    // Show the retrieved stats info
+    var showStats = document.getElementById('stats');
+    showStats.innerHTML = statsToShow;
+  }
+
</ins><span class="cx"> </script>
</span><span class="cx"> 
</span><span class="cx"> </body>
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcnomediacallhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/no-media-call.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/no-media-call.html      2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/no-media-call.html 2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1,7 +1,4 @@
</span><span class="cx"> <!doctype html>
</span><del>-<!--
-This test uses the legacy callback API with no media, and thus does not require fake media devices.
--->
</del><span class="cx"> 
</span><span class="cx"> <html>
</span><span class="cx"> <head>
</span><span class="lines">@@ -37,7 +34,6 @@
</span><span class="cx"> 
</span><span class="cx">     var parsedOffer = new RTCSessionDescription({ type: 'offer',
</span><span class="cx">                                                   sdp: offerSdp });
</span><del>-    // These functions use the legacy interface extensions to RTCPeerConnection.
</del><span class="cx">     gSecondConnection.setRemoteDescription(parsedOffer).then(
</span><span class="cx">       function() {
</span><span class="cx">         gSecondConnection.createAnswer().then(onAnswerCreated,
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolREADMEtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/README.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/README.txt     2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/README.txt        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -14,6 +14,8 @@
</span><span class="cx"> - draft-ietf-rtcweb-fec
</span><span class="cx"> - draft-ietf-rtcweb-data-protocol
</span><span class="cx"> - draft-ietf-rtcweb-data-channel
</span><ins>+- draft-ietf-mmusic-sdp-simulcast
+- draft-ietf-mmusic-rid
</ins><span class="cx"> 
</span><span class="cx"> - RFC 7742, "WebRTC Video Processing and Codec Requirements"
</span><span class="cx"> - RFC 7874, "WebRTC Audio Codec and Processing Requirements"
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolmissingfieldsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/missing-fields-expected.txt (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/missing-fields-expected.txt                            (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/missing-fields-expected.txt       2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+
+PASS Offer description with no mid is accepted 
+PASS Answer description with no mid is accepted 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolmissingfieldshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/missing-fields.html (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/missing-fields.html                            (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/missing-fields.html       2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,47 @@
</span><ins>+<!doctype html>
+<meta charset=utf-8>
+<title>RTCPeerconnection SDP parse tests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../RTCPeerConnection-helper.js"></script>
+<script>
+'use strict';
+
+function removeSdpLines(description, toRemove) {
+  const edited = description.sdp.split('\n').filter(function(line) {
+    return (!line.startsWith(toRemove));
+  }).join('\n');
+  return {type: description.type, sdp: edited};
+}
+
+promise_test(async t => {
+  const caller = new RTCPeerConnection();
+  const callee = new RTCPeerConnection();
+  t.add_cleanup(() => caller.close());
+  t.add_cleanup(() => callee.close());
+  caller.addTrack(trackFactories.audio());
+  const offer = await caller.createOffer();
+  await caller.setLocalDescription(offer);
+  let remote_offer = removeSdpLines(offer, 'a=mid:');
+  remote_offer = removeSdpLines(remote_offer, 'a=group:');
+  await callee.setRemoteDescription(remote_offer);
+  const answer = await callee.createAnswer();
+  await caller.setRemoteDescription(answer);
+}, 'Offer description with no mid is accepted');
+
+promise_test(async t => {
+  const caller = new RTCPeerConnection();
+  const callee = new RTCPeerConnection();
+  t.add_cleanup(() => caller.close());
+  t.add_cleanup(() => callee.close());
+  caller.addTrack(trackFactories.audio());
+  const offer = await caller.createOffer();
+  await caller.setLocalDescription(offer);
+  await callee.setRemoteDescription(offer);
+  const answer = await callee.createAnswer();
+  let remote_answer = removeSdpLines(answer, 'a=mid:');
+  remote_answer = removeSdpLines(remote_answer, 'a=group:');
+  await caller.setRemoteDescription(remote_answer);
+}, 'Answer description with no mid is accepted');
+
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolmsidparseexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/msid-parse-expected.txt (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/msid-parse-expected.txt                                (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/msid-parse-expected.txt   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+
+PASS Description with no msid produces a track with a stream 
+PASS Description with msid:- appid produces a track with no stream 
+PASS Description with msid:foo bar produces a stream with id foo 
+PASS Description with two msid produces two streams 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolmsidparsehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/msid-parse.html (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/msid-parse.html                                (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/msid-parse.html   2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,69 @@
</span><ins>+<!doctype html>
+<meta charset=utf-8>
+<title>RTCPeerconnection MSID parsing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../RTCPeerConnection-helper.js"></script>
+<script>
+'use strict';
+const preamble = `v=0
+o=- 0 3 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=fingerprint:sha-256 A7:24:72:CA:6E:02:55:39:BA:66:DF:6E:CC:4C:D8:B0:1A:BF:1A:56:65:7D:F4:03:AD:7E:77:43:2A:29:EC:93
+a=ice-ufrag:6HHHdzzeIhkE0CKj
+a=ice-pwd:XYDGVpfvklQIEnZ6YnyLsAew
+m=video 1 RTP/SAVPF 100
+a=rtcp-mux
+a=sendonly
+a=mid:video
+a=rtpmap:100 VP8/30
+`;
+
+
+promise_test(async t => {
+  const pc = new RTCPeerConnection();
+  t.add_cleanup(() => pc.close());
+  const ontrackPromise = addEventListenerPromise(t, pc, 'track');
+  await pc.setRemoteDescription({type: 'offer', sdp: preamble});
+  const trackevent = await ontrackPromise;
+  assert_equals(pc.getReceivers().length, 1);
+  assert_equals(trackevent.streams.length, 1, 'Stream count');
+}, 'Description with no msid produces a track with a stream');
+
+promise_test(async t => {
+  const pc = new RTCPeerConnection();
+  t.add_cleanup(() => pc.close());
+  const ontrackPromise = addEventListenerPromise(t, pc, 'track');
+  await pc.setRemoteDescription({type: 'offer',
+                                 sdp: preamble + 'a=msid:- foobar\n'});
+  const trackevent = await ontrackPromise;
+  assert_equals(pc.getReceivers().length, 1);
+  assert_equals(trackevent.streams.length, 0);
+}, 'Description with msid:- appid produces a track with no stream');
+
+promise_test(async t => {
+  const pc = new RTCPeerConnection();
+  t.add_cleanup(() => pc.close());
+  const ontrackPromise = addEventListenerPromise(t, pc, 'track');
+  await pc.setRemoteDescription({type: 'offer',
+                                 sdp: preamble + 'a=msid:foo bar\n'});
+  const trackevent = await ontrackPromise;
+  assert_equals(pc.getReceivers().length, 1);
+  assert_equals(trackevent.streams.length, 1);
+  assert_equals(trackevent.streams[0].id, 'foo');
+}, 'Description with msid:foo bar produces a stream with id foo');
+
+promise_test(async t => {
+  const pc = new RTCPeerConnection();
+  t.add_cleanup(() => pc.close());
+  const ontrackPromise = addEventListenerPromise(t, pc, 'track');
+  await pc.setRemoteDescription({type: 'offer',
+                                 sdp: preamble + 'a=msid:foo bar\n'
+                                               + 'a=msid:baz bar\n'});
+  const trackevent = await ontrackPromise;
+  assert_equals(pc.getReceivers().length, 1);
+  assert_equals(trackevent.streams.length, 2);
+}, 'Description with two msid produces two streams');
+
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolsimulcastofferexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/simulcast-offer-expected.txt (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/simulcast-offer-expected.txt                           (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/simulcast-offer-expected.txt      2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,3 @@
</span><ins>+
+FAIL createOffer() with multiple send encodings should create simulcast offer assert_not_equals: RID attribute for 'foo' missing. got disallowed value undefined
+
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolsimulcastofferhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/simulcast-offer.html (0 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/simulcast-offer.html                           (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/simulcast-offer.html      2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -0,0 +1,33 @@
</span><ins>+<!doctype html>
+<meta charset=utf-8>
+<title>RTCPeerConnection Simulcast Offer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict';
+
+// Tests for the construction of offers with simulcast according to:
+// draft-ietf-mmusic-sdp-simulcast-13
+// draft-ietf-mmusic-rid-15
+promise_test(async t => {
+  const pc = new RTCPeerConnection();
+  t.add_cleanup(() => pc.close());
+  const expected_rids = ['foo', 'bar', 'baz'];
+  pc.addTransceiver('video', {
+    sendEncodings: expected_rids.map(rid => ({rid}))
+  });
+
+  const offer = await pc.createOffer();
+  let offer_lines = offer.sdp.split('\r\n');
+  // Check for a RID line for each layer.
+  for (const rid of expected_rids) {
+    let result = offer_lines.find(line => line.startsWith(`a=rid:${rid}`));
+    assert_not_equals(result, undefined, `RID attribute for '${rid}' missing.`);
+  }
+
+  // Check for simulcast attribute with send direction and all RIDs.
+  let result = offer_lines.find(
+      line => line.startsWith(`a=simulcast:send ${expected_rids.join(';')}`));
+  assert_not_equals(result, undefined, "Could not find simulcast attribute.");
+}, 'createOffer() with multiple send encodings should create simulcast offer');
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcprotocolw3cimportlog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/w3c-import.log (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/w3c-import.log 2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/w3c-import.log    2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -16,4 +16,7 @@
</span><span class="cx"> List of files:
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/README.txt
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/jsep-initial-offer.https.html
</span><ins>+/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/missing-fields.html
+/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/msid-parse.html
+/LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/simulcast-offer.html
</ins><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/protocol/video-codecs.https.html
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcrtcpeerconnectionrtcpeerconnectionidlexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/rtcpeerconnection/rtcpeerconnection-idl-expected.txt (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/rtcpeerconnection/rtcpeerconnection-idl-expected.txt    2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/rtcpeerconnection/rtcpeerconnection-idl-expected.txt       2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -3,6 +3,8 @@
</span><span class="cx"> This test verifies the availability of the RTCPeerConnection interface.
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+Harness Error (FAIL), message = Not enough arguments
+
</ins><span class="cx"> PASS Partial interface RTCPeerConnection: original interface defined 
</span><span class="cx"> PASS Partial interface RTCPeerConnection[2]: original interface defined 
</span><span class="cx"> PASS Partial interface RTCPeerConnection[3]: original interface defined 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcsimplecallnossrcshttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/simplecall-no-ssrcs.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/simplecall-no-ssrcs.https.html  2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/simplecall-no-ssrcs.https.html     2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -17,7 +17,7 @@
</span><span class="cx">   <script src="/resources/testharness.js"></script>
</span><span class="cx">   <script src="/resources/testharnessreport.js"></script>
</span><span class="cx">   <script type="text/javascript">
</span><del>-  var test = async_test('Can set up a basic WebRTC call without announcing ssrcs.', {timeout: 5000});
</del><ins>+  var test = async_test('Can set up a basic WebRTC call without announcing ssrcs.');
</ins><span class="cx"> 
</span><span class="cx">   var gFirstConnection = null;
</span><span class="cx">   var gSecondConnection = null;
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcsimplecallhttpshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/simplecall.https.html (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/simplecall.https.html   2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/simplecall.https.html      2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -17,7 +17,7 @@
</span><span class="cx">   <script src="/resources/testharness.js"></script>
</span><span class="cx">   <script src="/resources/testharnessreport.js"></script>
</span><span class="cx">   <script type="text/javascript">
</span><del>-  var test = async_test('Can set up a basic WebRTC call.', {timeout: 5000});
</del><ins>+  var test = async_test('Can set up a basic WebRTC call.');
</ins><span class="cx"> 
</span><span class="cx">   var gFirstConnection = null;
</span><span class="cx">   var gSecondConnection = null;
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestswebrtcw3cimportlog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/w3c-import.log (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/w3c-import.log  2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webrtc/w3c-import.log     2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -32,7 +32,10 @@
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannel-send.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDataChannelEvent-constructor.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html
</span><ins>+/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCDtlsTransport-state.html
+/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCError.html
</ins><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceCandidate-constructor.html
</span><ins>+/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceConnectionState-candidate-pair.https.html
</ins><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceTransport-extension-helper.js
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceTransport-extension.https.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCIceTransport.html
</span><span class="lines">@@ -51,10 +54,11 @@
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-getTransceivers.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-helper.js
</span><del>-/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.html
</del><ins>+/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceConnectionState.https.html
</ins><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-iceGatheringState.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-ondatachannel.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onnegotiationneeded.html
</span><ins>+/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-onsignalingstatechanged.https.html
</ins><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-ontrack.https.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-remote-track-mute.https.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-removeTrack.https.html
</span><span class="lines">@@ -65,6 +69,7 @@
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription-rollback.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setLocalDescription.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-answer.html
</span><ins>+/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-nomsid.html
</ins><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-offer.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-pranswer.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-replaceTrack.https.html
</span><span class="lines">@@ -74,9 +79,6 @@
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-track-stats.https.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-transceivers.https.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCPeerConnectionIceEvent-constructor.html
</span><del>-/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCQuicStream.https.html
-/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCQuicTransport-helper.js
-/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCQuicTransport.https.html
</del><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpCapabilities-helper.js
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-codecs.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpParameters-degradationPreference.html
</span><span class="lines">@@ -94,13 +96,16 @@
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-getStats.https.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-replaceTrack.https.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-setParameters.html
</span><ins>+/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpSender-transport.https.html
</ins><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver-direction.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver-setCodecPreferences.html
</span><ins>+/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver-stop.html
</ins><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCRtpTransceiver.https.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCSctpTransport-constructor.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCSctpTransport-maxMessageSize.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCStats-helper.js
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-constructor.html
</span><ins>+/LayoutTests/imported/w3c/web-platform-tests/webrtc/RTCTrackEvent-fire.html
</ins><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/datachannel-emptystring.html
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/dictionary-helper.js
</span><span class="cx"> /LayoutTests/imported/w3c/web-platform-tests/webrtc/getstats.html
</span></span></pre></div>
<a id="trunkLayoutTeststestsoptionsjson"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/tests-options.json (243040 => 243041)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/tests-options.json     2019-03-16 11:26:14 UTC (rev 243040)
+++ trunk/LayoutTests/tests-options.json        2019-03-16 16:35:16 UTC (rev 243041)
</span><span class="lines">@@ -1700,9 +1700,21 @@
</span><span class="cx">     "imported/w3c/web-platform-tests/webrtc/RTCDTMFSender-ontonechange-long.https.html": [
</span><span class="cx">         "slow"
</span><span class="cx">     ],
</span><ins>+    "imported/w3c/web-platform-tests/webrtc/RTCIceConnectionState-candidate-pair.https.html": [
+        "slow"
+    ],
</ins><span class="cx">     "imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-track-stats.https.html": [
</span><span class="cx">         "slow"
</span><span class="cx">     ],
</span><ins>+    "imported/w3c/web-platform-tests/webrtc/RTCPeerConnection-transceivers.https.html": [
+        "slow"
+    ],
+    "imported/w3c/web-platform-tests/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html": [
+        "slow"
+    ],
+    "imported/w3c/web-platform-tests/webrtc/RTCRtpSender-transport.https.html": [
+        "slow"
+    ],
</ins><span class="cx">     "imported/w3c/web-platform-tests/xhr/progress-events-response-data-gzip.htm": [
</span><span class="cx">         "slow"
</span><span class="cx">     ],
</span></span></pre>
</div>
</div>

</body>
</html>