Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / components / metrics / net / network_metrics_provider.cc
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.
4
5 #include "components/metrics/net/network_metrics_provider.h"
6
7 #include <string>
8 #include <vector>
9
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"
15
16 #if defined(OS_CHROMEOS)
17 #include "components/metrics/net/wifi_access_point_info_provider_chromeos.h"
18 #endif // OS_CHROMEOS
19
20 using metrics::SystemProfileProto;
21
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();
32 }
33
34 NetworkMetricsProvider::~NetworkMetricsProvider() {
35   net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
36 }
37
38 void NetworkMetricsProvider::OnDidCreateMetricsLog() {
39   net::NetworkChangeNotifier::LogOperatorCodeHistogram(
40       net::NetworkChangeNotifier::GetConnectionType());
41 }
42
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());
51
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;
57
58   if (!wifi_access_point_info_provider_.get()) {
59 #if defined(OS_CHROMEOS)
60     wifi_access_point_info_provider_.reset(
61         new WifiAccessPointInfoProviderChromeos());
62 #else
63     wifi_access_point_info_provider_.reset(
64         new WifiAccessPointInfoProvider());
65 #endif // OS_CHROMEOS
66   }
67
68   // Connected wifi access point information.
69   WifiAccessPointInfoProvider::WifiAccessPointInfo info;
70   if (wifi_access_point_info_provider_->GetInfo(&info))
71     WriteWifiAccessPointProto(info, network);
72 }
73
74 void NetworkMetricsProvider::OnConnectionTypeChanged(
75     net::NetworkChangeNotifier::ConnectionType type) {
76   if (type == net::NetworkChangeNotifier::CONNECTION_NONE)
77     return;
78   if (type != connection_type_ &&
79       connection_type_ != net::NetworkChangeNotifier::CONNECTION_NONE) {
80     connection_type_is_ambiguous_ = true;
81   }
82   connection_type_ = type;
83
84   ProbeWifiPHYLayerProtocol();
85 }
86
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;
105   }
106   NOTREACHED();
107   return SystemProfileProto::Network::CONNECTION_UNKNOWN;
108 }
109
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;
127   }
128   NOTREACHED();
129   return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_UNKNOWN;
130 }
131
132 void NetworkMetricsProvider::ProbeWifiPHYLayerProtocol() {
133   PostTaskAndReplyWithResult(
134       io_task_runner_,
135       FROM_HERE,
136       base::Bind(&net::GetWifiPHYLayerProtocol),
137       base::Bind(&NetworkMetricsProvider::OnWifiPHYLayerProtocolResult,
138                  weak_ptr_factory_.GetWeakPtr()));
139 }
140
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;
146   }
147   wifi_phy_layer_protocol_ = mode;
148 }
149
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;
160       break;
161     case WifiAccessPointInfoProvider::WIFI_SECURITY_WPA:
162       security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_WPA;
163       break;
164     case WifiAccessPointInfoProvider::WIFI_SECURITY_WEP:
165       security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_WEP;
166       break;
167     case WifiAccessPointInfoProvider::WIFI_SECURITY_RSN:
168       security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_RSN;
169       break;
170     case WifiAccessPointInfoProvider::WIFI_SECURITY_802_1X:
171       security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_802_1X;
172       break;
173     case WifiAccessPointInfoProvider::WIFI_SECURITY_PSK:
174       security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_PSK;
175       break;
176     case WifiAccessPointInfoProvider::WIFI_SECURITY_UNKNOWN:
177       security = SystemProfileProto::Network::WifiAccessPoint::SECURITY_UNKNOWN;
178       break;
179   }
180   access_point_info->set_security_mode(security);
181
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;
189
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);
194     else
195       NOTREACHED();
196   }
197
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())
201     return;
202
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);
211
212   // Return if OUI list is not provided.
213   if (info.oui_list.empty())
214     return;
215
216   // Parse OUI list.
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();
221        ++it) {
222     uint32 oui;
223     if (base::HexStringToUInt(*it, &oui))
224       vendor->add_element_identifier(oui);
225     else
226       NOTREACHED();
227   }
228 }