Expose parameterless setLocalDescription() in iOS SDK.

Parameterless setLocalDescription is used to implement perfect
negotiation algorithm.

Bug: None
Change-Id: I89c39ee175fec5b09d9ca1700ef682e3cf20fe94
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/209700
Commit-Queue: Kári Helgason <kthelgason@webrtc.org>
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33401}
diff --git a/sdk/objc/api/peerconnection/RTCPeerConnection.h b/sdk/objc/api/peerconnection/RTCPeerConnection.h
index a332b2e..b33cef0 100644
--- a/sdk/objc/api/peerconnection/RTCPeerConnection.h
+++ b/sdk/objc/api/peerconnection/RTCPeerConnection.h
@@ -300,6 +300,11 @@
 - (void)setLocalDescription:(RTC_OBJC_TYPE(RTCSessionDescription) *)sdp
           completionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler;
 
+/** Creates an offer or answer (depending on current signaling state) and sets
+ * it as the local session description. */
+- (void)setLocalDescriptionWithCompletionHandler:
+    (nullable void (^)(NSError *_Nullable error))completionHandler;
+
 /** Apply the supplied RTCSessionDescription as the remote description. */
 - (void)setRemoteDescription:(RTC_OBJC_TYPE(RTCSessionDescription) *)sdp
            completionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler;
diff --git a/sdk/objc/api/peerconnection/RTCPeerConnection.mm b/sdk/objc/api/peerconnection/RTCPeerConnection.mm
index 766b61f..59fcd0c 100644
--- a/sdk/objc/api/peerconnection/RTCPeerConnection.mm
+++ b/sdk/objc/api/peerconnection/RTCPeerConnection.mm
@@ -29,12 +29,58 @@
 
 #include "api/jsep_ice_candidate.h"
 #include "api/rtc_event_log_output_file.h"
+#include "api/set_local_description_observer_interface.h"
+#include "api/set_remote_description_observer_interface.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_conversions.h"
 
 NSString *const kRTCPeerConnectionErrorDomain = @"org.webrtc.RTC_OBJC_TYPE(RTCPeerConnection)";
 int const kRTCPeerConnnectionSessionDescriptionError = -1;
 
+typedef void (^RTCSetSessionDescriptionCompletionHandler)(NSError *_Nullable error);
+
+namespace {
+
+class SetSessionDescriptionObserver : public webrtc::SetLocalDescriptionObserverInterface,
+                                      public webrtc::SetRemoteDescriptionObserverInterface {
+ public:
+  SetSessionDescriptionObserver(
+      RTCSetSessionDescriptionCompletionHandler _Nullable completionHandler) {
+    completion_handler_ = completionHandler;
+  }
+
+  virtual void OnSetLocalDescriptionComplete(webrtc::RTCError error) override {
+    if (completion_handler_ != nil) {
+      OnCompelete(error);
+    }
+  }
+
+  virtual void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override {
+    if (completion_handler_ != nil) {
+      OnCompelete(error);
+    }
+  }
+
+ private:
+  void OnCompelete(webrtc::RTCError error) {
+    RTC_DCHECK(completion_handler_);
+    if (error.ok()) {
+      completion_handler_(nil);
+    } else {
+      // TODO(hta): Add handling of error.type()
+      NSString *str = [NSString stringForStdString:error.message()];
+      NSError *err = [NSError errorWithDomain:kRTCPeerConnectionErrorDomain
+                                         code:kRTCPeerConnnectionSessionDescriptionError
+                                     userInfo:@{NSLocalizedDescriptionKey : str}];
+      completion_handler_(err);
+    }
+    completion_handler_ = nil;
+  }
+  RTCSetSessionDescriptionCompletionHandler completion_handler_;
+};
+
+}  // anonymous namespace
+
 namespace webrtc {
 
 class CreateSessionDescriptionObserverAdapter
@@ -74,38 +120,6 @@
                               NSError *error);
 };
 
-class SetSessionDescriptionObserverAdapter :
-    public SetSessionDescriptionObserver {
- public:
-  SetSessionDescriptionObserverAdapter(void (^completionHandler)
-      (NSError *error)) {
-    completion_handler_ = completionHandler;
-  }
-
-  ~SetSessionDescriptionObserverAdapter() override { completion_handler_ = nil; }
-
-  void OnSuccess() override {
-    RTC_DCHECK(completion_handler_);
-    completion_handler_(nil);
-    completion_handler_ = nil;
-  }
-
-  void OnFailure(RTCError error) override {
-    RTC_DCHECK(completion_handler_);
-    // TODO(hta): Add handling of error.type()
-    NSString *str = [NSString stringForStdString:error.message()];
-    NSError* err =
-        [NSError errorWithDomain:kRTCPeerConnectionErrorDomain
-                            code:kRTCPeerConnnectionSessionDescriptionError
-                        userInfo:@{ NSLocalizedDescriptionKey : str }];
-    completion_handler_(err);
-    completion_handler_ = nil;
-  }
-
- private:
-  void (^completion_handler_)(NSError *error);
-};
-
 PeerConnectionDelegateAdapter::PeerConnectionDelegateAdapter(RTC_OBJC_TYPE(RTCPeerConnection) *
                                                              peerConnection) {
   peer_connection_ = peerConnection;
@@ -548,19 +562,24 @@
 }
 
 - (void)setLocalDescription:(RTC_OBJC_TYPE(RTCSessionDescription) *)sdp
-          completionHandler:(void (^)(NSError *error))completionHandler {
-  rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
-      new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
-          completionHandler));
-  _peerConnection->SetLocalDescription(observer, sdp.nativeDescription);
+          completionHandler:(nullable void (^)(NSError *error))completionHandler {
+  rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface> observer(
+      new rtc::RefCountedObject<::SetSessionDescriptionObserver>(completionHandler));
+  _peerConnection->SetLocalDescription(sdp.nativeDescription->Clone(), observer);
+}
+
+- (void)setLocalDescriptionWithCompletionHandler:
+    (nullable void (^)(NSError *error))completionHandler {
+  rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface> observer(
+      new rtc::RefCountedObject<::SetSessionDescriptionObserver>(completionHandler));
+  _peerConnection->SetLocalDescription(observer);
 }
 
 - (void)setRemoteDescription:(RTC_OBJC_TYPE(RTCSessionDescription) *)sdp
-           completionHandler:(void (^)(NSError *error))completionHandler {
-  rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
-      new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
-          completionHandler));
-  _peerConnection->SetRemoteDescription(observer, sdp.nativeDescription);
+           completionHandler:(nullable void (^)(NSError *error))completionHandler {
+  rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface> observer(
+      new rtc::RefCountedObject<::SetSessionDescriptionObserver>(completionHandler));
+  _peerConnection->SetRemoteDescription(sdp.nativeDescription->Clone(), observer);
 }
 
 - (BOOL)setBweMinBitrateBps:(nullable NSNumber *)minBitrateBps