Pass around the candidate removals events in IOS clients

When local candidates are removed, signal to RTCPeerConnection
and eventually send to the remote client.
When a candidate-removal message is received, notify the native PeerConnection.

BUG=
R=tkchin@webrtc.org

Review URL: https://codereview.webrtc.org/1972483002 .

Cr-Commit-Position: refs/heads/master@{#12852}
diff --git a/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection+Private.h b/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection+Private.h
index cbae360..92bdfa3 100644
--- a/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection+Private.h
+++ b/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection+Private.h
@@ -45,6 +45,9 @@
 
   void OnIceCandidate(const IceCandidateInterface *candidate) override;
 
+  void OnIceCandidatesRemoved(
+      const std::vector<cricket::Candidate>& candidates) override;
+
  private:
   __weak RTCPeerConnection *peer_connection_;
 };
diff --git a/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection.mm b/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection.mm
index 9a488fd..3fcc652 100644
--- a/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection.mm
+++ b/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection.mm
@@ -25,6 +25,7 @@
 
 #include <memory>
 
+#include "webrtc/api/jsepicecandidate.h"
 #include "webrtc/base/checks.h"
 
 NSString * const kRTCPeerConnectionErrorDomain =
@@ -182,6 +183,23 @@
   [peer_connection.delegate peerConnection:peer_connection
                    didGenerateIceCandidate:iceCandidate];
 }
+
+void PeerConnectionDelegateAdapter::OnIceCandidatesRemoved(
+    const std::vector<cricket::Candidate>& candidates) {
+  NSMutableArray* ice_candidates =
+      [NSMutableArray arrayWithCapacity:candidates.size()];
+  for (const auto& candidate : candidates) {
+    std::unique_ptr<JsepIceCandidate> candidate_wrapper(
+        new JsepIceCandidate(candidate.transport_name(), -1, candidate));
+    RTCIceCandidate* ice_candidate = [[RTCIceCandidate alloc]
+        initWithNativeCandidate:candidate_wrapper.get()];
+    [ice_candidates addObject:ice_candidate];
+  }
+  RTCPeerConnection* peer_connection = peer_connection_;
+  [peer_connection.delegate peerConnection:peer_connection
+                    didRemoveIceCandidates:ice_candidates];
+}
+
 }  // namespace webrtc
 
 
@@ -273,6 +291,22 @@
   _peerConnection->AddIceCandidate(iceCandidate.get());
 }
 
+- (void)removeIceCandidates:(NSArray<RTCIceCandidate *> *)iceCandidates {
+  std::vector<cricket::Candidate> candidates;
+  for (RTCIceCandidate *iceCandidate in iceCandidates) {
+    std::unique_ptr<const webrtc::IceCandidateInterface> candidate(
+        iceCandidate.nativeCandidate);
+    if (candidate) {
+      candidates.push_back(candidate->candidate());
+      // Need to fill the transport name from the sdp_mid.
+      candidates.back().set_transport_name(candidate->sdp_mid());
+    }
+  }
+  if (!candidates.empty()) {
+    _peerConnection->RemoveIceCandidates(candidates);
+  }
+}
+
 - (void)addStream:(RTCMediaStream *)stream {
   if (!_peerConnection->AddStream(stream.nativeMediaStream)) {
     RTCLogError(@"Failed to add stream: %@", stream);