Bug 1456417: made MLineIndex nullable. r=bwc,smaug
authorNils Ohlmeier [:drno] <drno@ohlmeier.org>
Tue, 13 Nov 2018 22:52:24 +0000
changeset 505322 9c729de094ae62eef1507147490306d209133198
parent 505321 6afbbb6e200f89465fe64a17b07a28f4f283c8c0
child 505323 4458937e3ee03803dee195a36b540fbd36134f17
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbwc, smaug
bugs1456417
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1456417: made MLineIndex nullable. r=bwc,smaug Differential Revision: https://phabricator.services.mozilla.com/D10807
dom/media/PeerConnection.js
dom/media/bridge/IPeerConnection.idl
dom/media/tests/mochitest/mochitest.ini
dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html
dom/webidl/PeerConnectionImpl.webidl
media/webrtc/signaling/gtest/jsep_session_unittest.cpp
media/webrtc/signaling/src/jsep/JsepSession.h
media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
media/webrtc/signaling/src/jsep/JsepSessionImpl.h
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
testing/web-platform/meta/webrtc/RTCPeerConnection-addIceCandidate.html.ini
testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate.html
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -1187,32 +1187,27 @@ class RTCPeerConnection {
     let sections = desc.sdp.split(/(?:\r\n?|\n)m=/);
     let topSection = sections.shift();
     this._canTrickle =
       containsTrickle(topSection) || sections.every(containsTrickle);
   }
 
   // TODO: Implement processing for end-of-candidates (bug 1318167)
   addIceCandidate(cand, onSucc, onErr) {
+    if (cand === null) {
+      throw new this._win.DOMException(
+        "Empty candidate can not be added.",
+        "TypeError");
+    }
     return this._auto(onSucc, onErr, () => cand && this._addIceCandidate(cand));
   }
 
   async _addIceCandidate({ candidate, sdpMid, sdpMLineIndex }) {
     this._checkClosed();
-    if (sdpMid === null && sdpMLineIndex === null) {
-      throw new this._win.DOMException(
-          "Invalid candidate (both sdpMid and sdpMLineIndex are null).",
-          "TypeError");
-    }
     return this._chain(() => {
-      if (!this.remoteDescription) {
-        throw new this._win.DOMException(
-            "setRemoteDescription needs to called before addIceCandidate",
-            "InvalidStateError");
-      }
       return new Promise((resolve, reject) => {
         this._onAddIceCandidateSuccess = resolve;
         this._onAddIceCandidateError = reject;
         this._impl.addIceCandidate(candidate, sdpMid || "", sdpMLineIndex);
       });
     });
   }
 
@@ -1708,24 +1703,26 @@ class PeerConnectionObserver {
     this._dompc = dompc._innerObject;
   }
 
   newError(message, code) {
     // These strings must match those defined in the WebRTC spec.
     const reasonName = [
       "",
       "InternalError",
-      "InvalidCandidateError",
+      "InternalError",
       "InvalidParameterError",
       "InvalidStateError",
       "InvalidSessionDescriptionError",
       "IncompatibleSessionDescriptionError",
       "InternalError",
       "IncompatibleMediaStreamTrackError",
       "InternalError",
+      "TypeError",
+      "OperationError",
     ];
     let name = reasonName[Math.min(code, reasonName.length - 1)];
     return new this._dompc._win.DOMException(message, name);
   }
 
   dispatchEvent(event) {
     this._dompc.dispatchEvent(event);
   }
--- a/dom/media/bridge/IPeerConnection.idl
+++ b/dom/media/bridge/IPeerConnection.idl
@@ -47,10 +47,12 @@ interface IPeerConnection : nsISupports
   const unsigned long kNoError                          = 0; // Test driver only
   const unsigned long kInvalidCandidate                 = 2;
   const unsigned long kInvalidMediastreamTrack          = 3;
   const unsigned long kInvalidState                     = 4;
   const unsigned long kInvalidSessionDescription        = 5;
   const unsigned long kIncompatibleSessionDescription   = 6;
   const unsigned long kIncompatibleMediaStreamTrack     = 8;
   const unsigned long kInternalError                    = 9;
-  const unsigned long kMaxErrorType                     = 9; // Same as final error
+  const unsigned long kTypeError                        = 10;
+  const unsigned long kOperationError                   = 11;
+  const unsigned long kMaxErrorType                     = 11; // Same as final error
 };
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -99,17 +99,16 @@ skip-if = android_version == '18' # andr
 [test_getUserMedia_playVideoAudioTwice.html]
 [test_getUserMedia_playVideoTwice.html]
 [test_getUserMedia_scarySources.html]
 skip-if = toolkit == 'android' # no screenshare or windowshare on android
 [test_getUserMedia_spinEventLoop.html]
 [test_getUserMedia_trackCloneCleanup.html]
 [test_getUserMedia_trackEnded.html]
 [test_getUserMedia_peerIdentity.html]
-[test_peerConnection_addIceCandidate.html]
 [test_peerConnection_addtrack_removetrack_events.html]
 skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_audioCodecs.html]
 skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_basicAudio.html]
 skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_basicAudio_forced_lower_rate.html]
 skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
deleted file mode 100644
--- a/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html
+++ /dev/null
@@ -1,106 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <script type="application/javascript" src="pc.js"></script>
-</head>
-<body>
-<pre id="test">
-<script type="application/javascript">
-  createHTML({
-    bug: "1087551",
-    title: "addIceCandidate behavior (local and remote) including invalid data"
-  });
-
-  var test;
-  runNetworkTest(function () {
-    test = new PeerConnectionTest();
-    test.setMediaConstraints([{audio: true}], [{audio: true}]);
-    test.chain.removeAfter("PC_LOCAL_GET_ANSWER");
-
-    test.chain.insertAfter("PC_LOCAL_SET_LOCAL_DESCRIPTION", [
-      function PC_LOCAL_ADD_CANDIDATE_EARLY(test) {
-        var candidate = {
-          candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
-          sdpMLineIndex: 0};
-        return test.pcLocal._pc.addIceCandidate(candidate).then(
-          generateErrorCallback("addIceCandidate should have failed."),
-          err => {
-            is(err.name, "InvalidStateError", "Error is InvalidStateError");
-          });
-        }
-    ]);
-    test.chain.insertAfter("PC_REMOTE_SET_LOCAL_DESCRIPTION", [
-      function PC_REMOTE_ADD_CANDIDATE_INVALID_INDEX(test) {
-        var invalid_index = new RTCIceCandidate(
-          {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
-           sdpMLineIndex: 2});
-        return test.pcRemote._pc.addIceCandidate(invalid_index)
-        .then(
-          generateErrorCallback("addIceCandidate should have failed."),
-          err => {
-            is(err.name, "InvalidCandidateError", "Error is InvalidCandidateError");
-          }
-        );
-      },
-      function PC_REMOTE_ADD_BOGUS_CANDIDATE(test) {
-        var bogus = new RTCIceCandidate(
-          {candidate:"Pony Lords, jump!",
-           sdpMLineIndex: 0});
-        return test.pcRemote._pc.addIceCandidate(bogus)
-        .then(
-          generateErrorCallback("addIceCandidate should have failed."),
-          err => {
-            is(err.name, "InvalidCandidateError", "Error is InvalidCandidateError");
-          }
-        );
-      },
-      function PC_REMOTE_ADD_MISSING_MID_AND_MISSING_INDEX(test) {
-        var broken = new RTCIceCandidate(
-          {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host"});
-        return test.pcRemote._pc.addIceCandidate(broken)
-        .then(
-          generateErrorCallback("addIceCandidate should have failed."),
-          err => {
-            is(err.name, "TypeError", "Error is TypeError");
-          }
-        );
-      },
-      function PC_REMOTE_ADD_VALID_CANDIDATE(test) {
-        var candidate = {
-          candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
-          sdpMLineIndex: 0};
-        return test.pcRemote._pc.addIceCandidate(candidate)
-        .then(() => ok(true, "Successfully added valid ICE candidate"));
-      },
-      // bug 1095793
-      function PC_REMOTE_ADD_MISMATCHED_MID_AND_LEVEL_CANDIDATE(test) {
-        var bogus = new mozRTCIceCandidate(
-          {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
-           sdpMLineIndex: 0,
-           sdpMid: "1"});
-        return test.pcRemote._pc.addIceCandidate(bogus)
-        .then(generateErrorCallback("addIceCandidate should have failed."),
-              err => is(err.name, "InvalidCandidateError", "Error is InvalidCandidateError"));
-      },
-      function PC_REMOTE_ADD_MID_AND_MISSING_INDEX(test) {
-        var candidate = new RTCIceCandidate(
-          {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
-           sdpMid: "0"});
-        return test.pcRemote._pc.addIceCandidate(candidate)
-        .then(() => ok(true, "Successfully added valid ICE candidate"));
-      },
-      function PC_REMOTE_ADD_MATCHING_MID_AND_LEVEL_CANDIDATE(test) {
-        var candidate = new RTCIceCandidate(
-          {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host",
-           sdpMLineIndex: 0,
-           sdpMid: "0"});
-        return test.pcRemote._pc.addIceCandidate(candidate)
-        .then(() => ok(true, "Successfully added valid ICE candidate with matching mid and level"));
-      }
-    ]);
-    test.run();
-  });
-</script>
-</pre>
-</body>
-</html>
--- a/dom/webidl/PeerConnectionImpl.webidl
+++ b/dom/webidl/PeerConnectionImpl.webidl
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * PeerConnection.js' interface to the C++ PeerConnectionImpl.
  *
  * Do not confuse with RTCPeerConnection. This interface is purely for
  * communication between the PeerConnection JS DOM binding and the C++
- * implementation in SIPCC.
+ * implementation.
  *
  * See media/webrtc/signaling/include/PeerConnectionImpl.h
  *
  */
 
 interface nsISupports;
 
 /* Must be created first. Observer events will be dispatched on the thread provided */
@@ -86,19 +86,19 @@ interface PeerConnectionImpl  {
                          boolean sending);
 
   /* As the ICE candidates roll in this one should be called each time
    * in order to keep the candidate list up-to-date for the next SDP-related
    * call PeerConnectionImpl does not parse ICE candidates, just sticks them
    * into the SDP.
    */
   [Throws]
-  void addIceCandidate(DOMString candidate, DOMString mid, unsigned short level);
+  void addIceCandidate(DOMString candidate, DOMString mid, unsigned short? level);
 
-  /* Puts the SIPCC engine back to 'kIdle', shuts down threads, deletes state */
+  /* Shuts down threads, deletes state */
   [Throws]
   void close();
 
   /* Notify DOM window if this plugin crash is ours. */
   boolean pluginCrash(unsigned long long pluginId, DOMString name);
 
   /* Attributes */
   /* This provides the implementation with the certificate it uses to
--- a/media/webrtc/signaling/gtest/jsep_session_unittest.cpp
+++ b/media/webrtc/signaling/gtest/jsep_session_unittest.cpp
@@ -1091,17 +1091,18 @@ protected:
       {
         for (const auto& levelMidAndCandidate : mCandidatesToTrickle) {
           Level level;
           Mid mid;
           Candidate candidate;
           Tie(level, mid, candidate) = levelMidAndCandidate;
           std::cerr << "trickling candidate: " << candidate << " level: " << level << " mid: " << mid << std::endl;
           std::string transportId;
-          session.AddRemoteIceCandidate(candidate, mid, level, &transportId);
+          Maybe<unsigned long> lev = Some(level);
+          session.AddRemoteIceCandidate(candidate, mid, lev, &transportId);
         }
         mCandidatesToTrickle.clear();
       }
 
       void CheckRtpCandidates(bool expectRtpCandidates,
                               const SdpMediaSection& msection,
                               const std::string& transportId,
                               const std::string& context) const
@@ -5112,17 +5113,17 @@ TEST_F(JsepSessionTest, AddCandidateInHa
   AddTracks(*mSessionOff, "audio");
   std::string offer = CreateOffer();
   SetLocalOffer(offer);
 
   nsresult rv;
   std::string mid;
   std::string transportId;
   rv = mSessionOff->AddRemoteIceCandidate(strSampleCandidate,
-                                          mid, nSamplelevel,
+                                          mid, Some(nSamplelevel),
                                           &transportId);
   ASSERT_EQ(NS_ERROR_UNEXPECTED, rv);
 }
 
 TEST_F(JsepSessionTest, SetLocalWithoutCreateOffer) {
   types.push_back(SdpMediaSection::kAudio);
   AddTracks(*mSessionOff, "audio");
   AddTracks(*mSessionAns, "audio");
--- a/media/webrtc/signaling/src/jsep/JsepSession.h
+++ b/media/webrtc/signaling/src/jsep/JsepSession.h
@@ -156,17 +156,17 @@ public:
   virtual std::string GetRemoteDescription(JsepDescriptionPendingOrCurrent type)
                                            const = 0;
   virtual nsresult SetLocalDescription(JsepSdpType type,
                                        const std::string& sdp) = 0;
   virtual nsresult SetRemoteDescription(JsepSdpType type,
                                         const std::string& sdp) = 0;
   virtual nsresult AddRemoteIceCandidate(const std::string& candidate,
                                          const std::string& mid,
-                                         uint16_t level,
+                                         const Maybe<uint16_t>& level,
                                          std::string* transportId) = 0;
   virtual nsresult AddLocalIceCandidate(const std::string& candidate,
                                         const std::string& transportId,
                                         uint16_t* level,
                                         std::string* mid,
                                         bool* skipped) = 0;
   virtual nsresult UpdateDefaultCandidate(
       const std::string& defaultCandidateAddr,
--- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
+++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
@@ -2220,50 +2220,54 @@ JsepSessionImpl::SetState(JsepSignalingS
   MOZ_MTLOG(ML_NOTICE, "[" << mName << "]: " <<
             GetStateStr(mState) << " -> " << GetStateStr(state));
   mState = state;
 }
 
 nsresult
 JsepSessionImpl::AddRemoteIceCandidate(const std::string& candidate,
                                        const std::string& mid,
-                                       uint16_t level,
+                                       const Maybe<uint16_t>& level,
                                        std::string* transportId)
 {
   mLastError.clear();
 
   mozilla::Sdp* sdp = GetParsedRemoteDescription(kJsepDescriptionPendingOrCurrent);
 
   if (!sdp) {
     JSEP_SET_ERROR("Cannot add ICE candidate in state " << GetStateStr(mState));
     return NS_ERROR_UNEXPECTED;
   }
 
   JsepTransceiver* transceiver;
-  if (mid.empty()) {
-    transceiver = GetTransceiverForLevel(level);
+  if (!mid.empty()) {
+    transceiver = GetTransceiverForMid(mid);
+  } else if (level.isSome()) {
+    transceiver = GetTransceiverForLevel(level.value());
   } else {
-    transceiver = GetTransceiverForMid(mid);
+    JSEP_SET_ERROR("ICE candidate: \'" << candidate
+                   << "\' is missing MID and MLineIndex");
+    return NS_ERROR_TYPE_ERR;
   }
 
   if (!transceiver) {
     JSEP_SET_ERROR("Cannot set ICE candidate for level=" << level
                    << " mid=" << mid << ": No such transceiver.");
     return NS_ERROR_INVALID_ARG;
   }
 
-  if (transceiver->GetLevel() != level) {
-    JSEP_SET_ERROR("Mismatch between mid and level - \"" << mid
+  if (level.isSome() &&
+      transceiver->GetLevel() != level.value()) {
+    MOZ_MTLOG(ML_WARNING, "Mismatch between mid and level - \"" << mid
                    << "\" is not the mid for level " << level);
-    return NS_ERROR_INVALID_ARG;
   }
 
   *transportId = transceiver->mTransport.mTransportId;
 
-  return mSdpHelper.AddCandidateToSdp(sdp, candidate, level);
+  return mSdpHelper.AddCandidateToSdp(sdp, candidate, transceiver->GetLevel());
 }
 
 nsresult
 JsepSessionImpl::AddLocalIceCandidate(const std::string& candidate,
                                       const std::string& transportId,
                                       uint16_t* level,
                                       std::string* mid,
                                       bool* skipped)
--- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.h
+++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.h
@@ -108,17 +108,17 @@ public:
   virtual nsresult SetLocalDescription(JsepSdpType type,
                                        const std::string& sdp) override;
 
   virtual nsresult SetRemoteDescription(JsepSdpType type,
                                         const std::string& sdp) override;
 
   virtual nsresult AddRemoteIceCandidate(const std::string& candidate,
                                          const std::string& mid,
-                                         uint16_t level,
+                                         const Maybe<uint16_t>& level,
                                          std::string* transportId) override;
 
   virtual nsresult AddLocalIceCandidate(const std::string& candidate,
                                         const std::string& transportId,
                                         uint16_t* level,
                                         std::string* mid,
                                         bool* skipped) override;
 
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -1682,17 +1682,17 @@ PeerConnectionImpl::GetStats(MediaStream
                 WrapRunnableNM(&PeerConnectionImpl::GetStatsForPCObserver_s,
                                mHandle,
                                query),
                 NS_DISPATCH_NORMAL);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PeerConnectionImpl::AddIceCandidate(const char* aCandidate, const char* aMid, unsigned short aLevel) {
+PeerConnectionImpl::AddIceCandidate(const char* aCandidate, const char* aMid, const dom::Nullable<unsigned short>& aLevel) {
   PC_AUTO_ENTER_API_CALL(true);
 
   if (mForceIceTcp && std::string::npos != std::string(aCandidate).find(" UDP ")) {
     CSFLogError(LOGTAG, "Blocking remote UDP candidate: %s", aCandidate);
     return NS_OK;
   }
 
   JSErrorResult rv;
@@ -1715,18 +1715,22 @@ PeerConnectionImpl::AddIceCandidate(cons
                             timeDelta.ToMilliseconds());
     } else {
       Telemetry::Accumulate(Telemetry::WEBRTC_ICE_ON_TIME_TRICKLE_ARRIVAL_TIME,
                             timeDelta.ToMilliseconds());
     }
   }
 
   std::string transportId;
+  Maybe<unsigned short> level;
+  if (!aLevel.IsNull()) {
+    level = Some(aLevel.Value());
+  }
   nsresult res =
-    mJsepSession->AddRemoteIceCandidate(aCandidate, aMid, aLevel, &transportId);
+    mJsepSession->AddRemoteIceCandidate(aCandidate, aMid, level, &transportId);
 
   if (NS_SUCCEEDED(res)) {
     // We do not bother PCMedia about this before offer/answer concludes.
     // Once offer/answer concludes, PCMedia will extract these candidates from
     // the remote SDP.
     if (mSignalingState == PCImplSignalingState::SignalingStable) {
       mMedia->AddIceCandidate(aCandidate, transportId);
       mRawTrickledCandidates.push_back(aCandidate);
@@ -1735,29 +1739,32 @@ PeerConnectionImpl::AddIceCandidate(cons
   } else {
     ++mAddCandidateErrorCount;
     Error error;
     switch (res) {
       case NS_ERROR_UNEXPECTED:
         error = kInvalidState;
         break;
       case NS_ERROR_INVALID_ARG:
-        error = kInvalidCandidate;
+        error = kOperationError;
+        break;
+      case NS_ERROR_TYPE_ERR:
+        error = kTypeError;
         break;
       default:
         error = kInternalError;
     }
 
     std::string errorString = mJsepSession->GetLastError();
 
     CSFLogError(LOGTAG, "Failed to incorporate remote candidate into SDP:"
-                        " res = %u, candidate = %s, level = %u, error = %s",
+                        " res = %u, candidate = %s, level = %i, error = %s",
                         static_cast<unsigned>(res),
                         aCandidate,
-                        static_cast<unsigned>(aLevel),
+                        level.valueOr(-1),
                         errorString.c_str());
 
     pco->OnAddIceCandidateError(error, ObString(errorString.c_str()), rv);
   }
 
   return NS_OK;
 }
 
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -178,17 +178,19 @@ public:
   enum Error {
     kNoError                          = 0,
     kInvalidCandidate                 = 2,
     kInvalidMediastreamTrack          = 3,
     kInvalidState                     = 4,
     kInvalidSessionDescription        = 5,
     kIncompatibleSessionDescription   = 6,
     kIncompatibleMediaStreamTrack     = 8,
-    kInternalError                    = 9
+    kInternalError                    = 9,
+    kTypeError                        = 10,
+    kOperationError                   = 11
   };
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
   bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector);
 
   static already_AddRefed<PeerConnectionImpl>
       Constructor(const mozilla::dom::GlobalObject& aGlobal, ErrorResult& rv);
@@ -293,20 +295,21 @@ public:
 
   NS_IMETHODIMP_TO_ERRORRESULT(GetStats, ErrorResult &rv,
                                mozilla::dom::MediaStreamTrack *aSelector)
   {
     rv = GetStats(aSelector);
   }
 
   NS_IMETHODIMP AddIceCandidate(const char* aCandidate, const char* aMid,
-                                unsigned short aLevel);
+                                const dom::Nullable<unsigned short>& aLevel);
 
   void AddIceCandidate(const nsAString& aCandidate, const nsAString& aMid,
-                       unsigned short aLevel, ErrorResult &rv)
+                       const dom::Nullable<unsigned short>& aLevel,
+                       ErrorResult &rv)
   {
     rv = AddIceCandidate(NS_ConvertUTF16toUTF8(aCandidate).get(),
                          NS_ConvertUTF16toUTF8(aMid).get(), aLevel);
   }
 
   void UpdateNetworkState(bool online);
 
   NS_IMETHODIMP CloseStreams();
--- a/testing/web-platform/meta/webrtc/RTCPeerConnection-addIceCandidate.html.ini
+++ b/testing/web-platform/meta/webrtc/RTCPeerConnection-addIceCandidate.html.ini
@@ -1,36 +1,15 @@
 [RTCPeerConnection-addIceCandidate.html]
-  [Add null candidate should reject with TypeError]
-    expected: FAIL
-
-  [Add candidate with only valid sdpMid should succeed]
-    expected: FAIL
-
-  [Add candidate with only valid sdpMLineIndex should succeed]
-    expected: FAIL
-
   [Add with empty candidate string (end of candidate) should succeed]
     expected: FAIL
 
-  [Add candidate with invalid sdpMid should reject with OperationError]
-    expected: FAIL
-
-  [Add candidate with invalid sdpMLineIndex should reject with OperationError]
-    expected: FAIL
-
-  [Invalid sdpMLineIndex should be ignored if valid sdpMid is provided]
-    expected: FAIL
-
   [Add candidate with invalid ufrag should reject with OperationError]
     expected: FAIL
 
-  [Add candidate with invalid candidate string should reject with OperationError]
-    expected: FAIL
-
   [Add candidate with sdpMid belonging to different ufrag should reject with OperationError]
     expected: FAIL
 
   [Add valid candidate should never resolve when pc is closed]
     disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1382972
 
   [Add candidate with invalid usernameFragment should reject with OperationError]
     expected: FAIL
--- a/testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate.html
+++ b/testing/web-platform/tests/webrtc/RTCPeerConnection-addIceCandidate.html
@@ -56,19 +56,19 @@ a=dtls-id:1
 a=rtcp:10103 IN IP4 203.0.113.100
 a=rtcp-mux
 a=rtcp-rsize
 `;
 
   const sessionDesc = { type: 'offer', sdp };
 
   // valid candidate attributes
-  const sdpMid = 'a1';
-  const sdpMLineIndex = 0;
-  const usernameFragment = 'ETEn';
+  const sdpMid1 = 'a1';
+  const sdpMLineIndex1 = 0;
+  const usernameFragment1 = 'ETEn';
 
   const sdpMid2 = 'v1';
   const sdpMLineIndex2 = 1;
   const usernameFragment2 = 'BGKk';
 
   const mediaLine1 = 'm=audio';
   const mediaLine2 = 'm=video';
 
@@ -133,63 +133,73 @@ a=rtcp-rsize
   promise_test(t => {
     const pc = new RTCPeerConnection();
 
     t.add_cleanup(() => pc.close());
 
     return promise_rejects(t, 'InvalidStateError',
       pc.addIceCandidate({
         candidate: candidateStr1,
-        sdpMid, sdpMLineIndex, usernameFragment
+        sdpMid: sdpMid1,
+        sdpMLineIndex: sdpMLineIndex1,
+        usernameFragment: usernameFragment1
       }));
   }, 'Add ICE candidate before setting remote description should reject with InvalidStateError');
 
   /*
     Success cases
    */
   promise_test(t => {
     const pc = new RTCPeerConnection();
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
     .then(() => pc.addIceCandidate({
       candidate: candidateStr1,
-      sdpMid, sdpMLineIndex, usernameFragment
+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      usernameFragement: usernameFragment1
     }));
   }, 'Add ICE candidate after setting remote description should succeed');
 
   promise_test(t => {
     const pc = new RTCPeerConnection();
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
     .then(() => pc.addIceCandidate(new RTCIceCandidate({
       candidate: candidateStr1,
-      sdpMid, sdpMLineIndex, usernameFragment
+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      usernameFragement: usernameFragment1
     })));
   }, 'Add ICE candidate with RTCIceCandidate should succeed');
 
   promise_test(t => {
     const pc = new RTCPeerConnection();
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
-      .then(() => pc.addIceCandidate({ sdpMid }));
+      .then(() => pc.addIceCandidate({
+        candidate: candidateStr1,
+        sdpMid: sdpMid1 }));
   }, 'Add candidate with only valid sdpMid should succeed');
 
   promise_test(t => {
     const pc = new RTCPeerConnection();
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
-      .then(() => pc.addIceCandidate({ sdpMLineIndex }));
+      .then(() => pc.addIceCandidate({
+        candidate: candidateStr1,
+        sdpMLineIndex: sdpMLineIndex1 }));
   }, 'Add candidate with only valid sdpMLineIndex should succeed');
 
   /*
     4.4.2.  addIceCandidate
       4.6.2.  If candidate is applied successfully, the user agent MUST queue
               a task that runs the following steps:
         2.  If connection.pendingRemoteDescription is non-null, and represents
             the ICE generation for which candidate was processed, add
@@ -201,17 +211,19 @@ a=rtcp-rsize
   promise_test(t => {
     const pc = new RTCPeerConnection();
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
     .then(() => pc.addIceCandidate({
       candidate: candidateStr1,
-      sdpMid, sdpMLineIndex, usernameFragment
+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      usernameFragement: usernameFragment1
     }))
     .then(() => {
       assert_candidate_line_between(pc.remoteDescription.sdp,
         mediaLine1, candidateLine1, mediaLine2);
     });
   }, 'addIceCandidate with first sdpMid and sdpMLineIndex add candidate to first media stream');
 
   promise_test(t => {
@@ -235,34 +247,37 @@ a=rtcp-rsize
   promise_test(t => {
     const pc = new RTCPeerConnection();
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
     .then(() => pc.addIceCandidate({
       candidate: candidateStr1,
-      sdpMid, sdpMLineIndex,
-      usernameFragment: null
+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      ufrag: null
     }))
     .then(() => {
       assert_candidate_line_between(pc.remoteDescription.sdp,
         mediaLine1, candidateLine1, mediaLine2);
     });
   }, 'Add candidate for first media stream with null usernameFragment should add candidate to first media stream');
 
   promise_test(t => {
     const pc = new RTCPeerConnection();
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
     .then(() => pc.addIceCandidate({
       candidate: candidateStr1,
-      sdpMid, sdpMLineIndex, usernameFragment
+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      usernameFragement: usernameFragment1
     }))
     .then(() => pc.addIceCandidate({
       candidate: candidateStr2,
       sdpMid: sdpMid2,
       sdpMLineIndex: sdpMLineIndex2,
       usernameFragment: usernameFragment2
     }))
     .then(() => {
@@ -291,22 +306,25 @@ a=rtcp-rsize
   promise_test(t => {
     const pc = new RTCPeerConnection();
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
     .then(() => pc.addIceCandidate({
       candidate: candidateStr1,
-      sdpMid, sdpMLineIndex, usernameFragment
+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      usernameFragement: usernameFragment1
     }))
     .then(() => pc.addIceCandidate({
       candidate: '',
-      sdpMid, sdpMLineIndex,
-      usernameFragment
+      sdpMid: sdpMid1,
+      sdpMLineIndex: sdpMLineIndex1,
+      usernameFragement: usernameFragment1
     }))
     .then(() => {
       assert_candidate_line_between(pc.remoteDescription.sdp,
         mediaLine1, candidateLine1, mediaLine2);
 
       assert_candidate_line_between(pc.remoteDescription.sdp,
         mediaLine1, endOfCandidateLine, mediaLine2);
     });
@@ -399,17 +417,19 @@ a=rtcp-rsize
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
     .then(() =>
       promise_rejects(t, 'OperationError',
         pc.addIceCandidate({
           candidate: candidateStr1,
-          sdpMid: 'invalid', sdpMLineIndex, usernameFragment
+          sdpMid: 'invalid',
+          sdpMLineIndex: sdpMLineIndex1,
+          usernameFragement: usernameFragment1
         })));
   }, 'Add candidate with invalid sdpMid should reject with OperationError');
 
   /*
     4.4.2.  addIceCandidate
       4.4.  Else, if candidate.sdpMLineIndex is not null, run the following
           steps:
         1.  If candidate.sdpMLineIndex is equal to or larger than the
@@ -422,33 +442,33 @@ a=rtcp-rsize
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
     .then(() =>
       promise_rejects(t, 'OperationError',
         pc.addIceCandidate({
           candidate: candidateStr1,
           sdpMLineIndex: 2,
-          usernameFragment
+          usernameFragement: usernameFragment1
         })));
   }, 'Add candidate with invalid sdpMLineIndex should reject with OperationError');
 
   // There is an "Else" for the statement:
   // "Else, if candidate.sdpMLineIndex is not null, ..."
   promise_test(t => {
     const pc = new RTCPeerConnection();
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
     .then(() => pc.addIceCandidate({
       candidate: candidateStr1,
-      sdpMid,
+      sdpMid: sdpMid1,
       sdpMLineIndex: 2,
-      usernameFragment
+      usernameFragement: usernameFragment1
     }));
   }, 'Invalid sdpMLineIndex should be ignored if valid sdpMid is provided');
 
   promise_test(t => {
     const pc = new RTCPeerConnection();
 
     t.add_cleanup(() => pc.close());
 
@@ -477,18 +497,19 @@ a=rtcp-rsize
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
     .then(() =>
       promise_rejects(t, 'OperationError',
         pc.addIceCandidate({
           candidate: candidateStr1,
-          sdpMid, sdpMLineIndex,
-          usernameFragment: 'invalid'
+          sdpMid: sdpMid1,
+          sdpMLineIndex: sdpMLineIndex1,
+          ufrag: 'invalid'
         })));
   }, 'Add candidate with invalid usernameFragment should reject with OperationError');
 
   /*
     4.4.2.  addIceCandidate
       4.6.1.  If candidate could not be successfully added the user agent MUST
              queue a task that runs the following steps:
         2.  Reject p with a DOMException object whose name attribute has
@@ -499,29 +520,31 @@ a=rtcp-rsize
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
     .then(() =>
       promise_rejects(t, 'OperationError',
         pc.addIceCandidate({
           candidate: invalidCandidateStr,
-          sdpMid, sdpMLineIndex, usernameFragment
+          sdpMid: sdpMid1,
+          sdpMLineIndex: sdpMLineIndex1,
+          usernameFragement: usernameFragment1
         })));
   }, 'Add candidate with invalid candidate string should reject with OperationError');
 
   promise_test(t => {
     const pc = new RTCPeerConnection();
 
     t.add_cleanup(() => pc.close());
 
     return pc.setRemoteDescription(sessionDesc)
     .then(() =>
       promise_rejects(t, 'OperationError',
         pc.addIceCandidate({
           candidate: candidateStr2,
           sdpMid: sdpMid2,
           sdpMLineIndex: sdpMLineIndex2,
-          usernameFragment
+          usernameFragement: usernameFragment1
         })));
   }, 'Add candidate with sdpMid belonging to different usernameFragment should reject with OperationError');
 
 </script>