Don't add an aura tooltip to bubble close buttons on Windows.
[chromium-blink-merge.git] / net / base / net_util_win.cc
blob5cd4a42daf85853e0021320772ae5b8df07192a9
1 // Copyright (c) 2012 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 "net/base/net_util.h"
7 #include <iphlpapi.h>
8 #include <wlanapi.h>
10 #include <algorithm>
12 #include "base/files/file_path.h"
13 #include "base/lazy_instance.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/profiler/scoped_tracker.h"
16 #include "base/strings/string_piece.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/sys_string_conversions.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/threading/thread_restrictions.h"
21 #include "base/win/scoped_handle.h"
22 #include "base/win/windows_version.h"
23 #include "net/base/escape.h"
24 #include "net/base/ip_endpoint.h"
25 #include "net/base/net_errors.h"
26 #include "net/base/net_util_win.h"
27 #include "url/gurl.h"
29 namespace net {
31 namespace {
33 // Converts Windows defined types to NetworkInterfaceType.
34 NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType(DWORD ifType) {
35 // Bail out for pre-Vista versions of Windows which are documented to give
36 // inaccurate results like returning Ethernet for WiFi.
37 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa366058.aspx
38 if (base::win::GetVersion() < base::win::VERSION_VISTA)
39 return NetworkChangeNotifier::CONNECTION_UNKNOWN;
41 NetworkChangeNotifier::ConnectionType type =
42 NetworkChangeNotifier::CONNECTION_UNKNOWN;
43 if (ifType == IF_TYPE_ETHERNET_CSMACD) {
44 type = NetworkChangeNotifier::CONNECTION_ETHERNET;
45 } else if (ifType == IF_TYPE_IEEE80211) {
46 type = NetworkChangeNotifier::CONNECTION_WIFI;
48 // TODO(mallinath) - Cellular?
49 return type;
52 } // namespace
54 namespace internal {
56 base::LazyInstance<WlanApi>::Leaky lazy_wlanapi =
57 LAZY_INSTANCE_INITIALIZER;
59 WlanApi& WlanApi::GetInstance() {
60 return lazy_wlanapi.Get();
63 WlanApi::WlanApi() : initialized(false) {
64 // Use an absolute path to load the DLL to avoid DLL preloading attacks.
65 static const wchar_t* const kDLL = L"%WINDIR%\\system32\\wlanapi.dll";
66 wchar_t path[MAX_PATH] = {0};
67 ExpandEnvironmentStrings(kDLL, path, arraysize(path));
68 module = ::LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
69 if (!module)
70 return;
72 open_handle_func = reinterpret_cast<WlanOpenHandleFunc>(
73 ::GetProcAddress(module, "WlanOpenHandle"));
74 enum_interfaces_func = reinterpret_cast<WlanEnumInterfacesFunc>(
75 ::GetProcAddress(module, "WlanEnumInterfaces"));
76 query_interface_func = reinterpret_cast<WlanQueryInterfaceFunc>(
77 ::GetProcAddress(module, "WlanQueryInterface"));
78 set_interface_func = reinterpret_cast<WlanSetInterfaceFunc>(
79 ::GetProcAddress(module, "WlanSetInterface"));
80 free_memory_func = reinterpret_cast<WlanFreeMemoryFunc>(
81 ::GetProcAddress(module, "WlanFreeMemory"));
82 close_handle_func = reinterpret_cast<WlanCloseHandleFunc>(
83 ::GetProcAddress(module, "WlanCloseHandle"));
84 initialized = open_handle_func && enum_interfaces_func &&
85 query_interface_func && set_interface_func &&
86 free_memory_func && close_handle_func;
89 bool GetNetworkListImpl(NetworkInterfaceList* networks,
90 int policy,
91 bool is_xp,
92 const IP_ADAPTER_ADDRESSES* adapters) {
93 for (const IP_ADAPTER_ADDRESSES* adapter = adapters; adapter != NULL;
94 adapter = adapter->Next) {
95 // Ignore the loopback device.
96 if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) {
97 continue;
100 if (adapter->OperStatus != IfOperStatusUp) {
101 continue;
104 // Ignore any HOST side vmware adapters with a description like:
105 // VMware Virtual Ethernet Adapter for VMnet1
106 // but don't ignore any GUEST side adapters with a description like:
107 // VMware Accelerated AMD PCNet Adapter #2
108 if ((policy & EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES) &&
109 strstr(adapter->AdapterName, "VMnet") != NULL) {
110 continue;
113 for (IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress;
114 address; address = address->Next) {
115 int family = address->Address.lpSockaddr->sa_family;
116 if (family == AF_INET || family == AF_INET6) {
117 IPEndPoint endpoint;
118 if (endpoint.FromSockAddr(address->Address.lpSockaddr,
119 address->Address.iSockaddrLength)) {
120 // XP has no OnLinkPrefixLength field.
121 size_t prefix_length = is_xp ? 0 : address->OnLinkPrefixLength;
122 if (is_xp) {
123 // Prior to Windows Vista the FirstPrefix pointed to the list with
124 // single prefix for each IP address assigned to the adapter.
125 // Order of FirstPrefix does not match order of FirstUnicastAddress,
126 // so we need to find corresponding prefix.
127 for (IP_ADAPTER_PREFIX* prefix = adapter->FirstPrefix; prefix;
128 prefix = prefix->Next) {
129 int prefix_family = prefix->Address.lpSockaddr->sa_family;
130 IPEndPoint network_endpoint;
131 if (prefix_family == family &&
132 network_endpoint.FromSockAddr(prefix->Address.lpSockaddr,
133 prefix->Address.iSockaddrLength) &&
134 IPNumberMatchesPrefix(endpoint.address(),
135 network_endpoint.address(),
136 prefix->PrefixLength)) {
137 prefix_length =
138 std::max<size_t>(prefix_length, prefix->PrefixLength);
143 // If the duplicate address detection (DAD) state is not changed to
144 // Preferred, skip this address.
145 if (address->DadState != IpDadStatePreferred) {
146 continue;
149 uint32 index =
150 (family == AF_INET) ? adapter->IfIndex : adapter->Ipv6IfIndex;
152 // From http://technet.microsoft.com/en-us/ff568768(v=vs.60).aspx, the
153 // way to identify a temporary IPv6 Address is to check if
154 // PrefixOrigin is equal to IpPrefixOriginRouterAdvertisement and
155 // SuffixOrigin equal to IpSuffixOriginRandom.
156 int ip_address_attributes = IP_ADDRESS_ATTRIBUTE_NONE;
157 if (family == AF_INET6) {
158 if (address->PrefixOrigin == IpPrefixOriginRouterAdvertisement &&
159 address->SuffixOrigin == IpSuffixOriginRandom) {
160 ip_address_attributes |= IP_ADDRESS_ATTRIBUTE_TEMPORARY;
162 if (address->PreferredLifetime == 0) {
163 ip_address_attributes |= IP_ADDRESS_ATTRIBUTE_DEPRECATED;
166 networks->push_back(NetworkInterface(
167 adapter->AdapterName,
168 base::SysWideToNativeMB(adapter->FriendlyName), index,
169 GetNetworkInterfaceType(adapter->IfType), endpoint.address(),
170 prefix_length, ip_address_attributes));
175 return true;
178 } // namespace internal
180 bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
181 bool is_xp = base::win::GetVersion() < base::win::VERSION_VISTA;
182 ULONG len = 0;
183 ULONG flags = is_xp ? GAA_FLAG_INCLUDE_PREFIX : 0;
184 // GetAdaptersAddresses() may require IO operations.
185 base::ThreadRestrictions::AssertIOAllowed();
186 ULONG result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &len);
187 if (result != ERROR_BUFFER_OVERFLOW) {
188 // There are 0 networks.
189 return true;
191 scoped_ptr<char[]> buf(new char[len]);
192 IP_ADAPTER_ADDRESSES* adapters =
193 reinterpret_cast<IP_ADAPTER_ADDRESSES*>(buf.get());
194 result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapters, &len);
195 if (result != NO_ERROR) {
196 LOG(ERROR) << "GetAdaptersAddresses failed: " << result;
197 return false;
200 return internal::GetNetworkListImpl(networks, policy, is_xp, adapters);
203 WifiPHYLayerProtocol GetWifiPHYLayerProtocol() {
204 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
205 tracked_objects::ScopedTracker tracking_profile1(
206 FROM_HERE_WITH_EXPLICIT_FUNCTION(
207 "422516 net_util_win::GetWifiPHYLayerProtocol1"));
208 const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance();
209 if (!wlanapi.initialized)
210 return WIFI_PHY_LAYER_PROTOCOL_NONE;
212 internal::WlanHandle client;
213 DWORD cur_version = 0;
214 const DWORD kMaxClientVersion = 2;
215 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
216 tracked_objects::ScopedTracker tracking_profile2(
217 FROM_HERE_WITH_EXPLICIT_FUNCTION(
218 "422516 net_util_win::GetWifiPHYLayerProtocol2"));
219 DWORD result = wlanapi.OpenHandle(kMaxClientVersion, &cur_version, &client);
220 if (result != ERROR_SUCCESS)
221 return WIFI_PHY_LAYER_PROTOCOL_NONE;
223 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
224 tracked_objects::ScopedTracker tracking_profile3(
225 FROM_HERE_WITH_EXPLICIT_FUNCTION(
226 "422516 net_util_win::GetWifiPHYLayerProtocol3"));
227 WLAN_INTERFACE_INFO_LIST* interface_list_ptr = NULL;
228 result = wlanapi.enum_interfaces_func(client.Get(), NULL,
229 &interface_list_ptr);
230 if (result != ERROR_SUCCESS)
231 return WIFI_PHY_LAYER_PROTOCOL_NONE;
232 scoped_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter> interface_list(
233 interface_list_ptr);
235 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
236 tracked_objects::ScopedTracker tracking_profile4(
237 FROM_HERE_WITH_EXPLICIT_FUNCTION(
238 "422516 net_util_win::GetWifiPHYLayerProtocol4"));
239 // Assume at most one connected wifi interface.
240 WLAN_INTERFACE_INFO* info = NULL;
241 for (unsigned i = 0; i < interface_list->dwNumberOfItems; ++i) {
242 if (interface_list->InterfaceInfo[i].isState ==
243 wlan_interface_state_connected) {
244 info = &interface_list->InterfaceInfo[i];
245 break;
249 if (info == NULL)
250 return WIFI_PHY_LAYER_PROTOCOL_NONE;
252 WLAN_CONNECTION_ATTRIBUTES* conn_info_ptr;
253 DWORD conn_info_size = 0;
254 WLAN_OPCODE_VALUE_TYPE op_code;
255 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
256 tracked_objects::ScopedTracker tracking_profile5(
257 FROM_HERE_WITH_EXPLICIT_FUNCTION(
258 "422516 net_util_win::GetWifiPHYLayerProtocol5"));
259 result = wlanapi.query_interface_func(
260 client.Get(), &info->InterfaceGuid, wlan_intf_opcode_current_connection,
261 NULL, &conn_info_size, reinterpret_cast<VOID**>(&conn_info_ptr),
262 &op_code);
263 if (result != ERROR_SUCCESS)
264 return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN;
265 scoped_ptr<WLAN_CONNECTION_ATTRIBUTES, internal::WlanApiDeleter> conn_info(
266 conn_info_ptr);
268 switch (conn_info->wlanAssociationAttributes.dot11PhyType) {
269 case dot11_phy_type_fhss:
270 return WIFI_PHY_LAYER_PROTOCOL_ANCIENT;
271 case dot11_phy_type_dsss:
272 return WIFI_PHY_LAYER_PROTOCOL_B;
273 case dot11_phy_type_irbaseband:
274 return WIFI_PHY_LAYER_PROTOCOL_ANCIENT;
275 case dot11_phy_type_ofdm:
276 return WIFI_PHY_LAYER_PROTOCOL_A;
277 case dot11_phy_type_hrdsss:
278 return WIFI_PHY_LAYER_PROTOCOL_B;
279 case dot11_phy_type_erp:
280 return WIFI_PHY_LAYER_PROTOCOL_G;
281 case dot11_phy_type_ht:
282 return WIFI_PHY_LAYER_PROTOCOL_N;
283 default:
284 return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN;
288 // Note: There is no need to explicitly set the options back
289 // as the OS will automatically set them back when the WlanHandle
290 // is closed.
291 class WifiOptionSetter : public ScopedWifiOptions {
292 public:
293 WifiOptionSetter(int options) {
294 const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance();
295 if (!wlanapi.initialized)
296 return;
298 DWORD cur_version = 0;
299 const DWORD kMaxClientVersion = 2;
300 DWORD result = wlanapi.OpenHandle(
301 kMaxClientVersion, &cur_version, &client_);
302 if (result != ERROR_SUCCESS)
303 return;
305 WLAN_INTERFACE_INFO_LIST* interface_list_ptr = NULL;
306 result = wlanapi.enum_interfaces_func(client_.Get(), NULL,
307 &interface_list_ptr);
308 if (result != ERROR_SUCCESS)
309 return;
310 scoped_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter>
311 interface_list(interface_list_ptr);
313 for (unsigned i = 0; i < interface_list->dwNumberOfItems; ++i) {
314 WLAN_INTERFACE_INFO* info = &interface_list->InterfaceInfo[i];
315 if (options & WIFI_OPTIONS_DISABLE_SCAN) {
316 BOOL data = false;
317 wlanapi.set_interface_func(client_.Get(),
318 &info->InterfaceGuid,
319 wlan_intf_opcode_background_scan_enabled,
320 sizeof(data),
321 &data,
322 NULL);
324 if (options & WIFI_OPTIONS_MEDIA_STREAMING_MODE) {
325 BOOL data = true;
326 wlanapi.set_interface_func(client_.Get(),
327 &info->InterfaceGuid,
328 wlan_intf_opcode_media_streaming_mode,
329 sizeof(data),
330 &data,
331 NULL);
336 private:
337 internal::WlanHandle client_;
340 scoped_ptr<ScopedWifiOptions> SetWifiOptions(int options) {
341 return scoped_ptr<ScopedWifiOptions>(new WifiOptionSetter(options));
344 std::string GetWifiSSID() {
345 NOTIMPLEMENTED();
346 return "";
349 } // namespace net