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