Make the JsepSessionDesription clone() method copy candidates.

Bug: webrtc:12323
Change-Id: I54ba73a8f58d47eba6edcee521fc3efd13b95a79
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/199966
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32904}
diff --git a/api/jsep_ice_candidate.h b/api/jsep_ice_candidate.h
index 4ee84cf..1a4247c 100644
--- a/api/jsep_ice_candidate.h
+++ b/api/jsep_ice_candidate.h
@@ -34,6 +34,8 @@
   JsepIceCandidate(const std::string& sdp_mid,
                    int sdp_mline_index,
                    const cricket::Candidate& candidate);
+  JsepIceCandidate(const JsepIceCandidate&) = delete;
+  JsepIceCandidate& operator=(const JsepIceCandidate&) = delete;
   ~JsepIceCandidate() override;
   // |err| may be null.
   bool Initialize(const std::string& sdp, SdpParseError* err);
@@ -53,8 +55,6 @@
   std::string sdp_mid_;
   int sdp_mline_index_;
   cricket::Candidate candidate_;
-
-  RTC_DISALLOW_COPY_AND_ASSIGN(JsepIceCandidate);
 };
 
 // Implementation of IceCandidateCollection which stores JsepIceCandidates.
@@ -64,6 +64,8 @@
   // Move constructor is defined so that a vector of JsepCandidateCollections
   // can be resized.
   JsepCandidateCollection(JsepCandidateCollection&& o);
+  // Returns a copy of the candidate collection.
+  JsepCandidateCollection Clone() const;
   size_t count() const override;
   bool HasCandidate(const IceCandidateInterface* candidate) const override;
   // Adds and takes ownership of the JsepIceCandidate.
diff --git a/pc/jsep_ice_candidate.cc b/pc/jsep_ice_candidate.cc
index 4e45421..6dacde6 100644
--- a/pc/jsep_ice_candidate.cc
+++ b/pc/jsep_ice_candidate.cc
@@ -14,6 +14,11 @@
 
 #include "pc/webrtc_sdp.h"
 
+// This file contains JsepIceCandidate-related functions that are not
+// included in api/jsep_ice_candidate.cc. Some of these link to SDP
+// parsing/serializing functions, which some users may not want.
+// TODO(bugs.webrtc.org/12330): Merge the two .cc files somehow.
+
 namespace webrtc {
 
 IceCandidateInterface* CreateIceCandidate(const std::string& sdp_mid,
@@ -49,6 +54,16 @@
 
 JsepIceCandidate::~JsepIceCandidate() {}
 
+JsepCandidateCollection JsepCandidateCollection::Clone() const {
+  JsepCandidateCollection new_collection;
+  for (const auto& candidate : candidates_) {
+    new_collection.candidates_.push_back(std::make_unique<JsepIceCandidate>(
+        candidate->sdp_mid(), candidate->sdp_mline_index(),
+        candidate->candidate()));
+  }
+  return new_collection;
+}
+
 bool JsepIceCandidate::Initialize(const std::string& sdp, SdpParseError* err) {
   return SdpDeserializeCandidate(sdp, this, err);
 }
diff --git a/pc/jsep_session_description.cc b/pc/jsep_session_description.cc
index e0b2311..9de8194 100644
--- a/pc/jsep_session_description.cc
+++ b/pc/jsep_session_description.cc
@@ -218,8 +218,12 @@
 std::unique_ptr<SessionDescriptionInterface> JsepSessionDescription::Clone()
     const {
   auto new_description = std::make_unique<JsepSessionDescription>(type_);
-  new_description->Initialize(description_->Clone(), session_id_,
-                              session_version_);
+  new_description->session_id_ = session_id_;
+  new_description->session_version_ = session_version_;
+  new_description->description_ = description_->Clone();
+  for (const auto& collection : candidate_collection_) {
+    new_description->candidate_collection_.push_back(collection.Clone());
+  }
   return new_description;
 }
 
diff --git a/pc/jsep_session_description_unittest.cc b/pc/jsep_session_description_unittest.cc
index 7f83c08..d922a58 100644
--- a/pc/jsep_session_description_unittest.cc
+++ b/pc/jsep_session_description_unittest.cc
@@ -129,6 +129,33 @@
   EXPECT_EQ(jsep_desc_->session_version(), new_desc->session_version());
 }
 
+TEST_F(JsepSessionDescriptionTest, CloneWithCandidates) {
+  cricket::Candidate candidate_v4(
+      cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
+      rtc::SocketAddress("192.168.1.5", 1234), kCandidatePriority, "", "",
+      cricket::STUN_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
+  cricket::Candidate candidate_v6(
+      cricket::ICE_CANDIDATE_COMPONENT_RTP, "udp",
+      rtc::SocketAddress("::1", 1234), kCandidatePriority, "", "",
+      cricket::LOCAL_PORT_TYPE, kCandidateGeneration, kCandidateFoundation);
+
+  JsepIceCandidate jice_v4("audio", 0, candidate_v4);
+  JsepIceCandidate jice_v6("audio", 0, candidate_v6);
+  JsepIceCandidate jice_v4_video("video", 0, candidate_v4);
+  JsepIceCandidate jice_v6_video("video", 0, candidate_v6);
+  ASSERT_TRUE(jsep_desc_->AddCandidate(&jice_v4));
+  ASSERT_TRUE(jsep_desc_->AddCandidate(&jice_v6));
+  ASSERT_TRUE(jsep_desc_->AddCandidate(&jice_v4_video));
+  ASSERT_TRUE(jsep_desc_->AddCandidate(&jice_v6_video));
+  auto new_desc = jsep_desc_->Clone();
+  EXPECT_EQ(jsep_desc_->type(), new_desc->type());
+  std::string old_desc_string;
+  std::string new_desc_string;
+  EXPECT_TRUE(jsep_desc_->ToString(&old_desc_string));
+  EXPECT_TRUE(new_desc->ToString(&new_desc_string));
+  EXPECT_EQ(old_desc_string, new_desc_string);
+}
+
 // Test that number_of_mediasections() returns the number of media contents in
 // a session description.
 TEST_F(JsepSessionDescriptionTest, CheckSessionDescription) {