Enable CallbackList constructor subscription and adopt in NetworkManager

Update the CallbackList utility to allow subscribers to be added
directly during instantiation. This adds new constructors that accept a
callback, optionally with a removal tag, reducing the boilerplate
required to set up subscriptions immediately after object creation and
allows for removing multi-step initialization (that in some cases
requires thread hops).

As an initial accompanying change, the NetworkManager
hierarchy—including NetworkManagerBase and BasicNetworkManager—has been
updated to provide constructors that accept an initial network-change
callback. This allows clients to subscribe to network updates at the
moment of manager creation, simplifying initialization patterns and
ensuring no events are missed during setup. Existing tests have been
refactored to utilize these new constructor-based subscriptions.

Bug: webrtc:42222117
Change-Id: If1b001bf36e6a246c3ea241b1685d79e3c3acaec
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/467740
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#47570}
diff --git a/rtc_base/callback_list.h b/rtc_base/callback_list.h
index 043ed00..96e83a3 100644
--- a/rtc_base/callback_list.h
+++ b/rtc_base/callback_list.h
@@ -175,6 +175,12 @@
   CallbackList(CallbackList&&) = delete;
   CallbackList& operator=(CallbackList&&) = delete;
 
+  // Adds a new receiver with removal tag in constructor.
+  template <typename F>
+  CallbackList(const void* removal_tag, F&& f) {
+    AddReceiver(removal_tag, std::forward<F>(f));
+  }
+
   // Adds a new receiver. The receiver (a callable object or a function pointer)
   // must be movable, but need not be copyable. Its call signature should be
   // `void(ArgT...)`. The removal tag is a pointer to an arbitrary object that
diff --git a/rtc_base/callback_list_unittest.cc b/rtc_base/callback_list_unittest.cc
index 7c576ea..a5b0c41 100644
--- a/rtc_base/callback_list_unittest.cc
+++ b/rtc_base/callback_list_unittest.cc
@@ -317,5 +317,16 @@
 
 #pragma clang diagnostic pop
 
+TEST(CallbackList, ConstructorSingleSubscriberWithTagTest) {
+  int removal_tag;
+  int accumulator = 0;
+  CallbackList<> c(&removal_tag, [&accumulator] { accumulator += 10; });
+  c.Send();
+  EXPECT_EQ(accumulator, 10);
+  c.RemoveReceivers(&removal_tag);
+  c.Send();
+  EXPECT_EQ(accumulator, 10);  // No change after removal.
+}
+
 }  // namespace
 }  // namespace webrtc
diff --git a/rtc_base/network.cc b/rtc_base/network.cc
index f8ad220..e023bc8 100644
--- a/rtc_base/network.cc
+++ b/rtc_base/network.cc
@@ -327,6 +327,12 @@
   return nullptr;
 }
 
+NetworkManager::NetworkManager(NetworksChangedCallback callback) {
+  RTC_CHECK(callback.callback != nullptr);
+  networks_changed_callbacks_.AddReceiver(callback.removal_tag,
+                                          std::move(callback.callback));
+}
+
 void NetworkManager::SubscribeNetworksChanged(
     absl::AnyInvocable<void()> callback) {
   networks_changed_callbacks_.AddReceiver(std::move(callback));
@@ -354,6 +360,10 @@
 NetworkManagerBase::NetworkManagerBase()
     : enumeration_permission_(NetworkManager::ENUMERATION_ALLOWED) {}
 
+NetworkManagerBase::NetworkManagerBase(NetworksChangedCallback callback)
+    : NetworkManager(std::move(callback)),
+      enumeration_permission_(NetworkManager::ENUMERATION_ALLOWED) {}
+
 NetworkManager::EnumerationPermission
 NetworkManagerBase::enumeration_permission() const {
   return enumeration_permission_;
@@ -594,6 +604,22 @@
   RTC_DCHECK(socket_factory_);
 }
 
+BasicNetworkManager::BasicNetworkManager(
+    const Environment& env,
+    SocketFactory* absl_nonnull socket_factory,
+    NetworksChangedCallback callback,
+    NetworkMonitorFactory* absl_nullable network_monitor_factory)
+    : NetworkManagerBase(std::move(callback)),
+      env_(env),
+      network_monitor_factory_(network_monitor_factory),
+      socket_factory_(socket_factory),
+      allow_mac_based_ipv6_(
+          env_.field_trials().IsEnabled("WebRTC-AllowMACBasedIPv6")),
+      bind_using_ifname_(
+          !env_.field_trials().IsDisabled("WebRTC-BindUsingInterfaceName")) {
+  RTC_DCHECK(socket_factory_);
+}
+
 BasicNetworkManager::~BasicNetworkManager() {
   if (task_safety_flag_) {
     task_safety_flag_->SetNotAlive();
diff --git a/rtc_base/network.h b/rtc_base/network.h
index 0190f49..3772371 100644
--- a/rtc_base/network.h
+++ b/rtc_base/network.h
@@ -126,6 +126,13 @@
                                   public MdnsResponderProvider {
  public:
   NetworkManager() = default;
+  // NetworksChangedCallback joins the removal tag and the callable.
+  struct NetworksChangedCallback {
+    const void* removal_tag;
+    absl::AnyInvocable<void()> callback;
+  };
+
+  explicit NetworkManager(NetworksChangedCallback callback);
   // This enum indicates whether adapter enumeration is allowed.
   enum EnumerationPermission {
     ENUMERATION_ALLOWED,  // Adapter enumeration is allowed. Getting 0 network
@@ -480,6 +487,7 @@
 class RTC_EXPORT NetworkManagerBase : public NetworkManager {
  public:
   NetworkManagerBase();
+  explicit NetworkManagerBase(NetworksChangedCallback callback);
 
   std::vector<const Network*> GetNetworks() const override;
   std::vector<const Network*> GetAnyAddressNetworks() override;
@@ -555,6 +563,12 @@
       SocketFactory* absl_nonnull socket_factory,
       NetworkMonitorFactory* absl_nullable network_monitor_factory = nullptr);
 
+  BasicNetworkManager(
+      const Environment& env,
+      SocketFactory* absl_nonnull socket_factory,
+      NetworksChangedCallback callback,
+      NetworkMonitorFactory* absl_nullable network_monitor_factory = nullptr);
+
   ~BasicNetworkManager() override;
 
   void StartUpdating() override;
diff --git a/rtc_base/network_unittest.cc b/rtc_base/network_unittest.cc
index e5697a5..5694358 100644
--- a/rtc_base/network_unittest.cc
+++ b/rtc_base/network_unittest.cc
@@ -426,8 +426,8 @@
 // ALLOWED.
 TEST_F(NetworkTest, TestUpdateNetworks) {
   PhysicalSocketServer socket_server;
-  BasicNetworkManager manager(env_, &socket_server);
-  manager.SubscribeNetworksChanged(this, [this] { OnNetworksChanged(); });
+  BasicNetworkManager manager(env_, &socket_server,
+                              {this, [this] { OnNetworksChanged(); }});
   EXPECT_EQ(NetworkManager::ENUMERATION_ALLOWED,
             manager.enumeration_permission());
   manager.StartUpdating();
@@ -572,8 +572,8 @@
 // Test that the basic network merging case works.
 TEST_F(NetworkTest, TestIPv6MergeNetworkList) {
   PhysicalSocketServer socket_server;
-  BasicNetworkManager manager(env_, &socket_server);
-  manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); });
+  BasicNetworkManager manager(env_, &socket_server,
+                              {this, [this]() { OnNetworksChanged(); }});
   std::vector<std::unique_ptr<Network>> networks;
   SetupNetworks(&networks);
   std::vector<const Network*> original_list = CopyNetworkPointers(networks);
@@ -593,8 +593,8 @@
 // objects remain in the result list.
 TEST_F(NetworkTest, TestNoChangeMerge) {
   PhysicalSocketServer socket_server;
-  BasicNetworkManager manager(env_, &socket_server);
-  manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); });
+  BasicNetworkManager manager(env_, &socket_server,
+                              {this, [this]() { OnNetworksChanged(); }});
   std::vector<std::unique_ptr<Network>> networks;
   SetupNetworks(&networks);
   std::vector<const Network*> original_list = CopyNetworkPointers(networks);
@@ -623,8 +623,8 @@
 // IP changed.
 TEST_F(NetworkTest, MergeWithChangedIP) {
   PhysicalSocketServer socket_server;
-  BasicNetworkManager manager(env_, &socket_server);
-  manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); });
+  BasicNetworkManager manager(env_, &socket_server,
+                              {this, [this]() { OnNetworksChanged(); }});
   std::vector<std::unique_ptr<Network>> original_list;
   SetupNetworks(&original_list);
   // Make a network that we're going to change.
@@ -658,8 +658,8 @@
 
 TEST_F(NetworkTest, TestMultipleIPMergeNetworkList) {
   PhysicalSocketServer socket_server;
-  BasicNetworkManager manager(env_, &socket_server);
-  manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); });
+  BasicNetworkManager manager(env_, &socket_server,
+                              {this, [this]() { OnNetworksChanged(); }});
   std::vector<std::unique_ptr<Network>> original_list;
   SetupNetworks(&original_list);
   const Network* const network_ptr = original_list[2].get();
@@ -710,8 +710,8 @@
 // Test that merge correctly distinguishes multiple networks on an interface.
 TEST_F(NetworkTest, TestMultiplePublicNetworksOnOneInterfaceMerge) {
   PhysicalSocketServer socket_server;
-  BasicNetworkManager manager(env_, &socket_server);
-  manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); });
+  BasicNetworkManager manager(env_, &socket_server,
+                              {this, [this]() { OnNetworksChanged(); }});
   std::vector<std::unique_ptr<Network>> original_list;
   SetupNetworks(&original_list);
   bool changed = false;
@@ -1244,8 +1244,9 @@
 TEST_F(NetworkTest, TestNetworkMonitoring) {
   FakeNetworkMonitorFactory factory;
   PhysicalSocketServer socket_server;
-  BasicNetworkManager manager(env_, &socket_server, &factory);
-  manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); });
+  BasicNetworkManager manager(env_, &socket_server,
+                              {this, [this]() { OnNetworksChanged(); }},
+                              &factory);
   manager.StartUpdating();
   FakeNetworkMonitor* network_monitor = GetNetworkMonitor(manager);
   EXPECT_TRUE(network_monitor && network_monitor->started());
@@ -1275,8 +1276,9 @@
   IPAddress ip;
   FakeNetworkMonitorFactory factory;
   PhysicalSocketServer socket_server;
-  TestBasicNetworkManager manager(env_, &socket_server, &factory);
-  manager.SubscribeNetworksChanged(this, [this]() { OnNetworksChanged(); });
+  TestBasicNetworkManager manager(env_, &socket_server,
+                                  {this, [this]() { OnNetworksChanged(); }},
+                                  &factory);
   manager.StartUpdating();
   EXPECT_THAT(WaitUntil([&] { return callback_called_; }, IsTrue()), IsRtcOk());