tor-browser

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

commit 59cfd304555dad8bc0a1775250ce49f9baa8f1d4
parent 95352050d5d6b9edcd6a72fee87b1222503a4c6b
Author: Dan Baker <dbaker@mozilla.com>
Date:   Thu, 23 Oct 2025 15:08:34 -0600

Bug 1995393 - Vendor libwebrtc from 04ad566fb6

Upstream commit: https://webrtc.googlesource.com/src/+/04ad566fb627ac8ae9cce00f52a124563f774058
    LNA: Introduce LnaPermissionInterface::ShouldRequestPermission()

    Before this CL there was only one method RequestPermission which
    performed some synchronous checks e.g. if the address space was less
    public, and if necessary asynchronously requested the LNA permission.

    This CL introduces ShouldRequestPermission that only performs the
    synchronous part of the check. This allows us to centralize the logic
    for permission checking into the embedder and more importantly, allows
    us to avoid having to post a task for cases where it's not necessary to
    request a permission.

    Blink change: https://crrev.com/c/6794524

    Bug: chromium:421223919
    Change-Id: I8edb06f7b604eaae76e5230d404dd19c02d0e24b
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/402460
    Commit-Queue: Giovanni Ortuno Urquidi <ortuno@chromium.org>
    Reviewed-by: Harald Alvestrand <hta@webrtc.org>
    Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
    Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
    Cr-Commit-Position: refs/heads/main@{#45335}

Diffstat:
Mthird_party/libwebrtc/README.mozilla.last-vendor | 4++--
Mthird_party/libwebrtc/api/local_network_access_permission.h | 9+++++++++
Mthird_party/libwebrtc/api/test/mock_local_network_access_permission.cc | 34+++++++++++++++++++---------------
Mthird_party/libwebrtc/api/test/mock_local_network_access_permission.h | 19+++++++++++++++++--
Mthird_party/libwebrtc/moz-patch-stack/p0001.patch | 2+-
Mthird_party/libwebrtc/p2p/BUILD.gn | 2++
Mthird_party/libwebrtc/p2p/DEPS | 1+
Athird_party/libwebrtc/p2p/base/local_network_access_port_unittest.cc | 304+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mthird_party/libwebrtc/p2p/base/p2p_transport_channel.cc | 9++++-----
Mthird_party/libwebrtc/p2p/base/p2p_transport_channel_unittest.cc | 88+++++++++++++++++++++++++++----------------------------------------------------
Mthird_party/libwebrtc/p2p/base/port.cc | 6+++---
Mthird_party/libwebrtc/p2p/base/stun_port_unittest.cc | 171++-----------------------------------------------------------------------------
Mthird_party/libwebrtc/p2p/base/turn_port_unittest.cc | 160++-----------------------------------------------------------------------------
13 files changed, 399 insertions(+), 410 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-23T21:06:00.872672+00:00. +libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-23T21:08:22.854567+00:00. # base of lastest vendoring -dec6b34b86 +04ad566fb6 diff --git a/third_party/libwebrtc/api/local_network_access_permission.h b/third_party/libwebrtc/api/local_network_access_permission.h @@ -62,6 +62,15 @@ class LocalNetworkAccessPermissionInterface { public: virtual ~LocalNetworkAccessPermissionInterface() = default; + // Returns whether or not the caller should request permission. Depending + // on the originator's address space, sometimes it's not necessary to request + // permission. + // TODO(crbug.com/421223919): Make this method pure virtual once all + // implementations implement it. + virtual bool ShouldRequestPermission(const SocketAddress& addr) { + return addr.IsPrivateIP() || addr.IsLoopbackIP(); + } + // The callback will be called when the permission is granted or denied. The // callback will be called on the sequence that the caller runs on. virtual void RequestPermission( diff --git a/third_party/libwebrtc/api/test/mock_local_network_access_permission.cc b/third_party/libwebrtc/api/test/mock_local_network_access_permission.cc @@ -25,24 +25,28 @@ using ::testing::_; namespace webrtc { FakeLocalNetworkAccessPermissionFactory:: - FakeLocalNetworkAccessPermissionFactory( - LocalNetworkAccessPermissionStatus status) { - EXPECT_CALL(*this, Create()).WillRepeatedly([status]() { + FakeLocalNetworkAccessPermissionFactory(Result result) { + EXPECT_CALL(*this, Create()).WillRepeatedly([result]() { auto mock_lna_permission = std::make_unique<MockLocalNetworkAccessPermission>(); - - EXPECT_CALL(*mock_lna_permission, RequestPermission(_, _)) + EXPECT_CALL(*mock_lna_permission, ShouldRequestPermission(_)) .WillRepeatedly( - [status]( - const SocketAddress& /* addr */, - absl::AnyInvocable<void( - webrtc::LocalNetworkAccessPermissionStatus)> callback) { - Thread::Current()->PostTask( - [callback = std::move(callback), status]() mutable { - callback(status); - }); - }); - + ::testing::Return(result != Result::kPermissionNotNeeded)); + if (result != Result::kPermissionNotNeeded) { + EXPECT_CALL(*mock_lna_permission, RequestPermission(_, _)) + .WillRepeatedly( + [result]( + const SocketAddress& /* addr */, + absl::AnyInvocable<void( + webrtc::LocalNetworkAccessPermissionStatus)> callback) { + Thread::Current()->PostTask([callback = std::move(callback), + result]() mutable { + callback(result == Result::kPermissionGranted + ? LocalNetworkAccessPermissionStatus::kGranted + : LocalNetworkAccessPermissionStatus::kDenied); + }); + }); + } return mock_lna_permission; }); } diff --git a/third_party/libwebrtc/api/test/mock_local_network_access_permission.h b/third_party/libwebrtc/api/test/mock_local_network_access_permission.h @@ -23,6 +23,11 @@ namespace webrtc { class MockLocalNetworkAccessPermission : public LocalNetworkAccessPermissionInterface { public: + MOCK_METHOD(bool, + ShouldRequestPermission, + (const SocketAddress& addr), + (override)); + MOCK_METHOD( void, RequestPermission, @@ -45,8 +50,18 @@ class MockLocalNetworkAccessPermissionFactory class FakeLocalNetworkAccessPermissionFactory : public MockLocalNetworkAccessPermissionFactory { public: - explicit FakeLocalNetworkAccessPermissionFactory( - LocalNetworkAccessPermissionStatus status); + enum class Result { + // Use when the permission is not needed i.e. ShouldRequestPermission will + // return false. + kPermissionNotNeeded, + // Use when the permission is needed i.e. ShouldRequestPermission will + // return true, and RequestPermission will return kGranted/kDenied + // respectively. + kPermissionGranted, + kPermissionDenied, + }; + + explicit FakeLocalNetworkAccessPermissionFactory(Result result); ~FakeLocalNetworkAccessPermissionFactory() override; }; diff --git a/third_party/libwebrtc/moz-patch-stack/p0001.patch b/third_party/libwebrtc/moz-patch-stack/p0001.patch @@ -142,7 +142,7 @@ index 80402d3ea3..fe3d10dcf3 100644 } if (!keep_capturing) { diff --git a/p2p/base/port.cc b/p2p/base/port.cc -index cce75157e2..d91143db2f 100644 +index 033e3f6dd2..5a43cc7c70 100644 --- a/p2p/base/port.cc +++ b/p2p/base/port.cc @@ -53,6 +53,7 @@ diff --git a/third_party/libwebrtc/p2p/BUILD.gn b/third_party/libwebrtc/p2p/BUILD.gn @@ -1148,6 +1148,7 @@ if (rtc_include_tests) { sources = [ "base/async_stun_tcp_socket_unittest.cc", "base/ice_credentials_iterator_unittest.cc", + "base/local_network_access_port_unittest.cc", "base/p2p_transport_channel_unittest.cc", "base/packet_transport_internal_unittest.cc", "base/port_allocator_unittest.cc", @@ -1281,6 +1282,7 @@ if (rtc_include_tests) { "//third_party/abseil-cpp/absl/functional:any_invocable", "//third_party/abseil-cpp/absl/memory", "//third_party/abseil-cpp/absl/strings", + "//third_party/abseil-cpp/absl/strings:str_format", "//third_party/abseil-cpp/absl/strings:string_view", ] } diff --git a/third_party/libwebrtc/p2p/DEPS b/third_party/libwebrtc/p2p/DEPS @@ -3,4 +3,5 @@ include_rules = [ "+net", "+system_wrappers", "+absl/functional/any_invocable.h", + "+absl/strings", ] diff --git a/third_party/libwebrtc/p2p/base/local_network_access_port_unittest.cc b/third_party/libwebrtc/p2p/base/local_network_access_port_unittest.cc @@ -0,0 +1,304 @@ +/* + * Copyright 2025 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <memory> +#include <optional> +#include <string> +#include <tuple> +#include <utility> + +#include "absl/functional/any_invocable.h" +#include "absl/strings/str_format.h" +#include "absl/strings/str_replace.h" +#include "absl/strings/string_view.h" +#include "api/environment/environment.h" +#include "api/environment/environment_factory.h" +#include "api/local_network_access_permission.h" +#include "api/test/mock_async_dns_resolver.h" +#include "api/test/mock_local_network_access_permission.h" +#include "api/test/rtc_error_matchers.h" +#include "p2p/base/port.h" +#include "p2p/base/port_allocator.h" +#include "p2p/base/port_interface.h" +#include "p2p/base/stun_port.h" +#include "p2p/base/turn_port.h" +#include "p2p/client/relay_port_factory_interface.h" +#include "p2p/test/mock_dns_resolving_packet_socket_factory.h" +#include "p2p/test/test_stun_server.h" +#include "p2p/test/test_turn_server.h" +#include "p2p/test/turn_server.h" +#include "rtc_base/fake_clock.h" +#include "rtc_base/net_helpers.h" +#include "rtc_base/network.h" +#include "rtc_base/socket.h" +#include "rtc_base/socket_address.h" +#include "rtc_base/third_party/sigslot/sigslot.h" +#include "rtc_base/thread.h" +#include "rtc_base/virtual_socket_server.h" +#include "test/gmock.h" +#include "test/gtest.h" +#include "test/wait_until.h" + +namespace webrtc { +namespace { + +using LnaFakeResult = FakeLocalNetworkAccessPermissionFactory::Result; +using ::testing::_; +using ::testing::DoAll; +using ::testing::IsTrue; +using ::testing::Return; +using ::testing::ReturnPointee; +using ::testing::SetArgPointee; + +const SocketAddress kTurnUdpIntAddr("99.99.99.3", webrtc::TURN_SERVER_PORT); +const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0); +const SocketAddress kLocalAddr("11.11.11.11", 0); +const SocketAddress kLocalIPv6Addr("2401:fa00:4:1000:be30:5bff:fee5:c3", 0); + +constexpr char kIceUfrag[] = "TESTICEUFRAG0001"; +constexpr char kIcePwd[] = "TESTICEPWD00000000000001"; +constexpr char kTurnUsername[] = "test"; +constexpr char kTurnPassword[] = "test"; + +enum ServerType { kStun, kTurn }; + +// Class to test LocalNetworkAccess integration with STUN and TURN ports. +class LocalNetworkAccessPortTest + : public ::testing::Test, + public sigslot::has_slots<>, + public ::testing::WithParamInterface< + std::tuple<ServerType, absl::string_view, LnaFakeResult>> { + public: + LocalNetworkAccessPortTest() { + network_.AddIP(local_address_.ipaddr()); + + switch (server_type()) { + case kStun: + stun_server_ = + TestStunServer::Create(&ss_, {server_address(), 5000}, thread_); + break; + case kTurn: + turn_server_.AddInternalSocket({server_address(), 5000}, PROTO_UDP); + break; + } + } + + ~LocalNetworkAccessPortTest() override = default; + + void OnPortComplete(Port* port) { port_ready_ = true; } + void OnPortError(Port* port) { port_error_ = true; } + + protected: + static ServerType server_type() { return std::get<0>(GetParam()); } + static absl::string_view server_address() { return std::get<1>(GetParam()); } + static LnaFakeResult lna_fake_result() { return std::get<2>(GetParam()); } + + // Creates STUN or TURN port depending on the type of port we are testing. + std::unique_ptr<Port> CreatePort( + absl::string_view server_address, + LocalNetworkAccessPermissionFactoryInterface& lna_permission_factory) { + switch (server_type()) { + case kStun: + return CreateStunPort(server_address, lna_permission_factory); + case kTurn: + return CreateTurnPort(server_address, lna_permission_factory); + } + } + + std::unique_ptr<TurnPort> CreateTurnPort( + absl::string_view server_address, + LocalNetworkAccessPermissionFactoryInterface& lna_permission_factory) { + RelayServerConfig config; + config.credentials = RelayCredentials(kTurnUsername, kTurnPassword); + + ProtocolAddress proto_server_address({server_address, 5000}, PROTO_UDP); + CreateRelayPortArgs args = { + .env = env_, + .network_thread = &thread_, + .socket_factory = &socket_factory_, + .network = &network_, + .server_address = &proto_server_address, + .config = &config, + .username = kIceUfrag, + .password = kIcePwd, + .lna_permission_factory = &lna_permission_factory, + }; + + auto turn_port = TurnPort::Create(args, /*min_port=*/0, /*max_port=*/0); + turn_port->SignalPortComplete.connect( + this, &LocalNetworkAccessPortTest::OnPortComplete); + turn_port->SignalPortError.connect( + this, &LocalNetworkAccessPortTest::OnPortError); + + return turn_port; + } + + std::unique_ptr<StunPort> CreateStunPort( + absl::string_view server_address, + LocalNetworkAccessPermissionFactoryInterface& lna_permission_factory) { + Port::PortParametersRef params = { + .env = env_, + .network_thread = &thread_, + .socket_factory = &socket_factory_, + .network = &network_, + .ice_username_fragment = kIceUfrag, + .ice_password = kIcePwd, + .lna_permission_factory = &lna_permission_factory, + }; + + auto stun_port = StunPort::Create( + params, 0, 0, {SocketAddress(server_address, 5000)}, std::nullopt); + stun_port->SignalPortComplete.connect( + this, &LocalNetworkAccessPortTest::OnPortComplete); + stun_port->SignalPortError.connect( + this, &LocalNetworkAccessPortTest::OnPortError); + + return stun_port; + } + + void setup_dns_resolver_mock() { + auto expectations = + [&](webrtc::MockAsyncDnsResolver* resolver, + webrtc::MockAsyncDnsResolverResult* resolver_result) { + EXPECT_CALL(*resolver, Start(_, _, _)) + .WillOnce( + [](const webrtc::SocketAddress& /* addr */, int /* family */, + absl::AnyInvocable<void()> callback) { callback(); }); + + EXPECT_CALL(*resolver, result) + .WillRepeatedly(ReturnPointee(resolver_result)); + EXPECT_CALL(*resolver_result, GetError).WillRepeatedly(Return(0)); + EXPECT_CALL(*resolver_result, GetResolvedAddress(_, _)) + .WillOnce( + DoAll(SetArgPointee<1>(SocketAddress(server_address(), 5000)), + Return(true))); + }; + + socket_factory_.SetExpectations(std::move(expectations)); + } + + bool port_ready_ = false; + bool port_error_ = false; + + ScopedFakeClock fake_clock_; + const Environment env_ = CreateEnvironment(); + VirtualSocketServer ss_; + AutoSocketServerThread thread_{&ss_}; + MockDnsResolvingPacketSocketFactory socket_factory_{&ss_}; + + const bool is_using_ipv6_{SocketAddress(server_address(), 5000).family() == + AF_INET6}; + const SocketAddress local_address_{is_using_ipv6_ ? kLocalIPv6Addr + : kLocalAddr}; + Network network_{"unittest", "unittest", local_address_.ipaddr(), 32}; + + TestTurnServer turn_server_{&thread_, &ss_, kTurnUdpIntAddr, kTurnUdpExtAddr}; + TestStunServer::StunServerPtr stun_server_; +}; + +std::string GetTestName( + const testing::TestParamInfo<LocalNetworkAccessPortTest::ParamType>& info) { + std::string protocol_str; + switch (std::get<0>(info.param)) { + case kStun: + protocol_str = "Stun"; + break; + case kTurn: + protocol_str = "Turn"; + break; + } + + // Remove ":" + std::string sanitized_address = absl::StrReplaceAll( + std::get<1>(info.param), {{"::", "_"}, {":", "_"}, {".", "_"}}); + + std::string result_str; + switch (std::get<2>(info.param)) { + case LnaFakeResult::kPermissionNotNeeded: + result_str = "PermissionNotNeeded"; + break; + case LnaFakeResult::kPermissionGranted: + result_str = "PermissionGranted"; + break; + case LnaFakeResult::kPermissionDenied: + result_str = "PermissionDenied"; + break; + } + + return absl::StrFormat("%s_%s_%s", protocol_str, sanitized_address, + result_str); +} + +constexpr absl::string_view kTestAddresses[] = { + "127.0.0.1", + "10.0.0.3", + "1.1.1.1", + "::1", + "fd00:4860:4860::8844", + "2001:4860:4860::8888", +}; + +INSTANTIATE_TEST_SUITE_P( + All, + LocalNetworkAccessPortTest, + ::testing::Combine(::testing::Values(kStun, kTurn), + ::testing::ValuesIn(kTestAddresses), + ::testing::Values(LnaFakeResult::kPermissionNotNeeded, + LnaFakeResult::kPermissionGranted, + LnaFakeResult::kPermissionDenied)), + &GetTestName); + +TEST_P(LocalNetworkAccessPortTest, ResolvedAddress) { + FakeLocalNetworkAccessPermissionFactory factory(lna_fake_result()); + + auto port = CreatePort(server_address(), factory); + port->PrepareAddress(); + + if (lna_fake_result() == LnaFakeResult::kPermissionNotNeeded || + lna_fake_result() == LnaFakeResult::kPermissionGranted) { + EXPECT_THAT(WaitUntil([&] { return port_ready_; }, IsTrue(), + {.clock = &fake_clock_}), + IsRtcOk()); + EXPECT_EQ(1u, port->Candidates().size()); + EXPECT_NE(SOCKET_ERROR, port->GetError()); + } else { + EXPECT_THAT(WaitUntil([&] { return port_error_; }, IsTrue(), + {.clock = &fake_clock_}), + IsRtcOk()); + EXPECT_EQ(0u, port->Candidates().size()); + EXPECT_NE(SOCKET_ERROR, port->GetError()); + } +} + +TEST_P(LocalNetworkAccessPortTest, UnresolvedAddress) { + setup_dns_resolver_mock(); + FakeLocalNetworkAccessPermissionFactory factory(lna_fake_result()); + + auto port = CreatePort("fakehost.test", factory); + port->PrepareAddress(); + + if (lna_fake_result() == LnaFakeResult::kPermissionNotNeeded || + lna_fake_result() == LnaFakeResult::kPermissionGranted) { + EXPECT_THAT(WaitUntil([&] { return port_ready_; }, IsTrue(), + {.clock = &fake_clock_}), + IsRtcOk()); + EXPECT_EQ(1u, port->Candidates().size()); + EXPECT_NE(SOCKET_ERROR, port->GetError()); + } else { + EXPECT_THAT(WaitUntil([&] { return port_error_; }, IsTrue(), + {.clock = &fake_clock_}), + IsRtcOk()); + EXPECT_EQ(0u, port->Candidates().size()); + EXPECT_NE(SOCKET_ERROR, port->GetError()); + } +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/p2p/base/p2p_transport_channel.cc b/third_party/libwebrtc/p2p/base/p2p_transport_channel.cc @@ -1315,17 +1315,16 @@ void P2PTransportChannel::CheckLocalNetworkAccessPermission( return; } - if (!candidate.address().IsPrivateIP() && - !candidate.address().IsLoopbackIP()) { - RTC_LOG(LS_VERBOSE) << "Skipping LNA permission check for public IP " + std::unique_ptr<LocalNetworkAccessPermissionInterface> permission_query = + lna_permission_factory_->Create(); + if (!permission_query->ShouldRequestPermission(candidate.address())) { + RTC_LOG(LS_VERBOSE) << "No need to request permission for candidate: " << candidate.address().ipaddr().ToSensitiveString() << "."; FinishAddingRemoteCandidate(candidate); return; } - std::unique_ptr<LocalNetworkAccessPermissionInterface> permission_query = - lna_permission_factory_->Create(); auto permission_query_ptr = permission_query.get(); permission_queries_.emplace_back(candidate, std::move(permission_query)); diff --git a/third_party/libwebrtc/p2p/base/p2p_transport_channel_unittest.cc b/third_party/libwebrtc/p2p/base/p2p_transport_channel_unittest.cc @@ -18,6 +18,7 @@ #include <memory> #include <optional> #include <string> +#include <tuple> #include <utility> #include <vector> @@ -30,7 +31,6 @@ #include "api/environment/environment.h" #include "api/environment/environment_factory.h" #include "api/ice_transport_interface.h" -#include "api/local_network_access_permission.h" #include "api/packet_socket_factory.h" #include "api/scoped_refptr.h" #include "api/task_queue/pending_task_safety_flag.h" @@ -119,6 +119,7 @@ using ::testing::SetArgPointee; using ::testing::SizeIs; using ::testing::Values; using ::testing::WithParamInterface; +using LnaFakeResult = FakeLocalNetworkAccessPermissionFactory::Result; // Default timeout for tests in this file. // Should be large enough for slow buildbots to run the tests reliably. @@ -6798,63 +6799,27 @@ TEST_F(P2PTransportChannelTest, EnableDnsLookupsWithTransportPolicyNoHost) { DestroyChannels(); } -struct LocalAreaNetworkPermissionTestConfig { - template <typename Sink> - friend void AbslStringify( - Sink& sink, - const LocalAreaNetworkPermissionTestConfig& config) { - sink.Append(config.address); - sink.Append("_"); - switch (config.lna_permission_status) { - case LocalNetworkAccessPermissionStatus::kDenied: - sink.Append("Denied"); - break; - case LocalNetworkAccessPermissionStatus::kGranted: - sink.Append("Granted"); - break; - } - } - - LocalNetworkAccessPermissionStatus lna_permission_status; - absl::string_view address; - bool candidate_added; -} kAllLocalAreNetworkPermissionTestConfigs[] = { - {LocalNetworkAccessPermissionStatus::kDenied, "127.0.0.1", - /*candidate_added=*/false}, - {LocalNetworkAccessPermissionStatus::kDenied, "10.0.0.3", - /*candidate_added=*/false}, - {LocalNetworkAccessPermissionStatus::kDenied, "1.1.1.1", - /*candidate_added=*/true}, - {LocalNetworkAccessPermissionStatus::kDenied, "::1", - /*candidate_added=*/false}, - {LocalNetworkAccessPermissionStatus::kDenied, "fd00:4860:4860::8844", - /*candidate_added=*/false}, - {LocalNetworkAccessPermissionStatus::kDenied, "2001:4860:4860::8888", - /*candidate_added=*/true}, - {LocalNetworkAccessPermissionStatus::kGranted, "127.0.0.1", - /*candidate_added=*/true}, - {LocalNetworkAccessPermissionStatus::kGranted, "10.0.0.3", - /*candidate_added=*/true}, - {LocalNetworkAccessPermissionStatus::kGranted, "1.1.1.1", - /*candidate_added=*/true}, - {LocalNetworkAccessPermissionStatus::kGranted, "::1", - /*candidate_added=*/true}, - {LocalNetworkAccessPermissionStatus::kGranted, "fd00:4860:4860::8844", - /*candidate_added=*/true}, - {LocalNetworkAccessPermissionStatus::kGranted, "2001:4860:4860::8888", - /*candidate_added=*/true}, +constexpr absl::string_view kTestAddresses[] = { + "127.0.0.1", + "10.0.0.3", + "1.1.1.1", + "::1", + "fd00:4860:4860::8844", + "2001:4860:4860::8888", }; -class LocalAreaNetworkPermissionTest +class LocalNetworkAccessPermissionTest : public P2PTransportChannelPingTest, public ::testing::WithParamInterface< - LocalAreaNetworkPermissionTestConfig> {}; + std::tuple<absl::string_view, LnaFakeResult>> {}; + +TEST_P(LocalNetworkAccessPermissionTest, LiteralAddresses) { + const auto [address, lna_fake_result] = GetParam(); -TEST_P(LocalAreaNetworkPermissionTest, LiteralAddresses) { const Environment env = CreateEnvironment(); FakePortAllocator pa(env, ss()); FakeLocalNetworkAccessPermissionFactory lna_permission_factory( - GetParam().lna_permission_status); + lna_fake_result); IceTransportInit init; init.set_port_allocator(&pa); @@ -6866,27 +6831,30 @@ TEST_P(LocalAreaNetworkPermissionTest, LiteralAddresses) { ch->MaybeStartGathering(); ch->AddRemoteCandidate( - CreateUdpCandidate(IceCandidateType::kHost, GetParam().address, 5000, 1)); + CreateUdpCandidate(IceCandidateType::kHost, address, 5000, 1)); ASSERT_THAT( WaitUntil([&] { return ch->PermissionQueriesOutstandingForTesting(); }, Eq(0)), IsRtcOk()); - if (GetParam().candidate_added) { + if (lna_fake_result == LnaFakeResult::kPermissionNotNeeded || + lna_fake_result == LnaFakeResult::kPermissionGranted) { EXPECT_EQ(1u, ch->remote_candidates().size()); } else { EXPECT_EQ(0u, ch->remote_candidates().size()); } } -TEST_P(LocalAreaNetworkPermissionTest, UnresolvedAddresses) { +TEST_P(LocalNetworkAccessPermissionTest, UnresolvedAddresses) { + const auto [address, lna_fake_result] = GetParam(); + const Environment env = CreateEnvironment(); FakePortAllocator pa(env, ss()); FakeLocalNetworkAccessPermissionFactory lna_permission_factory( - GetParam().lna_permission_status); + lna_fake_result); ResolverFactoryFixture resolver_fixture; - resolver_fixture.SetAddressToReturn({GetParam().address, 5000}); + resolver_fixture.SetAddressToReturn({address, 5000}); IceTransportInit init; init.set_port_allocator(&pa); @@ -6905,7 +6873,8 @@ TEST_P(LocalAreaNetworkPermissionTest, UnresolvedAddresses) { WaitUntil([&] { return ch->PermissionQueriesOutstandingForTesting(); }, Eq(0)), IsRtcOk()); - if (GetParam().candidate_added) { + if (lna_fake_result == LnaFakeResult::kPermissionNotNeeded || + lna_fake_result == LnaFakeResult::kPermissionGranted) { EXPECT_EQ(1u, ch->remote_candidates().size()); } else { EXPECT_EQ(0u, ch->remote_candidates().size()); @@ -6914,8 +6883,11 @@ TEST_P(LocalAreaNetworkPermissionTest, UnresolvedAddresses) { INSTANTIATE_TEST_SUITE_P( All, - LocalAreaNetworkPermissionTest, - ::testing::ValuesIn(kAllLocalAreNetworkPermissionTestConfigs)); + LocalNetworkAccessPermissionTest, + ::testing::Combine(::testing::ValuesIn(kTestAddresses), + ::testing::Values(LnaFakeResult::kPermissionNotNeeded, + LnaFakeResult::kPermissionGranted, + LnaFakeResult::kPermissionDenied))); class GatherAfterConnectedTest : public P2PTransportChannelTest, public WithParamInterface<bool> {}; diff --git a/third_party/libwebrtc/p2p/base/port.cc b/third_party/libwebrtc/p2p/base/port.cc @@ -950,7 +950,9 @@ void Port::MaybeRequestLocalNetworkAccessPermission( return; } - if (!address.IsPrivateIP() && !address.IsLoopbackIP()) { + std::unique_ptr<LocalNetworkAccessPermissionInterface> permission_query = + lna_permission_factory_->Create(); + if (!permission_query->ShouldRequestPermission(address)) { std::move(callback)(LocalNetworkAccessPermissionStatus::kGranted); return; } @@ -958,8 +960,6 @@ void Port::MaybeRequestLocalNetworkAccessPermission( RTC_LOG(LS_VERBOSE) << "Asynchronously requesting LNA permission." << address.HostAsSensitiveURIString(); - std::unique_ptr<LocalNetworkAccessPermissionInterface> permission_query = - lna_permission_factory_->Create(); auto* permission_query_ptr = permission_query.get(); permission_queries_.push_back(std::move(permission_query)); diff --git a/third_party/libwebrtc/p2p/base/stun_port_unittest.cc b/third_party/libwebrtc/p2p/base/stun_port_unittest.cc @@ -16,7 +16,6 @@ #include <optional> #include <set> #include <string> -#include <utility> #include <vector> #include "absl/functional/any_invocable.h" @@ -25,10 +24,8 @@ #include "api/environment/environment_factory.h" #include "api/field_trials.h" #include "api/field_trials_view.h" -#include "api/local_network_access_permission.h" #include "api/packet_socket_factory.h" #include "api/test/mock_async_dns_resolver.h" -#include "api/test/mock_local_network_access_permission.h" #include "api/test/rtc_error_matchers.h" #include "api/transport/stun.h" #include "api/units/time_delta.h" @@ -195,26 +192,21 @@ class StunPortTestBase : public ::testing::Test, public sigslot::has_slots<> { } void CreateStunPort(const webrtc::SocketAddress& server_addr, - const webrtc::FieldTrialsView* field_trials = nullptr, - webrtc::LocalNetworkAccessPermissionFactoryInterface* - lna_permission_factory = nullptr) { + const webrtc::FieldTrialsView* field_trials = nullptr) { ServerAddresses stun_servers; stun_servers.insert(server_addr); - CreateStunPort(stun_servers, field_trials, lna_permission_factory); + CreateStunPort(stun_servers, field_trials); } void CreateStunPort(const ServerAddresses& stun_servers, - const webrtc::FieldTrialsView* field_trials = nullptr, - webrtc::LocalNetworkAccessPermissionFactoryInterface* - lna_permission_factory = nullptr) { + const webrtc::FieldTrialsView* field_trials = nullptr) { stun_port_ = webrtc::StunPort::Create( {.env = CreateEnvironment(field_trials), .network_thread = &thread_, .socket_factory = socket_factory(), .network = network_, .ice_username_fragment = webrtc::CreateRandomString(16), - .ice_password = webrtc::CreateRandomString(22), - .lna_permission_factory = lna_permission_factory}, + .ice_password = webrtc::CreateRandomString(22)}, 0, 0, stun_servers, std::nullopt); stun_port_->SetIceTiebreaker(kTiebreakerDefault); stun_port_->set_stun_keepalive_delay(stun_keepalive_delay_); @@ -776,161 +768,6 @@ INSTANTIATE_TEST_SUITE_P(All, StunPortIPAddressTypeMetricsTest, ::testing::ValuesIn(kAllIPAddressTypeTestConfigs)); -struct LocalAreaNetworkPermissionTestConfig { - template <typename Sink> - friend void AbslStringify( - Sink& sink, - const LocalAreaNetworkPermissionTestConfig& config) { - sink.Append(config.address); - sink.Append("_"); - switch (config.lna_permission_status) { - case webrtc::LocalNetworkAccessPermissionStatus::kDenied: - sink.Append("Denied"); - break; - case webrtc::LocalNetworkAccessPermissionStatus::kGranted: - sink.Append("Granted"); - break; - } - } - - webrtc::LocalNetworkAccessPermissionStatus lna_permission_status; - absl::string_view address; - bool should_succeed; -} kAllLocalAreNetworkPermissionTestConfigs[] = { - {webrtc::LocalNetworkAccessPermissionStatus::kDenied, "127.0.0.1", - /*should_succeed=*/false}, - {webrtc::LocalNetworkAccessPermissionStatus::kDenied, "10.0.0.3", - /*should_succeed=*/false}, - {webrtc::LocalNetworkAccessPermissionStatus::kDenied, "1.1.1.1", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kDenied, "::1", - /*should_succeed=*/false}, - {webrtc::LocalNetworkAccessPermissionStatus::kDenied, - "fd00:4860:4860::8844", - /*should_succeed=*/false}, - {webrtc::LocalNetworkAccessPermissionStatus::kDenied, - "2001:4860:4860::8888", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kGranted, "127.0.0.1", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kGranted, "10.0.0.3", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kGranted, "1.1.1.1", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kGranted, "::1", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kGranted, - "fd00:4860:4860::8844", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kGranted, - "2001:4860:4860::8888", - /*should_succeed=*/true}, -}; - -class StunPortLocalNetworkAccessPermissionTest - : public FakeClockBase, - public StunPortTestBase, - public ::testing::WithParamInterface< - LocalAreaNetworkPermissionTestConfig> { - public: - StunPortLocalNetworkAccessPermissionTest() - : StunPortTestBase( - /*address=*/using_ipv6_address() ? kPrivateIPv6.ipaddr() - : kPrivateIP.ipaddr(), - /*stun_server_addresses=*/{{GetParam().address, 5000}}, - /*nat_server_address=*/ - using_ipv6_address() ? kNatAddrIPv6 : kNatAddr), - socket_factory_(ss()) {} - - protected: - webrtc::PacketSocketFactory* socket_factory() override { - return &socket_factory_; - } - - void setup_dns_resolver_mock() { - auto expectations = - [](webrtc::MockAsyncDnsResolver* resolver, - webrtc::MockAsyncDnsResolverResult* resolver_result) { - EXPECT_CALL(*resolver, Start(_, _, _)) - .WillOnce( - [](const webrtc::SocketAddress& /* addr */, int /* family */, - absl::AnyInvocable<void()> callback) { callback(); }); - - EXPECT_CALL(*resolver, result) - .WillRepeatedly(ReturnPointee(resolver_result)); - EXPECT_CALL(*resolver_result, GetError).WillOnce(Return(0)); - EXPECT_CALL(*resolver_result, GetResolvedAddress(_, _)) - .WillOnce(DoAll( - SetArgPointee<1>(SocketAddress(GetParam().address, 5000)), - Return(true))); - }; - - socket_factory_.SetExpectations(std::move(expectations)); - } - - private: - bool using_ipv6_address() { - return SocketAddress(GetParam().address, 5000).family() == AF_INET6; - } - - webrtc::MockDnsResolvingPacketSocketFactory socket_factory_; -}; - -TEST_P(StunPortLocalNetworkAccessPermissionTest, ResolvedAddresses) { - webrtc::FakeLocalNetworkAccessPermissionFactory factory( - GetParam().lna_permission_status); - - CreateStunPort({GetParam().address, 5000}, /*field_trials=*/nullptr, - &factory); - - PrepareAddress(); - EXPECT_THAT( - webrtc::WaitUntil([&] { return done(); }, IsTrue(), - {.timeout = webrtc::TimeDelta::Millis(kTimeoutMs), - .clock = &fake_clock}), - webrtc::IsRtcOk()); - - if (GetParam().should_succeed) { - EXPECT_FALSE(error()); - EXPECT_EQ(1U, port()->Candidates().size()); - EXPECT_EQ(0, error_event_.error_code); - } else { - EXPECT_TRUE(error()); - EXPECT_EQ(0U, port()->Candidates().size()); - EXPECT_EQ(0, error_event_.error_code); - } -} - -TEST_P(StunPortLocalNetworkAccessPermissionTest, UnresolvedAddresses) { - setup_dns_resolver_mock(); - - webrtc::FakeLocalNetworkAccessPermissionFactory factory( - GetParam().lna_permission_status); - CreateStunPort({"fakehost.test", 5000}, /*field_trials=*/nullptr, &factory); - - PrepareAddress(); - EXPECT_THAT( - webrtc::WaitUntil([&] { return done(); }, IsTrue(), - {.timeout = webrtc::TimeDelta::Millis(kTimeoutMs), - .clock = &fake_clock}), - webrtc::IsRtcOk()); - - if (GetParam().should_succeed) { - EXPECT_FALSE(error()); - EXPECT_EQ(1U, port()->Candidates().size()); - EXPECT_EQ(0, error_event_.error_code); - } else { - EXPECT_TRUE(error()); - EXPECT_EQ(0U, port()->Candidates().size()); - EXPECT_EQ(0, error_event_.error_code); - } -} - -INSTANTIATE_TEST_SUITE_P( - All, - StunPortLocalNetworkAccessPermissionTest, - ::testing::ValuesIn(kAllLocalAreNetworkPermissionTestConfigs)); - class MockAsyncPacketSocket : public webrtc::AsyncPacketSocket { public: ~MockAsyncPacketSocket() override = default; diff --git a/third_party/libwebrtc/p2p/base/turn_port_unittest.cc b/third_party/libwebrtc/p2p/base/turn_port_unittest.cc @@ -24,10 +24,8 @@ #include "api/candidate.h" #include "api/environment/environment.h" #include "api/environment/environment_factory.h" -#include "api/local_network_access_permission.h" #include "api/packet_socket_factory.h" #include "api/test/mock_async_dns_resolver.h" -#include "api/test/mock_local_network_access_permission.h" #include "api/test/rtc_error_matchers.h" #include "api/transport/stun.h" #include "api/units/time_delta.h" @@ -281,12 +279,9 @@ class TurnPortTest : public ::testing::Test, bool CreateTurnPort(const SocketAddress& local_address, absl::string_view username, absl::string_view password, - const ProtocolAddress& server_address, - LocalNetworkAccessPermissionFactoryInterface* - lna_permission_factory = nullptr) { + const ProtocolAddress& server_address) { return CreateTurnPortWithAllParams(MakeNetwork(local_address), username, - password, server_address, - lna_permission_factory); + password, server_address); } bool CreateTurnPortWithNetwork(const Network* network, @@ -303,9 +298,7 @@ class TurnPortTest : public ::testing::Test, bool CreateTurnPortWithAllParams(const Network* network, absl::string_view username, absl::string_view password, - const ProtocolAddress& server_address, - LocalNetworkAccessPermissionFactoryInterface* - lna_permission_factory = nullptr) { + const ProtocolAddress& server_address) { RelayServerConfig config; config.credentials = RelayCredentials(username, password); CreateRelayPortArgs args = {.env = env_}; @@ -317,7 +310,6 @@ class TurnPortTest : public ::testing::Test, args.server_address = &server_address; args.config = &config; args.turn_customizer = turn_customizer_.get(); - args.lna_permission_factory = lna_permission_factory; turn_port_ = TurnPort::Create(args, 0, 0); if (!turn_port_) { @@ -2245,150 +2237,4 @@ INSTANTIATE_TEST_SUITE_P(All, TurnPortIPAddressTypeMetricsTest, ::testing::ValuesIn(kAllIPAddressTypeTestConfigs)); -struct LocalAreaNetworkPermissionTestConfig { - template <typename Sink> - friend void AbslStringify( - Sink& sink, - const LocalAreaNetworkPermissionTestConfig& config) { - sink.Append(config.address); - sink.Append("_"); - switch (config.lna_permission_status) { - case webrtc::LocalNetworkAccessPermissionStatus::kDenied: - sink.Append("Denied"); - break; - case webrtc::LocalNetworkAccessPermissionStatus::kGranted: - sink.Append("Granted"); - break; - } - } - - webrtc::LocalNetworkAccessPermissionStatus lna_permission_status; - absl::string_view address; - bool should_succeed; -} kAllLocalAreNetworkPermissionTestConfigs[] = { - {webrtc::LocalNetworkAccessPermissionStatus::kDenied, "127.0.0.1", - /*should_succeed=*/false}, - {webrtc::LocalNetworkAccessPermissionStatus::kDenied, "10.0.0.3", - /*should_succeed=*/false}, - {webrtc::LocalNetworkAccessPermissionStatus::kDenied, "1.1.1.1", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kDenied, "::1", - /*should_succeed=*/false}, - {webrtc::LocalNetworkAccessPermissionStatus::kDenied, - "fd00:4860:4860::8844", - /*should_succeed=*/false}, - {webrtc::LocalNetworkAccessPermissionStatus::kDenied, - "2001:4860:4860::8888", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kGranted, "127.0.0.1", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kGranted, "10.0.0.3", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kGranted, "1.1.1.1", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kGranted, "::1", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kGranted, - "fd00:4860:4860::8844", - /*should_succeed=*/true}, - {webrtc::LocalNetworkAccessPermissionStatus::kGranted, - "2001:4860:4860::8888", - /*should_succeed=*/true}, -}; - -class TurnPortLocalNetworkAccessPermissionTest - : public TurnPortWithMockDnsResolverTest, - public ::testing::WithParamInterface< - LocalAreaNetworkPermissionTestConfig> { - protected: - void CreateTurnPort( - absl::string_view address, - LocalNetworkAccessPermissionFactoryInterface* lna_permission_factory) { - ProtocolAddress server_address({address, 5000}, PROTO_UDP); - - // Use the test's address instead of `server_address` because - // `server_address` might not be a resolved address with an unknown family. - SocketAddress local_address = - SocketAddress(GetParam().address, 5000).family() == AF_INET6 - ? kLocalIPv6Addr - : kLocalAddr1; - TurnPortWithMockDnsResolverTest::CreateTurnPort( - local_address, kTurnUsername, kTurnPassword, server_address, - lna_permission_factory); - } - - void setup_dns_resolver_mock() { - auto expectations = - [](webrtc::MockAsyncDnsResolver* resolver, - webrtc::MockAsyncDnsResolverResult* resolver_result) { - EXPECT_CALL(*resolver, Start(_, _, _)) - .WillOnce( - [](const webrtc::SocketAddress& /* addr */, int /* family */, - absl::AnyInvocable<void()> callback) { callback(); }); - - EXPECT_CALL(*resolver, result) - .WillRepeatedly(ReturnPointee(resolver_result)); - EXPECT_CALL(*resolver_result, GetError).WillRepeatedly(Return(0)); - EXPECT_CALL(*resolver_result, GetResolvedAddress(_, _)) - .WillOnce(DoAll( - SetArgPointee<1>(SocketAddress(GetParam().address, 5000)), - Return(true))); - }; - - SetDnsResolverExpectations(std::move(expectations)); - } -}; - -TEST_P(TurnPortLocalNetworkAccessPermissionTest, ResolvedAddresses) { - turn_server_.AddInternalSocket({GetParam().address, 5000}, PROTO_UDP); - - FakeLocalNetworkAccessPermissionFactory factory( - GetParam().lna_permission_status); - CreateTurnPort(GetParam().address, &factory); - turn_port_->PrepareAddress(); - - if (GetParam().should_succeed) { - EXPECT_THAT(WaitUntil([&] { return turn_ready_; }, IsTrue(), - {.clock = &fake_clock_}), - IsRtcOk()); - EXPECT_EQ(1u, turn_port_->Candidates().size()); - EXPECT_NE(SOCKET_ERROR, turn_port_->error()); - } else { - EXPECT_THAT(WaitUntil([&] { return turn_error_; }, IsTrue(), - {.clock = &fake_clock_}), - IsRtcOk()); - EXPECT_EQ(0u, turn_port_->Candidates().size()); - EXPECT_NE(SOCKET_ERROR, turn_port_->error()); - } -} - -TEST_P(TurnPortLocalNetworkAccessPermissionTest, UnresolvedAddresses) { - turn_server_.AddInternalSocket({GetParam().address, 5000}, PROTO_UDP); - setup_dns_resolver_mock(); - - FakeLocalNetworkAccessPermissionFactory factory( - GetParam().lna_permission_status); - CreateTurnPort("fakehost.test", &factory); - turn_port_->PrepareAddress(); - - if (GetParam().should_succeed) { - EXPECT_THAT(WaitUntil([&] { return turn_ready_; }, IsTrue(), - {.clock = &fake_clock_}), - IsRtcOk()); - EXPECT_EQ(1u, turn_port_->Candidates().size()); - EXPECT_NE(SOCKET_ERROR, turn_port_->error()); - } else { - EXPECT_THAT(WaitUntil([&] { return turn_error_; }, IsTrue(), - {.clock = &fake_clock_}), - IsRtcOk()); - EXPECT_EQ(0u, turn_port_->Candidates().size()); - EXPECT_NE(SOCKET_ERROR, turn_port_->error()); - } -} - -INSTANTIATE_TEST_SUITE_P( - All, - TurnPortLocalNetworkAccessPermissionTest, - ::testing::ValuesIn(kAllLocalAreNetworkPermissionTestConfigs)); - } // namespace webrtc