tor-browser

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

commit f3a967c6177f79346082dd5a97dac16af7f36f44
parent fae0f39dcc4a61317b7aa6ad025c9f504d4b5258
Author: Dan Baker <dbaker@mozilla.com>
Date:   Mon, 27 Oct 2025 13:31:42 -0600

Bug 1995393 - Vendor libwebrtc from 4bafeff6ae

Upstream commit: https://webrtc.googlesource.com/src/+/4bafeff6ae5b8658c2b0e5899e0c3289e800e2e9
    Make outbound-rtp lifetime spec-compliant (behind flag).

    The spec says to delay the creation of the outbound-rtp until the SDP
    answer is set. This is equivalent to checking if the currentDirection is
    set, since that is one of the side-effects of negotiating an m-section.

    Plan B is opted out of this logic because currentDirection is not
    applicable to Plan B. Some drive-by comments are added to the
    inbound-rtp code paths for symmetry and clarity.

    Bug: chromium:406585888
    Change-Id: Ib2c7eb99316cd1f82269a756029d19d4c71b0e46
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/406261
    Reviewed-by: Harald Alvestrand <hta@webrtc.org>
    Commit-Queue: Henrik Boström <hbos@webrtc.org>
    Cr-Commit-Position: refs/heads/main@{#45446}

Diffstat:
Mthird_party/libwebrtc/README.mozilla.last-vendor | 4++--
Mthird_party/libwebrtc/pc/rtc_stats_collector.cc | 27+++++++++++++++++++++------
Mthird_party/libwebrtc/pc/rtc_stats_collector.h | 1+
Mthird_party/libwebrtc/pc/rtc_stats_integrationtest.cc | 50++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 74 insertions(+), 8 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 /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc -libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-27T19:29:02.897056+00:00. +libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-27T19:31:26.560039+00:00. # base of lastest vendoring -5b6cc53a2e +4bafeff6ae diff --git a/third_party/libwebrtc/pc/rtc_stats_collector.cc b/third_party/libwebrtc/pc/rtc_stats_collector.cc @@ -1174,6 +1174,7 @@ RTCStatsCollector::RTCStatsCollector(PeerConnectionInternal* pc, const Environment& env, int64_t cache_lifetime_us) : pc_(pc), + is_unified_plan_(pc->IsUnifiedPlan()), env_(env), stats_timestamp_with_environment_clock_( pc->GetConfiguration().stats_timestamp_with_environment_clock()), @@ -1750,9 +1751,11 @@ void RTCStatsCollector::ProduceAudioRTPStreamStats_n( for (const VoiceReceiverInfo& voice_receiver_info : stats.track_media_info_map.voice_media_info()->receivers) { if (!voice_receiver_info.connected()) { - continue; + continue; // The SSRC is not known yet. } if (spec_lifetime && voice_receiver_info.packets_received == 0) { + // The SSRC is known despite not receiving any packets. This happens if + // SSRC is signalled in the SDP which we should not rely on for getStats. continue; } // Inbound. @@ -1799,8 +1802,13 @@ void RTCStatsCollector::ProduceAudioRTPStreamStats_n( std::map<std::string, RTCOutboundRtpStreamStats*> audio_outbound_rtps; for (const VoiceSenderInfo& voice_sender_info : stats.track_media_info_map.voice_media_info()->senders) { - if (!voice_sender_info.connected()) - continue; + if (!voice_sender_info.connected()) { + continue; // The SSRC is not known yet. + } + if (spec_lifetime && is_unified_plan_ && + !stats.current_direction.has_value()) { + continue; // The SSRC is known but the O/A has not completed. + } auto outbound_audio = CreateOutboundRTPStreamStatsFromVoiceSenderInfo( transport_id, mid, *stats.track_media_info_map.voice_media_info(), voice_sender_info, timestamp, report); @@ -1858,9 +1866,11 @@ void RTCStatsCollector::ProduceVideoRTPStreamStats_n( for (const VideoReceiverInfo& video_receiver_info : stats.track_media_info_map.video_media_info()->receivers) { if (!video_receiver_info.connected()) { - continue; + continue; // The SSRC is not known yet. } if (spec_lifetime && video_receiver_info.packets_received == 0) { + // The SSRC is known despite not receiving any packets. This happens if + // SSRC is signalled in the SDP which we should not rely on for getStats. continue; } auto inbound_video = CreateInboundRTPStreamStatsFromVideoReceiverInfo( @@ -1899,8 +1909,13 @@ void RTCStatsCollector::ProduceVideoRTPStreamStats_n( std::map<std::string, RTCOutboundRtpStreamStats*> video_outbound_rtps; for (const VideoSenderInfo& video_sender_info : stats.track_media_info_map.video_media_info()->senders) { - if (!video_sender_info.connected()) - continue; + if (!video_sender_info.connected()) { + continue; // The SSRC is not known yet. + } + if (spec_lifetime && is_unified_plan_ && + !stats.current_direction.has_value()) { + continue; // The SSRC is known but the O/A has not completed. + } auto outbound_video = CreateOutboundRTPStreamStatsFromVideoSenderInfo( transport_id, mid, *stats.track_media_info_map.video_media_info(), video_sender_info, timestamp, report); diff --git a/third_party/libwebrtc/pc/rtc_stats_collector.h b/third_party/libwebrtc/pc/rtc_stats_collector.h @@ -250,6 +250,7 @@ class RTCStatsCollector : public RefCountInterface { scoped_refptr<RtpReceiverInternal> receiver_selector); PeerConnectionInternal* const pc_; + const bool is_unified_plan_; const Environment env_; const bool stats_timestamp_with_environment_clock_; Thread* const signaling_thread_; diff --git a/third_party/libwebrtc/pc/rtc_stats_integrationtest.cc b/third_party/libwebrtc/pc/rtc_stats_integrationtest.cc @@ -1250,6 +1250,56 @@ class RTCStatsRtpLifetimeTest : public RTCStatsIntegrationTest { } }; +TEST_F(RTCStatsRtpLifetimeTest, AudioOutboundRtpMissingBeforeStable) { + // Caller to send audio. + scoped_refptr<MediaStreamInterface> stream = caller_->GetUserMedia( + /*audio=*/true, {}, /*video=*/false); + scoped_refptr<AudioTrackInterface> track = stream->GetAudioTracks()[0]; + caller_->pc()->AddTransceiver(track, {}); + + // Setting the offer is not enough to make the outbound-rtp appear. + auto offer = caller_->AwaitCreateOffer(); + caller_->AwaitSetLocalDescription(offer.get()); + scoped_refptr<const RTCStatsReport> report = GetStats(caller_->pc()); + std::vector<const RTCOutboundRtpStreamStats*> outbound_rtps = + report->GetStatsOfType<RTCOutboundRtpStreamStats>(); + EXPECT_THAT(outbound_rtps, SizeIs(0)); + + // Once the O/A completes, the outbound-rtp immediately appears (the stats + // cache is cleared). + callee_->AwaitSetRemoteDescription(offer.get()); + auto answer = callee_->AwaitCreateAnswer(); + caller_->AwaitSetRemoteDescription(answer.get()); + report = GetStats(caller_->pc()); + outbound_rtps = report->GetStatsOfType<RTCOutboundRtpStreamStats>(); + EXPECT_THAT(outbound_rtps, SizeIs(1)); +} + +TEST_F(RTCStatsRtpLifetimeTest, VideoOutboundRtpMissingBeforeStable) { + // Caller to send video. + scoped_refptr<MediaStreamInterface> stream = caller_->GetUserMedia( + /*audio=*/false, {}, /*video=*/true); + scoped_refptr<VideoTrackInterface> track = stream->GetVideoTracks()[0]; + caller_->pc()->AddTransceiver(track, {}); + + // Setting the offer is not enough to make the outbound-rtp appear. + auto offer = caller_->AwaitCreateOffer(); + caller_->AwaitSetLocalDescription(offer.get()); + scoped_refptr<const RTCStatsReport> report = GetStats(caller_->pc()); + std::vector<const RTCOutboundRtpStreamStats*> outbound_rtps = + report->GetStatsOfType<RTCOutboundRtpStreamStats>(); + EXPECT_THAT(outbound_rtps, SizeIs(0)); + + // Once the O/A completes, the outbound-rtp immediately appears (the stats + // cache is cleared). + callee_->AwaitSetRemoteDescription(offer.get()); + auto answer = callee_->AwaitCreateAnswer(); + caller_->AwaitSetRemoteDescription(answer.get()); + report = GetStats(caller_->pc()); + outbound_rtps = report->GetStatsOfType<RTCOutboundRtpStreamStats>(); + EXPECT_THAT(outbound_rtps, SizeIs(1)); +} + TEST_F(RTCStatsRtpLifetimeTest, AudioInboundRtpMissingBeforeFirstPacket) { // Caller to send audio. scoped_refptr<MediaStreamInterface> stream = caller_->GetUserMedia(