1 // Copyright 2020 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 "chrome/browser/chromeos/net/network_health/network_health.h"
6
7 #include <map>
8 #include <vector>
9
10 #include "chromeos/network/network_event_log.h"
11 #include "chromeos/services/network_config/in_process_instance.h"
12 #include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
13 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
14 #include "chromeos/services/network_health/public/mojom/network_health.mojom.h"
15
16 namespace chromeos {
17 namespace network_health {
18
19 namespace {
20
DeviceStateToNetworkState(network_config::mojom::DeviceStateType device_state)21 constexpr mojom::NetworkState DeviceStateToNetworkState(
22 network_config::mojom::DeviceStateType device_state) {
23 switch (device_state) {
24 case network_config::mojom::DeviceStateType::kUninitialized:
25 return mojom::NetworkState::kUninitialized;
26 case network_config::mojom::DeviceStateType::kDisabled:
27 case network_config::mojom::DeviceStateType::kDisabling:
28 case network_config::mojom::DeviceStateType::kEnabling:
29 // Disabling and Enabling are intermediate state that we care about in the
30 // UI, but not for purposes of network health, we can treat as Disabled.
31 return mojom::NetworkState::kDisabled;
32 case network_config::mojom::DeviceStateType::kEnabled:
33 return mojom::NetworkState::kNotConnected;
34 case network_config::mojom::DeviceStateType::kProhibited:
35 return mojom::NetworkState::kProhibited;
36 case network_config::mojom::DeviceStateType::kUnavailable:
37 NOTREACHED();
38 return mojom::NetworkState::kUninitialized;
39 }
40 }
41
ConnectionStateToNetworkState(network_config::mojom::ConnectionStateType connection_state)42 constexpr mojom::NetworkState ConnectionStateToNetworkState(
43 network_config::mojom::ConnectionStateType connection_state) {
44 switch (connection_state) {
45 case network_config::mojom::ConnectionStateType::kOnline:
46 return mojom::NetworkState::kOnline;
47 case network_config::mojom::ConnectionStateType::kConnected:
48 return mojom::NetworkState::kConnected;
49 case network_config::mojom::ConnectionStateType::kPortal:
50 return mojom::NetworkState::kPortal;
51 case network_config::mojom::ConnectionStateType::kConnecting:
52 return mojom::NetworkState::kConnecting;
53 case network_config::mojom::ConnectionStateType::kNotConnected:
54 return mojom::NetworkState::kNotConnected;
55 }
56 }
57
58 // Populates a mojom::NetworkPtr based on the given |device_prop| and
59 // |network_prop| if a valid Network can be created. Returns a base::nullopt
60 // otherwise. This function assumes that |device_prop| is populated, while
61 // |network_prop| could be null.
CreateNetwork(const network_config::mojom::DeviceStatePropertiesPtr & device_prop,const network_config::mojom::NetworkStatePropertiesPtr & net_prop)62 mojom::NetworkPtr CreateNetwork(
63 const network_config::mojom::DeviceStatePropertiesPtr& device_prop,
64 const network_config::mojom::NetworkStatePropertiesPtr& net_prop) {
65 auto net = mojom::Network::New();
66 net->mac_address = device_prop->mac_address;
67 net->type = device_prop->type;
68
69 if (net_prop) {
70 net->state = ConnectionStateToNetworkState(net_prop->connection_state);
71 net->name = net_prop->name;
72 net->guid = net_prop->guid;
73 if (chromeos::network_config::NetworkTypeMatchesType(
74 net_prop->type, network_config::mojom::NetworkType::kWireless)) {
75 net->signal_strength = network_health::mojom::UInt32Value::New(
76 network_config::GetWirelessSignalStrength(net_prop.get()));
77 }
78 } else {
79 net->state = DeviceStateToNetworkState(device_prop->device_state);
80 }
81
82 return net;
83 }
84
85 } // namespace
86
NetworkHealth()87 NetworkHealth::NetworkHealth() {
88 network_config::BindToInProcessInstance(
89 remote_cros_network_config_.BindNewPipeAndPassReceiver());
90 remote_cros_network_config_->AddObserver(
91 cros_network_config_observer_receiver_.BindNewPipeAndPassRemote());
92 RefreshNetworkHealthState();
93 }
94
95 NetworkHealth::~NetworkHealth() = default;
96
BindReceiver(mojo::PendingReceiver<mojom::NetworkHealthService> receiver)97 void NetworkHealth::BindReceiver(
98 mojo::PendingReceiver<mojom::NetworkHealthService> receiver) {
99 receivers_.Add(this, std::move(receiver));
100 }
101
GetNetworkHealthState()102 const mojom::NetworkHealthStatePtr NetworkHealth::GetNetworkHealthState() {
103 NET_LOG(EVENT) << "Network Health State Requested";
104 return network_health_state_.Clone();
105 }
106
GetNetworkList(GetNetworkListCallback callback)107 void NetworkHealth::GetNetworkList(GetNetworkListCallback callback) {
108 std::move(callback).Run(mojo::Clone(network_health_state_.networks));
109 }
110
GetHealthSnapshot(GetHealthSnapshotCallback callback)111 void NetworkHealth::GetHealthSnapshot(GetHealthSnapshotCallback callback) {
112 std::move(callback).Run(network_health_state_.Clone());
113 }
114
OnNetworkStateListChanged()115 void NetworkHealth::OnNetworkStateListChanged() {
116 RequestNetworkStateList();
117 }
118
OnDeviceStateListChanged()119 void NetworkHealth::OnDeviceStateListChanged() {
120 RequestDeviceStateList();
121 }
122
OnActiveNetworksChanged(std::vector<network_config::mojom::NetworkStatePropertiesPtr>)123 void NetworkHealth::OnActiveNetworksChanged(
124 std::vector<network_config::mojom::NetworkStatePropertiesPtr>) {}
125
OnNetworkStateChanged(network_config::mojom::NetworkStatePropertiesPtr)126 void NetworkHealth::OnNetworkStateChanged(
127 network_config::mojom::NetworkStatePropertiesPtr) {}
128
OnVpnProvidersChanged()129 void NetworkHealth::OnVpnProvidersChanged() {}
130
OnNetworkCertificatesChanged()131 void NetworkHealth::OnNetworkCertificatesChanged() {}
132
OnNetworkStateListReceived(std::vector<network_config::mojom::NetworkStatePropertiesPtr> props)133 void NetworkHealth::OnNetworkStateListReceived(
134 std::vector<network_config::mojom::NetworkStatePropertiesPtr> props) {
135 network_properties_.swap(props);
136 CreateNetworkHealthState();
137 }
138
OnDeviceStateListReceived(std::vector<network_config::mojom::DeviceStatePropertiesPtr> props)139 void NetworkHealth::OnDeviceStateListReceived(
140 std::vector<network_config::mojom::DeviceStatePropertiesPtr> props) {
141 device_properties_.swap(props);
142 CreateNetworkHealthState();
143 }
144
CreateNetworkHealthState()145 void NetworkHealth::CreateNetworkHealthState() {
146 // If the device information has not been collected, the NetworkHealthState
147 // cannot be created.
148 if (device_properties_.empty())
149 return;
150
151 network_health_state_.networks.clear();
152
153 std::map<network_config::mojom::NetworkType,
154 network_config::mojom::DeviceStatePropertiesPtr>
155 device_type_map;
156
157 // This function only supports one Network structure per underlying device. If
158 // this assumption changes, this function will need to be reworked.
159 for (const auto& d : device_properties_) {
160 device_type_map[d->type] = mojo::Clone(d);
161 }
162
163 // For each NetworkStateProperties, create a Network structure using the
164 // underlying DeviceStateProperties. Remove devices from the type map that
165 // have an associated NetworkStateProperties.
166 for (const auto& net_prop : network_properties_) {
167 auto device_iter = device_type_map.find(net_prop->type);
168 if (device_iter == device_type_map.end()) {
169 continue;
170 }
171 network_health_state_.networks.push_back(
172 CreateNetwork(device_iter->second, net_prop));
173 device_type_map.erase(device_iter);
174 }
175
176 // For the remaining devices that do not have associated
177 // NetworkStateProperties, create Network structures.
178 for (const auto& device_prop : device_type_map) {
179 // Devices that have an kUnavailable state are not valid.
180 if (device_prop.second->device_state ==
181 network_config::mojom::DeviceStateType::kUnavailable) {
182 NET_LOG(ERROR) << "Device in unexpected unavailable state: "
183 << device_prop.second->type;
184 continue;
185 }
186
187 network_health_state_.networks.push_back(
188 CreateNetwork(device_prop.second, nullptr));
189 }
190 }
191
RefreshNetworkHealthState()192 void NetworkHealth::RefreshNetworkHealthState() {
193 RequestNetworkStateList();
194 RequestDeviceStateList();
195 }
196
RequestNetworkStateList()197 void NetworkHealth::RequestNetworkStateList() {
198 remote_cros_network_config_->GetNetworkStateList(
199 network_config::mojom::NetworkFilter::New(
200 network_config::mojom::FilterType::kActive,
201 network_config::mojom::NetworkType::kAll,
202 network_config::mojom::kNoLimit),
203 base::BindOnce(&NetworkHealth::OnNetworkStateListReceived,
204 base::Unretained(this)));
205 }
206
RequestDeviceStateList()207 void NetworkHealth::RequestDeviceStateList() {
208 remote_cros_network_config_->GetDeviceStateList(base::BindOnce(
209 &NetworkHealth::OnDeviceStateListReceived, base::Unretained(this)));
210 }
211
212 } // namespace network_health
213 } // namespace chromeos
214