tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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:
Mthird_party/libwebrtc/README.mozilla.last-vendor | 4++--
Mthird_party/libwebrtc/experiments/field_trials.py | 6++++++
Mthird_party/libwebrtc/moz-patch-stack/s0103.patch | 2+-
Mthird_party/libwebrtc/pc/BUILD.gn | 4++++
Mthird_party/libwebrtc/pc/sdp_munging_detector.cc | 33+++++++++++++++++++++++++++++++++
Mthird_party/libwebrtc/pc/sdp_munging_detector.h | 6++++++
Mthird_party/libwebrtc/pc/sdp_munging_detector_unittest.cc | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mthird_party/libwebrtc/pc/sdp_offer_answer.cc | 2++
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;