| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "services/network/network_change_manager.h" |
| |
| #include <algorithm> |
| #include <utility> |
| |
| #include "base/functional/bind.h" |
| #include "build/build_config.h" |
| #include "mojo/public/cpp/bindings/pending_remote.h" |
| #include "net/base/network_change_notifier.h" |
| #include "net/base/network_change_notifier_passive.h" |
| |
| namespace network { |
| |
| NetworkChangeManager::NetworkChangeManager( |
| std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier) |
| : network_change_notifier_(std::move(network_change_notifier)) { |
| net::NetworkChangeNotifier::AddNetworkChangeObserver(this); |
| connection_type_ = |
| mojom::ConnectionType(net::NetworkChangeNotifier::GetConnectionType()); |
| } |
| |
| NetworkChangeManager::~NetworkChangeManager() { |
| net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); |
| } |
| |
| void NetworkChangeManager::AddReceiver( |
| mojo::PendingReceiver<mojom::NetworkChangeManager> receiver) { |
| receivers_.Add(this, std::move(receiver)); |
| } |
| |
| void NetworkChangeManager::RequestNotifications( |
| mojo::PendingRemote<mojom::NetworkChangeManagerClient> |
| client_pending_remote) { |
| mojo::Remote<mojom::NetworkChangeManagerClient> client_remote( |
| std::move(client_pending_remote)); |
| client_remote.set_disconnect_handler(base::BindOnce( |
| &NetworkChangeManager::NotificationPipeBroken, |
| // base::Unretained is safe as destruction of the |
| // NetworkChangeManager will also destroy the |
| // |clients_| list (which this object will be |
| // inserted into, below), which will destroy the |
| // client_remote, rendering this callback moot. |
| base::Unretained(this), base::Unretained(client_remote.get()))); |
| client_remote->OnInitialConnectionType(connection_type_); |
| clients_.push_back(std::move(client_remote)); |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) |
| void NetworkChangeManager::OnNetworkChanged( |
| bool dns_changed, |
| mojom::IPAddressChangeType ip_address_change_type, |
| bool connection_type_changed, |
| mojom::ConnectionType new_connection_type, |
| bool connection_subtype_changed, |
| mojom::ConnectionSubtype new_connection_subtype) { |
| // network_change_notifier_ can be null in unit tests. |
| if (!network_change_notifier_) |
| return; |
| |
| net::NetworkChangeNotifierPassive* notifier = |
| static_cast<net::NetworkChangeNotifierPassive*>( |
| network_change_notifier_.get()); |
| if (dns_changed) |
| notifier->OnDNSChanged(); |
| if (ip_address_change_type != |
| mojom::IPAddressChangeType::IP_ADDRESS_CHANGE_NONE) { |
| notifier->OnIPAddressChanged( |
| net::NetworkChangeNotifier::IPAddressChangeType( |
| ip_address_change_type)); |
| } |
| if (connection_type_changed) { |
| notifier->OnConnectionChanged( |
| net::NetworkChangeNotifier::ConnectionType(new_connection_type)); |
| } |
| if (connection_type_changed || connection_subtype_changed) { |
| notifier->OnConnectionSubtypeChanged( |
| net::NetworkChangeNotifier::ConnectionType(new_connection_type), |
| net::NetworkChangeNotifier::ConnectionSubtype(new_connection_subtype)); |
| } |
| } |
| #endif |
| |
| #if BUILDFLAG(IS_LINUX) |
| void NetworkChangeManager::BindNetworkInterfaceChangeListener( |
| mojo::PendingAssociatedReceiver<mojom::NetworkInterfaceChangeListener> |
| listener_receiver) { |
| interface_change_listener_receiver_.Bind(std::move(listener_receiver)); |
| } |
| |
| // NetworkInterfaceChangeListener implementation: |
| void NetworkChangeManager::OnNetworkInterfacesChanged( |
| mojom::NetworkInterfaceChangeParamsPtr change_params) { |
| // network_change_notifier_ can be null in unit tests. |
| if (!network_change_notifier_) { |
| return; |
| } |
| |
| net::NetworkChangeNotifierPassive* notifier = |
| static_cast<net::NetworkChangeNotifierPassive*>( |
| network_change_notifier_.get()); |
| |
| notifier->GetAddressMapOwner()->GetAddressMapCacheLinux()->ApplyDiffs( |
| change_params->address_map, change_params->online_links); |
| } |
| #endif // BUILDFLAG(IS_LINUX) |
| |
| size_t NetworkChangeManager::GetNumClientsForTesting() const { |
| return clients_.size(); |
| } |
| |
| void NetworkChangeManager::NotificationPipeBroken( |
| mojom::NetworkChangeManagerClient* client) { |
| clients_.erase(std::ranges::find( |
| clients_, client, &mojo::Remote<mojom::NetworkChangeManagerClient>::get)); |
| } |
| |
| void NetworkChangeManager::OnNetworkChanged( |
| net::NetworkChangeNotifier::ConnectionType type) { |
| connection_type_ = mojom::ConnectionType(type); |
| for (const auto& client : clients_) { |
| client->OnNetworkChanged(connection_type_); |
| } |
| } |
| |
| } // namespace network |