1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "services/network/network_change_manager.h"
6 
7 #include <algorithm>
8 #include <utility>
9 
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "mojo/public/cpp/bindings/pending_remote.h"
13 #include "net/base/network_change_notifier.h"
14 #include "net/base/network_change_notifier_posix.h"
15 
16 namespace network {
17 
NetworkChangeManager(std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier)18 NetworkChangeManager::NetworkChangeManager(
19     std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier)
20     : network_change_notifier_(std::move(network_change_notifier)) {
21   net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
22   connection_type_ =
23       mojom::ConnectionType(net::NetworkChangeNotifier::GetConnectionType());
24 }
25 
~NetworkChangeManager()26 NetworkChangeManager::~NetworkChangeManager() {
27   net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
28 }
29 
AddReceiver(mojo::PendingReceiver<mojom::NetworkChangeManager> receiver)30 void NetworkChangeManager::AddReceiver(
31     mojo::PendingReceiver<mojom::NetworkChangeManager> receiver) {
32   receivers_.Add(this, std::move(receiver));
33 }
34 
RequestNotifications(mojo::PendingRemote<mojom::NetworkChangeManagerClient> client_pending_remote)35 void NetworkChangeManager::RequestNotifications(
36     mojo::PendingRemote<mojom::NetworkChangeManagerClient>
37         client_pending_remote) {
38   mojo::Remote<mojom::NetworkChangeManagerClient> client_remote(
39       std::move(client_pending_remote));
40   client_remote.set_disconnect_handler(base::BindOnce(
41       &NetworkChangeManager::NotificationPipeBroken,
42       // base::Unretained is safe as destruction of the
43       // NetworkChangeManager will also destroy the
44       // |clients_| list (which this object will be
45       // inserted into, below), which will destroy the
46       // client_remote, rendering this callback moot.
47       base::Unretained(this), base::Unretained(client_remote.get())));
48   client_remote->OnInitialConnectionType(connection_type_);
49   clients_.push_back(std::move(client_remote));
50 }
51 
52 #if defined(OS_CHROMEOS) || defined(OS_ANDROID)
OnNetworkChanged(bool dns_changed,bool ip_address_changed,bool connection_type_changed,mojom::ConnectionType new_connection_type,bool connection_subtype_changed,mojom::ConnectionSubtype new_connection_subtype)53 void NetworkChangeManager::OnNetworkChanged(
54     bool dns_changed,
55     bool ip_address_changed,
56     bool connection_type_changed,
57     mojom::ConnectionType new_connection_type,
58     bool connection_subtype_changed,
59     mojom::ConnectionSubtype new_connection_subtype) {
60   // network_change_notifier_ can be null in unit tests.
61   if (!network_change_notifier_)
62     return;
63 
64   net::NetworkChangeNotifierPosix* notifier =
65       static_cast<net::NetworkChangeNotifierPosix*>(
66           network_change_notifier_.get());
67   if (dns_changed)
68     notifier->OnDNSChanged();
69   if (ip_address_changed)
70     notifier->OnIPAddressChanged();
71   if (connection_type_changed) {
72     notifier->OnConnectionChanged(
73         net::NetworkChangeNotifier::ConnectionType(new_connection_type));
74   }
75   if (connection_type_changed || connection_subtype_changed) {
76     notifier->OnConnectionSubtypeChanged(
77         net::NetworkChangeNotifier::ConnectionType(new_connection_type),
78         net::NetworkChangeNotifier::ConnectionSubtype(new_connection_subtype));
79   }
80 }
81 #endif
82 
GetNumClientsForTesting() const83 size_t NetworkChangeManager::GetNumClientsForTesting() const {
84   return clients_.size();
85 }
86 
NotificationPipeBroken(mojom::NetworkChangeManagerClient * client)87 void NetworkChangeManager::NotificationPipeBroken(
88     mojom::NetworkChangeManagerClient* client) {
89   clients_.erase(std::find_if(
90       clients_.begin(), clients_.end(),
91       [client](mojo::Remote<mojom::NetworkChangeManagerClient>& remote) {
92         return remote.get() == client;
93       }));
94 }
95 
OnNetworkChanged(net::NetworkChangeNotifier::ConnectionType type)96 void NetworkChangeManager::OnNetworkChanged(
97     net::NetworkChangeNotifier::ConnectionType type) {
98   connection_type_ = mojom::ConnectionType(type);
99   for (const auto& client : clients_) {
100     client->OnNetworkChanged(connection_type_);
101   }
102 }
103 
104 }  // namespace network
105