[Unified Plan] Support legacy endpoints that do not use a=mid

These legacy endpoints were supported with Plan B since the SDP
parser would fill in default MID values if a=mid was absent that
happened to match the default offered MIDs.

With Unified Plan, these default MIDs changed so the autofilled
MIDs do not match any more.

This CL adds information to the SessionDescription struct to
indicate whether or not a=mid was present and modified
PeerConnection::SetRemoteDescription to copy MIDs from the local
description if the a=mid lines are not present.

Bug: webrtc:9540
Change-Id: Ibf923b4ad59edb0facd06ddbd01cc10c62fc48e6
Reviewed-on: https://webrtc-review.googlesource.com/c/114820
Commit-Queue: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Amit Hilbuch <amithi@webrtc.org>
Reviewed-by: Seth Hampson <shampson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26054}
diff --git a/pc/webrtcsdp_unittest.cc b/pc/webrtcsdp_unittest.cc
index 0ecba4c..849f6c5 100644
--- a/pc/webrtcsdp_unittest.cc
+++ b/pc/webrtcsdp_unittest.cc
@@ -38,6 +38,7 @@
 #include "rtc_base/sslfingerprint.h"
 #include "rtc_base/stringencode.h"
 #include "rtc_base/stringutils.h"
+#include "test/gmock.h"
 #include "test/gtest.h"
 
 #ifdef WEBRTC_ANDROID
@@ -48,20 +49,20 @@
 using cricket::AudioCodec;
 using cricket::AudioContentDescription;
 using cricket::Candidate;
+using cricket::ContentGroup;
 using cricket::ContentInfo;
 using cricket::CryptoParams;
-using cricket::ContentGroup;
 using cricket::DataCodec;
 using cricket::DataContentDescription;
 using cricket::ICE_CANDIDATE_COMPONENT_RTCP;
 using cricket::ICE_CANDIDATE_COMPONENT_RTP;
 using cricket::kFecSsrcGroupSemantics;
 using cricket::LOCAL_PORT_TYPE;
-using cricket::RELAY_PORT_TYPE;
-using cricket::SessionDescription;
 using cricket::MediaProtocolType;
+using cricket::RELAY_PORT_TYPE;
 using cricket::RidDescription;
 using cricket::RidDirection;
+using cricket::SessionDescription;
 using cricket::SimulcastDescription;
 using cricket::SimulcastLayer;
 using cricket::StreamParams;
@@ -70,6 +71,8 @@
 using cricket::TransportInfo;
 using cricket::VideoCodec;
 using cricket::VideoContentDescription;
+using ::testing::ElementsAre;
+using ::testing::Field;
 using webrtc::IceCandidateCollection;
 using webrtc::IceCandidateInterface;
 using webrtc::JsepIceCandidate;
@@ -1032,10 +1035,10 @@
     desc_.AddContent(kVideoContentName, MediaProtocolType::kRtp, video_desc_);
 
     // TransportInfo
-    EXPECT_TRUE(desc_.AddTransportInfo(TransportInfo(
-        kAudioContentName, TransportDescription(kUfragVoice, kPwdVoice))));
-    EXPECT_TRUE(desc_.AddTransportInfo(TransportInfo(
-        kVideoContentName, TransportDescription(kUfragVideo, kPwdVideo))));
+    desc_.AddTransportInfo(TransportInfo(
+        kAudioContentName, TransportDescription(kUfragVoice, kPwdVoice)));
+    desc_.AddTransportInfo(TransportInfo(
+        kVideoContentName, TransportDescription(kUfragVideo, kPwdVideo)));
 
     // v4 host
     int port = 1234;
@@ -1231,8 +1234,8 @@
     }
     audio_desc_2->AddStream(audio_track_2);
     desc_.AddContent(kAudioContentName2, MediaProtocolType::kRtp, audio_desc_2);
-    EXPECT_TRUE(desc_.AddTransportInfo(TransportInfo(
-        kAudioContentName2, TransportDescription(kUfragVoice2, kPwdVoice2))));
+    desc_.AddTransportInfo(TransportInfo(
+        kAudioContentName2, TransportDescription(kUfragVoice2, kPwdVoice2)));
     // Video track 2, in stream 2.
     VideoContentDescription* video_desc_2 = CreateVideoContentDescription();
     StreamParams video_track_2;
@@ -1244,8 +1247,8 @@
     }
     video_desc_2->AddStream(video_track_2);
     desc_.AddContent(kVideoContentName2, MediaProtocolType::kRtp, video_desc_2);
-    EXPECT_TRUE(desc_.AddTransportInfo(TransportInfo(
-        kVideoContentName2, TransportDescription(kUfragVideo2, kPwdVideo2))));
+    desc_.AddTransportInfo(TransportInfo(
+        kVideoContentName2, TransportDescription(kUfragVideo2, kPwdVideo2)));
 
     // Video track 3, in stream 2.
     VideoContentDescription* video_desc_3 = CreateVideoContentDescription();
@@ -1258,8 +1261,8 @@
     }
     video_desc_3->AddStream(video_track_3);
     desc_.AddContent(kVideoContentName3, MediaProtocolType::kRtp, video_desc_3);
-    EXPECT_TRUE(desc_.AddTransportInfo(TransportInfo(
-        kVideoContentName3, TransportDescription(kUfragVideo3, kPwdVideo3))));
+    desc_.AddTransportInfo(TransportInfo(
+        kVideoContentName3, TransportDescription(kUfragVideo3, kPwdVideo3)));
     desc_.set_msid_signaling(cricket::kMsidSignalingMediaSection);
 
     ASSERT_TRUE(jdesc_.Initialize(desc_.Copy(), jdesc_.session_id(),
@@ -1302,8 +1305,8 @@
     audio_track_2.ssrcs.push_back(kAudioTrack2Ssrc);
     audio_desc_2->AddStream(audio_track_2);
     desc_.AddContent(kAudioContentName2, MediaProtocolType::kRtp, audio_desc_2);
-    EXPECT_TRUE(desc_.AddTransportInfo(TransportInfo(
-        kAudioContentName2, TransportDescription(kUfragVoice2, kPwdVoice2))));
+    desc_.AddTransportInfo(TransportInfo(
+        kAudioContentName2, TransportDescription(kUfragVoice2, kPwdVoice2)));
 
     // Audio track 3 has no stream ids.
     AudioContentDescription* audio_desc_3 = CreateAudioContentDescription();
@@ -1314,8 +1317,8 @@
     audio_track_3.ssrcs.push_back(kAudioTrack3Ssrc);
     audio_desc_3->AddStream(audio_track_3);
     desc_.AddContent(kAudioContentName3, MediaProtocolType::kRtp, audio_desc_3);
-    EXPECT_TRUE(desc_.AddTransportInfo(TransportInfo(
-        kAudioContentName3, TransportDescription(kUfragVoice3, kPwdVoice3))));
+    desc_.AddTransportInfo(TransportInfo(
+        kAudioContentName3, TransportDescription(kUfragVoice3, kPwdVoice3)));
     desc_.set_msid_signaling(msid_signaling);
     ASSERT_TRUE(jdesc_.Initialize(desc_.Copy(), jdesc_.session_id(),
                                   jdesc_.session_version()));
@@ -1614,7 +1617,7 @@
     SessionDescription* desc =
         const_cast<SessionDescription*>(jdesc->description());
     desc->RemoveTransportInfoByName(content_name);
-    EXPECT_TRUE(desc->AddTransportInfo(transport_info));
+    desc->AddTransportInfo(transport_info);
     for (size_t i = 0; i < jdesc_.number_of_mediasections(); ++i) {
       const IceCandidateCollection* cc = jdesc_.candidates(i);
       for (size_t j = 0; j < cc->count(); ++j) {
@@ -1653,16 +1656,16 @@
     desc_.RemoveTransportInfoByName(kAudioContentName);
     desc_.RemoveTransportInfoByName(kVideoContentName);
     rtc::SSLFingerprint fingerprint(rtc::DIGEST_SHA_1, kIdentityDigest);
-    EXPECT_TRUE(desc_.AddTransportInfo(TransportInfo(
+    desc_.AddTransportInfo(TransportInfo(
         kAudioContentName,
         TransportDescription(std::vector<std::string>(), kUfragVoice, kPwdVoice,
                              cricket::ICEMODE_FULL,
-                             cricket::CONNECTIONROLE_NONE, &fingerprint))));
-    EXPECT_TRUE(desc_.AddTransportInfo(TransportInfo(
+                             cricket::CONNECTIONROLE_NONE, &fingerprint)));
+    desc_.AddTransportInfo(TransportInfo(
         kVideoContentName,
         TransportDescription(std::vector<std::string>(), kUfragVideo, kPwdVideo,
                              cricket::ICEMODE_FULL,
-                             cricket::CONNECTIONROLE_NONE, &fingerprint))));
+                             cricket::CONNECTIONROLE_NONE, &fingerprint)));
   }
 
   void AddExtmap(bool encrypted) {
@@ -1779,8 +1782,8 @@
     data_desc_->AddCodec(codec);
     desc_.AddContent(kDataContentName, MediaProtocolType::kSctp,
                      data.release());
-    EXPECT_TRUE(desc_.AddTransportInfo(TransportInfo(
-        kDataContentName, TransportDescription(kUfragData, kPwdData))));
+    desc_.AddTransportInfo(TransportInfo(
+        kDataContentName, TransportDescription(kUfragData, kPwdData)));
   }
 
   void AddRtpDataChannel() {
@@ -1799,8 +1802,8 @@
                      "inline:FvLcvU2P3ZWmQxgPAgcDu7Zl9vftYElFOjEzhWs5", ""));
     data_desc_->set_protocol(cricket::kMediaProtocolSavpf);
     desc_.AddContent(kDataContentName, MediaProtocolType::kRtp, data.release());
-    EXPECT_TRUE(desc_.AddTransportInfo(TransportInfo(
-        kDataContentName, TransportDescription(kUfragData, kPwdData))));
+    desc_.AddTransportInfo(TransportInfo(
+        kDataContentName, TransportDescription(kUfragData, kPwdData)));
   }
 
   bool TestDeserializeDirection(RtpTransceiverDirection direction) {
@@ -2450,9 +2453,7 @@
   JsepSessionDescription jdesc(kDummyType);
   EXPECT_TRUE(SdpDeserialize(kSdpNoRtpmapString, &jdesc));
   cricket::AudioContentDescription* audio =
-      jdesc.description()
-          ->GetContentDescriptionByName(cricket::CN_AUDIO)
-          ->as_audio();
+      cricket::GetFirstAudioContentDescription(jdesc.description());
   AudioCodecs ref_codecs;
   // The codecs in the AudioContentDescription should be in the same order as
   // the payload types (<fmt>s) on the m= line.
@@ -2475,9 +2476,7 @@
   JsepSessionDescription jdesc(kDummyType);
   EXPECT_TRUE(SdpDeserialize(kSdpNoRtpmapString, &jdesc));
   cricket::AudioContentDescription* audio =
-      jdesc.description()
-          ->GetContentDescriptionByName(cricket::CN_AUDIO)
-          ->as_audio();
+      cricket::GetFirstAudioContentDescription(jdesc.description());
 
   cricket::AudioCodec g729 = audio->codecs()[0];
   EXPECT_EQ("G729", g729.name);
@@ -3074,15 +3073,11 @@
 
   // Verify
   cricket::AudioContentDescription* audio =
-      jdesc.description()
-          ->GetContentDescriptionByName(cricket::CN_AUDIO)
-          ->as_audio();
+      cricket::GetFirstAudioContentDescription(jdesc.description());
   EXPECT_TRUE(audio->conference_mode());
 
   cricket::VideoContentDescription* video =
-      jdesc.description()
-          ->GetContentDescriptionByName(cricket::CN_VIDEO)
-          ->as_video();
+      cricket::GetFirstVideoContentDescription(jdesc.description());
   EXPECT_TRUE(video->conference_mode());
 }
 
@@ -3097,15 +3092,11 @@
 
   // Verify.
   cricket::AudioContentDescription* audio =
-      jdesc.description()
-          ->GetContentDescriptionByName(cricket::CN_AUDIO)
-          ->as_audio();
+      cricket::GetFirstAudioContentDescription(jdesc.description());
   EXPECT_TRUE(audio->conference_mode());
 
   cricket::VideoContentDescription* video =
-      jdesc.description()
-          ->GetContentDescriptionByName(cricket::CN_VIDEO)
-          ->as_video();
+      cricket::GetFirstVideoContentDescription(jdesc.description());
   EXPECT_TRUE(video->conference_mode());
 }
 
@@ -4318,3 +4309,19 @@
 
   TestSerialize(jdesc_);
 }
+
+// Test that the content name is empty if the media section does not have an
+// a=mid line.
+TEST_F(WebRtcSdpTest, ParseNoMid) {
+  std::string sdp = kSdpString;
+  Replace("a=mid:audio_content_name\r\n", "", &sdp);
+  Replace("a=mid:video_content_name\r\n", "", &sdp);
+
+  JsepSessionDescription output(kDummyType);
+  SdpParseError error;
+  ASSERT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
+
+  EXPECT_THAT(output.description()->contents(),
+              ElementsAre(Field("name", &cricket::ContentInfo::name, ""),
+                          Field("name", &cricket::ContentInfo::name, "")));
+}