1 // Copyright 2014 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.
5 #include "components/metrics/net/network_metrics_provider.h"
10 #include "base/compiler_specific.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/string_util.h"
14 #include "base/task_runner_util.h"
16 #if defined(OS_CHROMEOS)
17 #include "components/metrics/net/wifi_access_point_info_provider_chromeos.h"
22 NetworkMetricsProvider::NetworkMetricsProvider(
23 base::TaskRunner
* io_task_runner
)
24 : io_task_runner_(io_task_runner
),
25 connection_type_is_ambiguous_(false),
26 wifi_phy_layer_protocol_is_ambiguous_(false),
27 wifi_phy_layer_protocol_(net::WIFI_PHY_LAYER_PROTOCOL_UNKNOWN
),
28 weak_ptr_factory_(this) {
29 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
30 connection_type_
= net::NetworkChangeNotifier::GetConnectionType();
31 ProbeWifiPHYLayerProtocol();
34 NetworkMetricsProvider::~NetworkMetricsProvider() {
35 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
38 void NetworkMetricsProvider::OnDidCreateMetricsLog() {
39 net::NetworkChangeNotifier::LogOperatorCodeHistogram(
40 net::NetworkChangeNotifier::GetConnectionType());
43 void NetworkMetricsProvider::ProvideSystemProfileMetrics(
44 SystemProfileProto
* system_profile
) {
45 SystemProfileProto::Network
* network
= system_profile
->mutable_network();
46 network
->set_connection_type_is_ambiguous(connection_type_is_ambiguous_
);
47 network
->set_connection_type(GetConnectionType());
48 network
->set_wifi_phy_layer_protocol_is_ambiguous(
49 wifi_phy_layer_protocol_is_ambiguous_
);
50 network
->set_wifi_phy_layer_protocol(GetWifiPHYLayerProtocol());
52 // Resets the "ambiguous" flags, since a new metrics log session has started.
53 connection_type_is_ambiguous_
= false;
54 // TODO(isherman): This line seems unnecessary.
55 connection_type_
= net::NetworkChangeNotifier::GetConnectionType();
56 wifi_phy_layer_protocol_is_ambiguous_
= false;
58 if (!wifi_access_point_info_provider_
.get()) {
59 #if defined(OS_CHROMEOS)
60 wifi_access_point_info_provider_
.reset(
61 new WifiAccessPointInfoProviderChromeos());
63 wifi_access_point_info_provider_
.reset(
64 new WifiAccessPointInfoProvider());
68 // Connected wifi access point information.
69 WifiAccessPointInfoProvider::WifiAccessPointInfo info
;
70 if (wifi_access_point_info_provider_
->GetInfo(&info
))
71 WriteWifiAccessPointProto(info
, network
);
74 void NetworkMetricsProvider::OnConnectionTypeChanged(
75 net::NetworkChangeNotifier::ConnectionType type
) {
76 if (type
== net::NetworkChangeNotifier::CONNECTION_NONE
)
78 if (type
!= connection_type_
&&
79 connection_type_
!= net::NetworkChangeNotifier::CONNECTION_NONE
) {
80 connection_type_is_ambiguous_
= true;
82 connection_type_
= type
;
84 ProbeWifiPHYLayerProtocol();
87 SystemProfileProto::Network::ConnectionType
88 NetworkMetricsProvider::GetConnectionType() const {
89 switch (connection_type_
) {
90 case net::NetworkChangeNotifier::CONNECTION_NONE
:
91 case net::NetworkChangeNotifier::CONNECTION_UNKNOWN
:
92 return SystemProfileProto::Network::CONNECTION_UNKNOWN
;
93 case net::NetworkChangeNotifier::CONNECTION_ETHERNET
:
94 return SystemProfileProto::Network::CONNECTION_ETHERNET
;
95 case net::NetworkChangeNotifier::CONNECTION_WIFI
:
96 return SystemProfileProto::Network::CONNECTION_WIFI
;
97 case net::NetworkChangeNotifier::CONNECTION_2G
:
98 return SystemProfileProto::Network::CONNECTION_2G
;
99 case net::NetworkChangeNotifier::CONNECTION_3G
:
100 return SystemProfileProto::Network::CONNECTION_3G
;
101 case net::NetworkChangeNotifier::CONNECTION_4G
:
102 return SystemProfileProto::Network::CONNECTION_4G
;
103 case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH
:
104 return SystemProfileProto::Network::CONNECTION_BLUETOOTH
;
107 return SystemProfileProto::Network::CONNECTION_UNKNOWN
;
110 SystemProfileProto::Network::WifiPHYLayerProtocol
111 NetworkMetricsProvider::GetWifiPHYLayerProtocol() const {
112 switch (wifi_phy_layer_protocol_
) {
113 case net::WIFI_PHY_LAYER_PROTOCOL_NONE
:
114 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_NONE
;
115 case net::WIFI_PHY_LAYER_PROTOCOL_ANCIENT
:
116 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_ANCIENT
;
117 case net::WIFI_PHY_LAYER_PROTOCOL_A
:
118 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_A
;
119 case net::WIFI_PHY_LAYER_PROTOCOL_B
:
120 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_B
;
121 case net::WIFI_PHY_LAYER_PROTOCOL_G
:
122 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_G
;
123 case net::WIFI_PHY_LAYER_PROTOCOL_N
:
124 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_N
;
125 case net::WIFI_PHY_LAYER_PROTOCOL_UNKNOWN
:
126 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_UNKNOWN
;
129 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_UNKNOWN
;
132 void NetworkMetricsProvider::ProbeWifiPHYLayerProtocol() {
133 PostTaskAndReplyWithResult(
136 base::Bind(&net::GetWifiPHYLayerProtocol
),
137 base::Bind(&NetworkMetricsProvider::OnWifiPHYLayerProtocolResult
,
138 weak_ptr_factory_
.GetWeakPtr()));
141 void NetworkMetricsProvider::OnWifiPHYLayerProtocolResult(
142 net::WifiPHYLayerProtocol mode
) {
143 if (wifi_phy_layer_protocol_
!= net::WIFI_PHY_LAYER_PROTOCOL_UNKNOWN
&&
144 mode
!= wifi_phy_layer_protocol_
) {
145 wifi_phy_layer_protocol_is_ambiguous_
= true;
147 wifi_phy_layer_protocol_
= mode
;
150 void NetworkMetricsProvider::WriteWifiAccessPointProto(
151 const WifiAccessPointInfoProvider::WifiAccessPointInfo
& info
,
152 SystemProfileProto::Network
* network_proto
) {
153 SystemProfileProto::Network::WifiAccessPoint
* access_point_info
=
154 network_proto
->mutable_access_point_info();
155 SystemProfileProto::Network::WifiAccessPoint::SecurityMode security
=
156 SystemProfileProto::Network::WifiAccessPoint::SECURITY_UNKNOWN
;
157 switch (info
.security
) {
158 case WifiAccessPointInfoProvider::WIFI_SECURITY_NONE
:
159 security
= SystemProfileProto::Network::WifiAccessPoint::SECURITY_NONE
;
161 case WifiAccessPointInfoProvider::WIFI_SECURITY_WPA
:
162 security
= SystemProfileProto::Network::WifiAccessPoint::SECURITY_WPA
;
164 case WifiAccessPointInfoProvider::WIFI_SECURITY_WEP
:
165 security
= SystemProfileProto::Network::WifiAccessPoint::SECURITY_WEP
;
167 case WifiAccessPointInfoProvider::WIFI_SECURITY_RSN
:
168 security
= SystemProfileProto::Network::WifiAccessPoint::SECURITY_RSN
;
170 case WifiAccessPointInfoProvider::WIFI_SECURITY_802_1X
:
171 security
= SystemProfileProto::Network::WifiAccessPoint::SECURITY_802_1X
;
173 case WifiAccessPointInfoProvider::WIFI_SECURITY_PSK
:
174 security
= SystemProfileProto::Network::WifiAccessPoint::SECURITY_PSK
;
176 case WifiAccessPointInfoProvider::WIFI_SECURITY_UNKNOWN
:
177 security
= SystemProfileProto::Network::WifiAccessPoint::SECURITY_UNKNOWN
;
180 access_point_info
->set_security_mode(security
);
182 // |bssid| is xx:xx:xx:xx:xx:xx, extract the first three components and
183 // pack into a uint32.
184 std::string bssid
= info
.bssid
;
185 if (bssid
.size() == 17 && bssid
[2] == ':' && bssid
[5] == ':' &&
186 bssid
[8] == ':' && bssid
[11] == ':' && bssid
[14] == ':') {
187 std::string vendor_prefix_str
;
188 uint32 vendor_prefix
;
190 base::RemoveChars(bssid
.substr(0, 9), ":", &vendor_prefix_str
);
191 DCHECK_EQ(6U, vendor_prefix_str
.size());
192 if (base::HexStringToUInt(vendor_prefix_str
, &vendor_prefix
))
193 access_point_info
->set_vendor_prefix(vendor_prefix
);
198 // Return if vendor information is not provided.
199 if (info
.model_number
.empty() && info
.model_name
.empty() &&
200 info
.device_name
.empty() && info
.oui_list
.empty())
203 SystemProfileProto::Network::WifiAccessPoint::VendorInformation
* vendor
=
204 access_point_info
->mutable_vendor_info();
205 if (!info
.model_number
.empty())
206 vendor
->set_model_number(info
.model_number
);
207 if (!info
.model_name
.empty())
208 vendor
->set_model_name(info
.model_name
);
209 if (!info
.device_name
.empty())
210 vendor
->set_device_name(info
.device_name
);
212 // Return if OUI list is not provided.
213 if (info
.oui_list
.empty())
217 std::vector
<std::string
> oui_list
;
218 base::SplitString(info
.oui_list
, ' ', &oui_list
);
219 for (std::vector
<std::string
>::const_iterator it
= oui_list
.begin();
220 it
!= oui_list
.end();
223 if (base::HexStringToUInt(*it
, &oui
))
224 vendor
->add_element_identifier(oui
);
230 bool NetworkMetricsProvider::IsCellularConnection() {
231 switch (GetConnectionType()) {
232 case SystemProfileProto_Network_ConnectionType_CONNECTION_2G
:
233 case SystemProfileProto_Network_ConnectionType_CONNECTION_3G
:
234 case SystemProfileProto_Network_ConnectionType_CONNECTION_4G
:
241 void NetworkMetricsProvider::GetIsCellularConnection(bool* is_cellular_out
) {
242 *is_cellular_out
= IsCellularConnection();
245 base::Callback
<void(bool*)> NetworkMetricsProvider::GetConnectionCallback() {
246 return base::Bind(&NetworkMetricsProvider::GetIsCellularConnection
,
247 weak_ptr_factory_
.GetWeakPtr());
250 } // namespace metrics