commit 93afb7fe93cf4e5abd194bf084dd947b245a8ae0
parent c3450ad20fff8e19e42c75aec71b743253543106
Author: Michael Froman <mfroman@mozilla.com>
Date: Wed, 8 Oct 2025 15:33:54 -0500
Bug 1993083 - Vendor libwebrtc from 84d07a37d9
Upstream commit: https://webrtc.googlesource.com/src/+/84d07a37d9f2fcb41fdee0d2be0199eda962bcd9
munging: add field trial to control when to throw
WebRTC-NoSdpMangle/Enabled,1,2,83/
allows for finch rollout of restrictions without requiring a code change to turn off low-usage munging.
WebRTC-NoSdpMangleForTesting/Enabled,1,2,83/
will reject any modification by default unless it is part of the
comma-separated list of exceptions. This allows for proactive deactivation and adding E2E tests.
Bug: chromium:40567530
Change-Id: If57602089dcc3e9372044b37996ec4c468fdd0cb
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/395340
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@webrtc.org>
Commit-Queue: Philipp Hancke <phancke@meta.com>
Cr-Commit-Position: refs/heads/main@{#44981}
Diffstat:
8 files changed, 191 insertions(+), 3 deletions(-)
diff --git a/third_party/libwebrtc/README.mozilla.last-vendor b/third_party/libwebrtc/README.mozilla.last-vendor
@@ -1,4 +1,4 @@
# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
-libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-08T20:32:42.417925+00:00.
+libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-08T20:33:45.058808+00:00.
# base of lastest vendoring
-ea929e9ce1
+84d07a37d9
diff --git a/third_party/libwebrtc/experiments/field_trials.py b/third_party/libwebrtc/experiments/field_trials.py
@@ -125,6 +125,12 @@ ACTIVE_FIELD_TRIALS: FrozenSet[FieldTrial] = frozenset([
FieldTrial('WebRTC-NoSdpMangleNumberOfContents',
40567530,
date(2025, 10, 11)),
+ FieldTrial('WebRTC-NoSdpMangleReject',
+ 40567530,
+ date(2026, 6, 1)),
+ FieldTrial('WebRTC-NoSdpMangleAllowForTesting',
+ 40567530,
+ date(2026, 6, 1)),
FieldTrial('WebRTC-Pacer-FastRetransmissions',
40235589,
date(2024, 4, 1)),
diff --git a/third_party/libwebrtc/moz-patch-stack/s0103.patch b/third_party/libwebrtc/moz-patch-stack/s0103.patch
@@ -601,7 +601,7 @@ index 16290b35f7..71ba90f630 100644
import("../../webrtc.gni")
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
-index 9b4f1ce01f..79a6f4f36c 100644
+index 4b98a026ca..ca03ab219a 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -30,8 +30,8 @@
diff --git a/third_party/libwebrtc/pc/BUILD.gn b/third_party/libwebrtc/pc/BUILD.gn
@@ -1059,6 +1059,7 @@ rtc_library("sdp_munging_detector") {
]
deps = [
":session_description",
+ "../api:field_trials_view",
"../api:libjingle_peerconnection_api",
"../api:rtp_parameters",
"../media:codec",
@@ -1069,6 +1070,8 @@ rtc_library("sdp_munging_detector") {
"../rtc_base:checks",
"../rtc_base:logging",
"//third_party/abseil-cpp/absl/algorithm:container",
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/strings:string_view",
]
}
rtc_library("sdp_offer_answer") {
@@ -2430,6 +2433,7 @@ if (rtc_include_tests && !build_with_chromium) {
":sctp_data_channel",
":sctp_transport",
":sctp_utils",
+ ":sdp_munging_detector",
":sdp_utils",
":session_description",
":simulcast_description",
diff --git a/third_party/libwebrtc/pc/sdp_munging_detector.cc b/third_party/libwebrtc/pc/sdp_munging_detector.cc
@@ -13,8 +13,12 @@
#include <algorithm>
#include <cstddef>
#include <string>
+#include <vector>
#include "absl/algorithm/container.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+#include "api/field_trials_view.h"
#include "api/jsep.h"
#include "api/media_types.h"
#include "api/uma_metrics.h"
@@ -563,4 +567,33 @@ bool HasUfragSdpMunging(const SessionDescriptionInterface* sdesc,
return false;
}
+bool IsSdpMungingAllowed(SdpMungingType sdp_munging_type,
+ const FieldTrialsView& trials) {
+ if (sdp_munging_type == SdpMungingType::kNoModification) {
+ return true;
+ }
+ std::string type_as_string =
+ std::to_string(static_cast<int>(sdp_munging_type));
+
+ std::string trial;
+ // NoSdpMangleReject is for rollout, disallowing specific types of munging
+ // via Finch. It is a comma-separated list of SdpMungingTypes
+ if (trials.IsEnabled("WebRTC-NoSdpMangleReject")) {
+ trial = trials.Lookup("WebRTC-NoSdpMangleReject");
+ const std::vector<absl::string_view> rejected_types =
+ absl::StrSplit(trial, ',');
+ return absl::c_find(rejected_types, type_as_string) == rejected_types.end();
+ }
+ // NoSdpMangleAllowForTesting is for running E2E tests which should reject
+ // by default with a test-supplied list of exceptions as a comma-separated
+ // list.
+ if (!trials.IsEnabled("WebRTC-NoSdpMangleAllowForTesting")) {
+ return true;
+ }
+ trial = trials.Lookup("WebRTC-NoSdpMangleAllowForTesting");
+ const std::vector<absl::string_view> allowed_types =
+ absl::StrSplit(trial, ',');
+ return absl::c_find(allowed_types, type_as_string) != allowed_types.end();
+}
+
} // namespace webrtc
diff --git a/third_party/libwebrtc/pc/sdp_munging_detector.h b/third_party/libwebrtc/pc/sdp_munging_detector.h
@@ -11,6 +11,7 @@
#ifndef PC_SDP_MUNGING_DETECTOR_H_
#define PC_SDP_MUNGING_DETECTOR_H_
+#include "api/field_trials_view.h"
#include "api/jsep.h"
#include "api/uma_metrics.h"
@@ -24,6 +25,11 @@ SdpMungingType DetermineSdpMungingType(
bool HasUfragSdpMunging(const SessionDescriptionInterface* sdesc,
const SessionDescriptionInterface* last_created_desc);
+// Determines if SDP munging is allowed. This is determined based on the field
+// trials WebRTC-NoSdpMangle and WebRTC-NoSdpMangleForTesting.
+bool IsSdpMungingAllowed(SdpMungingType sdp_munging_type,
+ const FieldTrialsView& trials);
+
} // namespace webrtc
#endif // PC_SDP_MUNGING_DETECTOR_H_
diff --git a/third_party/libwebrtc/pc/sdp_munging_detector_unittest.cc b/third_party/libwebrtc/pc/sdp_munging_detector_unittest.cc
@@ -7,6 +7,7 @@
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
+#include "pc/sdp_munging_detector.h"
#include <algorithm>
#include <cstddef>
@@ -204,6 +205,142 @@ TEST_F(SdpMungingTest, DISABLED_ReportUMAMetricsWithNoMunging) {
ElementsAre(Pair(SdpMungingType::kNoModification, 1)));
}
+TEST_F(SdpMungingTest, AllowWithDenyListForRollout) {
+ // Don't munge and you are good.
+ EXPECT_TRUE(IsSdpMungingAllowed(SdpMungingType::kNoModification,
+ *FieldTrials::CreateNoGlobal("")));
+ // Empty string (default) means everything is allowed from the perspective of
+ // the trial.
+ EXPECT_TRUE(IsSdpMungingAllowed(SdpMungingType::kUnknownModification,
+ *FieldTrials::CreateNoGlobal("")));
+
+ // Deny list is set, modification on deny list is rejected.
+ EXPECT_FALSE(IsSdpMungingAllowed(
+ SdpMungingType::kUnknownModification /*=1*/,
+ *FieldTrials::CreateNoGlobal("WebRTC-NoSdpMangleReject/Enabled,1/")));
+
+ // Deny list is set, modification not on deny list is allowed.
+ EXPECT_TRUE(IsSdpMungingAllowed(
+ SdpMungingType::kWithoutCreateAnswer /*=2*/,
+ *FieldTrials::CreateNoGlobal("WebRTC-NoSdpMangleReject/Enabled,1/")));
+
+ // Split by comma.
+ EXPECT_FALSE(IsSdpMungingAllowed(
+ SdpMungingType::kUnknownModification /*=1*/,
+ *FieldTrials::CreateNoGlobal("WebRTC-NoSdpMangleReject/Enabled,1,2/")));
+ EXPECT_FALSE(IsSdpMungingAllowed(
+ SdpMungingType::kWithoutCreateAnswer /*=2*/,
+ *FieldTrials::CreateNoGlobal("WebRTC-NoSdpMangleReject/Enabled,1,2/")));
+ EXPECT_TRUE(IsSdpMungingAllowed(
+ SdpMungingType::kWithoutCreateOffer /*=3*/,
+ *FieldTrials::CreateNoGlobal("WebRTC-NoSdpMangleReject/Enabled,1,2,4/")));
+}
+
+TEST_F(SdpMungingTest, DenyWithAllowListForTesting) {
+ // Don't munge and you are good.
+ EXPECT_TRUE(IsSdpMungingAllowed(SdpMungingType::kNoModification,
+ *FieldTrials::CreateNoGlobal("")));
+ // Empty string (default) means everything is allowed from the perspective of
+ // the trial.
+ EXPECT_TRUE(IsSdpMungingAllowed(SdpMungingType::kUnknownModification,
+ *FieldTrials::CreateNoGlobal("")));
+
+ // Allow-list is set, modification is on allow list.
+ EXPECT_TRUE(
+ IsSdpMungingAllowed(SdpMungingType::kUnknownModification /*=1*/,
+ *FieldTrials::CreateNoGlobal(
+ "WebRTC-NoSdpMangleAllowForTesting/Enabled,1/")));
+
+ // Allow-list is set, modification is not on allow list.
+ EXPECT_FALSE(
+ IsSdpMungingAllowed(SdpMungingType::kWithoutCreateAnswer /*=2*/,
+ *FieldTrials::CreateNoGlobal(
+ "WebRTC-NoSdpMangleAllowForTesting/Enabled,1/")));
+
+ // Split by comma.
+ EXPECT_TRUE(IsSdpMungingAllowed(
+ SdpMungingType::kUnknownModification /*=1*/,
+ *FieldTrials::CreateNoGlobal(
+ "WebRTC-NoSdpMangleAllowForTesting/Enabled,1,2/")));
+ EXPECT_TRUE(IsSdpMungingAllowed(
+ SdpMungingType::kWithoutCreateAnswer /*=2*/,
+ *FieldTrials::CreateNoGlobal(
+ "WebRTC-NoSdpMangleAllowForTesting/Enabled,1,2/")));
+ EXPECT_FALSE(IsSdpMungingAllowed(
+ SdpMungingType::kWithoutCreateOffer /*=3*/,
+ *FieldTrials::CreateNoGlobal(
+ "WebRTC-NoSdpMangleAllowForTesting/Enabled,1,2,4/")));
+}
+
+TEST_F(SdpMungingTest, AllowListAcceptsUnmunged) {
+ auto pc = CreatePeerConnection("WebRTC-NoSdpMangle/Enabled/");
+ pc->AddAudioTrack("audio_track", {});
+
+ auto offer = pc->CreateOffer();
+ RTCError error;
+ EXPECT_TRUE(pc->SetLocalDescription(std::move(offer), &error));
+}
+
+TEST_F(SdpMungingTest, DenyListAcceptsUnmunged) {
+ auto pc = CreatePeerConnection("WebRTC-NoSdpMangleAllowForTesting/Enabled/");
+ pc->AddAudioTrack("audio_track", {});
+
+ auto offer = pc->CreateOffer();
+ RTCError error;
+ EXPECT_TRUE(pc->SetLocalDescription(std::move(offer), &error));
+}
+
+TEST_F(SdpMungingTest, DenyListThrows) {
+ // This test needs to use a feature that is not throwing by default.
+ // kAudioCodecsFmtpOpusStereo=68 is going to stay with us for quite a while.
+ auto pc = CreatePeerConnection("WebRTC-NoSdpMangleAllowForTesting/Enabled/");
+ pc->AddAudioTrack("audio_track", {});
+
+ auto offer = pc->CreateOffer();
+ auto& contents = offer->description()->contents();
+ ASSERT_EQ(contents.size(), 1u);
+ auto* media_description = contents[0].media_description();
+ ASSERT_TRUE(media_description);
+ std::vector<Codec> codecs = media_description->codecs();
+ for (auto& codec : codecs) {
+ if (codec.name == kOpusCodecName) {
+ codec.SetParam(kCodecParamStereo, kParamValueTrue);
+ }
+ }
+ media_description->set_codecs(codecs);
+ RTCError error;
+ EXPECT_FALSE(pc->SetLocalDescription(std::move(offer), &error));
+ EXPECT_THAT(
+ metrics::Samples("WebRTC.PeerConnection.SdpMunging.Offer.Initial"),
+ ElementsAre(Pair(SdpMungingType::kAudioCodecsFmtpOpusStereo, 1)));
+}
+
+TEST_F(SdpMungingTest, DenyListExceptionDoesNotThrow) {
+ // This test needs to use a feature that is not throwing by default.
+ // kAudioCodecsFmtpOpusStereo=68 is going to stay with us for quite a while.
+ auto pc =
+ CreatePeerConnection("WebRTC-NoSdpMangleAllowForTesting/Enabled,68/");
+ pc->AddAudioTrack("audio_track", {});
+
+ auto offer = pc->CreateOffer();
+ auto& contents = offer->description()->contents();
+ ASSERT_EQ(contents.size(), 1u);
+ auto* media_description = contents[0].media_description();
+ ASSERT_TRUE(media_description);
+ std::vector<Codec> codecs = media_description->codecs();
+ for (auto& codec : codecs) {
+ if (codec.name == kOpusCodecName) {
+ codec.SetParam(kCodecParamStereo, kParamValueTrue);
+ }
+ }
+ media_description->set_codecs(codecs);
+ RTCError error;
+ EXPECT_TRUE(pc->SetLocalDescription(std::move(offer), &error));
+ EXPECT_THAT(
+ metrics::Samples("WebRTC.PeerConnection.SdpMunging.Offer.Initial"),
+ ElementsAre(Pair(SdpMungingType::kAudioCodecsFmtpOpusStereo, 1)));
+}
+
TEST_F(SdpMungingTest, InitialSetLocalDescriptionWithoutCreateOffer) {
RTCConfiguration config;
config.certificates.push_back(
diff --git a/third_party/libwebrtc/pc/sdp_offer_answer.cc b/third_party/libwebrtc/pc/sdp_offer_answer.cc
@@ -2483,6 +2483,8 @@ void SdpOfferAnswerHandler::DoSetLocalDescription(
!pc_->trials().IsDisabled(
"WebRTC-NoSdpMangleNumberOfContents")) {
reject_error = true;
+ } else {
+ reject_error = !IsSdpMungingAllowed(sdp_munging_type, pc_->trials());
}
SdpMungingOutcome outcome = reject_error ? SdpMungingOutcome::kRejected
: SdpMungingOutcome::kAccepted;