Make NetworkMetricsProvider::OnDidCreateMetricsLog a no-op on non-Android.
[chromium-blink-merge.git] / components / metrics / net / network_metrics_provider.cc
blob12054a9d2ad2260e2381ac4dc7ee7c353aaface5
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"
7 #include <string>
8 #include <vector>
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"
18 #endif // OS_CHROMEOS
20 namespace metrics {
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 #if defined(OS_ANDROID)
40 net::NetworkChangeNotifier::LogOperatorCodeHistogram(
41 net::NetworkChangeNotifier::GetConnectionType());
42 #endif // OS_ANDROID
45 void NetworkMetricsProvider::ProvideSystemProfileMetrics(
46 SystemProfileProto* system_profile) {
47 SystemProfileProto::Network* network = system_profile->mutable_network();
48 network->set_connection_type_is_ambiguous(connection_type_is_ambiguous_);
49 network->set_connection_type(GetConnectionType());
50 network->set_wifi_phy_layer_protocol_is_ambiguous(
51 wifi_phy_layer_protocol_is_ambiguous_);
52 network->set_wifi_phy_layer_protocol(GetWifiPHYLayerProtocol());
54 // Update the connection type. Note that this is necessary to set the network
55 // type to "none" if there is no network connection for an entire UMA logging
56 // window, since OnConnectionTypeChanged() ignores transitions to the "none"
57 // state.
58 connection_type_ = net::NetworkChangeNotifier::GetConnectionType();
59 // Reset the "ambiguous" flags, since a new metrics log session has started.
60 connection_type_is_ambiguous_ = false;
61 wifi_phy_layer_protocol_is_ambiguous_ = false;
63 if (!wifi_access_point_info_provider_.get()) {
64 #if defined(OS_CHROMEOS)
65 wifi_access_point_info_provider_.reset(
66 new WifiAccessPointInfoProviderChromeos());
67 #else
68 wifi_access_point_info_provider_.reset(
69 new WifiAccessPointInfoProvider());
70 #endif // OS_CHROMEOS
73 // Connected wifi access point information.
74 WifiAccessPointInfoProvider::WifiAccessPointInfo info;
75 if (wifi_access_point_info_provider_->GetInfo(&info))
76 WriteWifiAccessPointProto(info, network);
79 void NetworkMetricsProvider::OnConnectionTypeChanged(
80 net::NetworkChangeNotifier::ConnectionType type) {
81 // To avoid reporting an ambiguous connection type for users on flaky
82 // connections, ignore transitions to the "none" state. Note that the
83 // connection type is refreshed in ProvideSystemProfileMetrics() each time a
84 // new UMA logging window begins, so users who genuinely transition to offline
85 // mode for an extended duration will still be at least partially represented
86 // in the metrics logs.
87 if (type == net::NetworkChangeNotifier::CONNECTION_NONE)
88 return;
90 if (type != connection_type_ &&
91 connection_type_ != net::NetworkChangeNotifier::CONNECTION_NONE) {
92 connection_type_is_ambiguous_ = true;
94 connection_type_ = type;
96 ProbeWifiPHYLayerProtocol();
99 SystemProfileProto::Network::ConnectionType
100 NetworkMetricsProvider::GetConnectionType() const {
101 switch (connection_type_) {
102 case net::NetworkChangeNotifier::CONNECTION_NONE:
103 case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
104 return SystemProfileProto::Network::CONNECTION_UNKNOWN;
105 case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
106 return SystemProfileProto::Network::CONNECTION_ETHERNET;
107 case net::NetworkChangeNotifier::CONNECTION_WIFI:
108 return SystemProfileProto::Network::CONNECTION_WIFI;
109 case net::NetworkChangeNotifier::CONNECTION_2G:
110 return SystemProfileProto::Network::CONNECTION_2G;
111 case net::NetworkChangeNotifier::CONNECTION_3G:
112 return SystemProfileProto::Network::CONNECTION_3G;
113 case net::NetworkChangeNotifier::CONNECTION_4G:
114 return SystemProfileProto::Network::CONNECTION_4G;
115 case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH:
116 return SystemProfileProto::Network::CONNECTION_BLUETOOTH;
118 NOTREACHED();
119 return SystemProfileProto::Network::CONNECTION_UNKNOWN;
122 SystemProfileProto::Network::WifiPHYLayerProtocol
123 NetworkMetricsProvider::GetWifiPHYLayerProtocol() const {
124 switch (wifi_phy_layer_protocol_) {
125 case net::WIFI_PHY_LAYER_PROTOCOL_NONE:
126 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_NONE;
127 case net::WIFI_PHY_LAYER_PROTOCOL_ANCIENT:
128 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_ANCIENT;
129 case net::WIFI_PHY_LAYER_PROTOCOL_A:
130 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_A;
131 case net::WIFI_PHY_LAYER_PROTOCOL_B:
132 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_B;
133 case net::WIFI_PHY_LAYER_PROTOCOL_G:
134 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_G;
135 case net::WIFI_PHY_LAYER_PROTOCOL_N:
136 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_N;
137 case net::WIFI_PHY_LAYER_PROTOCOL_UNKNOWN:
138 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_UNKNOWN;
140 NOTREACHED();
141 return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_UNKNOWN;
144 void NetworkMetricsProvider::ProbeWifiPHYLayerProtocol() {
145 PostTaskAndReplyWithResult(
146 io_task_runner_,
147 FROM_HERE,
148 base::Bind(&net::GetWifiPHYLayerProtocol),
149 base::Bind(&NetworkMetricsProvider::OnWifiPHYLayerProtocolResult,
150 weak_ptr_factory_.GetWeakPtr()));
153 void NetworkMetricsProvider::OnWifiPHYLayerProtocolResult(
154 net::WifiPHYLayerProtocol mode) {
155 if (wifi_phy_layer_protocol_ != net::WIFI_PHY_LAYER_PROTOCOL_UNKNOWN &&
156 mode != wifi_phy_layer_protocol_) {
157 wifi_phy_layer_protocol_is_ambiguous_ = true;
159 wifi_phy_layer_protocol_ = mode;
162 void NetworkMetricsProvider::WriteWifiAccessPointProto(
163 const WifiAccessPointInfoProvider::WifiAccessPointInfo& info,
164 SystemProfileProto::Network* network_proto) {
165 SystemProfileProto::Network::WifiAccessPoint* access_point_info =
166 network_proto->mutable_access_point_info();
167 SystemProfileProto::Network::WifiAccessPoint::SecurityMode security =
168 SystemProfileProto::Network::WifiAccessPoint::SECURITY_UNKNOWN;
169 switch (info.security) {
170 case WifiAccessPointInfoProvider::WIFI_SECURITY_NONE:
171 security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_NONE;
172 break;
173 case WifiAccessPointInfoProvider::WIFI_SECURITY_WPA:
174 security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_WPA;
175 break;
176 case WifiAccessPointInfoProvider::WIFI_SECURITY_WEP:
177 security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_WEP;
178 break;
179 case WifiAccessPointInfoProvider::WIFI_SECURITY_RSN:
180 security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_RSN;
181 break;
182 case WifiAccessPointInfoProvider::WIFI_SECURITY_802_1X:
183 security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_802_1X;
184 break;
185 case WifiAccessPointInfoProvider::WIFI_SECURITY_PSK:
186 security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_PSK;
187 break;
188 case WifiAccessPointInfoProvider::WIFI_SECURITY_UNKNOWN:
189 security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_UNKNOWN;
190 break;
192 access_point_info->set_security_mode(security);
194 // |bssid| is xx:xx:xx:xx:xx:xx, extract the first three components and
195 // pack into a uint32.
196 std::string bssid = info.bssid;
197 if (bssid.size() == 17 && bssid[2] == ':' && bssid[5] == ':' &&
198 bssid[8] == ':' && bssid[11] == ':' && bssid[14] == ':') {
199 std::string vendor_prefix_str;
200 uint32 vendor_prefix;
202 base::RemoveChars(bssid.substr(0, 9), ":", &vendor_prefix_str);
203 DCHECK_EQ(6U, vendor_prefix_str.size());
204 if (base::HexStringToUInt(vendor_prefix_str, &vendor_prefix))
205 access_point_info->set_vendor_prefix(vendor_prefix);
206 else
207 NOTREACHED();
210 // Return if vendor information is not provided.
211 if (info.model_number.empty() && info.model_name.empty() &&
212 info.device_name.empty() && info.oui_list.empty())
213 return;
215 SystemProfileProto::Network::WifiAccessPoint::VendorInformation* vendor =
216 access_point_info->mutable_vendor_info();
217 if (!info.model_number.empty())
218 vendor->set_model_number(info.model_number);
219 if (!info.model_name.empty())
220 vendor->set_model_name(info.model_name);
221 if (!info.device_name.empty())
222 vendor->set_device_name(info.device_name);
224 // Return if OUI list is not provided.
225 if (info.oui_list.empty())
226 return;
228 // Parse OUI list.
229 std::vector<std::string> oui_list;
230 base::SplitString(info.oui_list, ' ', &oui_list);
231 for (std::vector<std::string>::const_iterator it = oui_list.begin();
232 it != oui_list.end();
233 ++it) {
234 uint32 oui;
235 if (base::HexStringToUInt(*it, &oui))
236 vendor->add_element_identifier(oui);
237 else
238 NOTREACHED();
242 } // namespace metrics