diff options
author | hubbe <hubbe@chromium.org> | 2014-09-23 14:25:54 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-23 21:26:08 +0000 |
commit | 693959c4726d968b0396345918a84bc284aea510 (patch) | |
tree | b208ed5c122104e704c4253629098f4e3d6bffb9 /net | |
parent | 37c078080a860d121443e657eb4089b784469162 (diff) | |
download | chromium_src-693959c4726d968b0396345918a84bc284aea510.zip chromium_src-693959c4726d968b0396345918a84bc284aea510.tar.gz chromium_src-693959c4726d968b0396345918a84bc284aea510.tar.bz2 |
Cast: Allow extension to control wifi options on windows
This allows the cast extension to turn off wifi scan while
streaming is in progress, and also set the "media streaming mode"
further experimentation is need to see if these options are actually
useful.
BUG=410500
Review URL: https://codereview.chromium.org/566243005
Cr-Commit-Position: refs/heads/master@{#296253}
Diffstat (limited to 'net')
-rw-r--r-- | net/base/net_util.cc | 3 | ||||
-rw-r--r-- | net/base/net_util.h | 22 | ||||
-rw-r--r-- | net/base/net_util_posix.cc | 6 | ||||
-rw-r--r-- | net/base/net_util_unittest.cc | 109 | ||||
-rw-r--r-- | net/base/net_util_win.cc | 184 | ||||
-rw-r--r-- | net/base/net_util_win.h | 85 |
6 files changed, 322 insertions, 87 deletions
diff --git a/net/base/net_util.cc b/net/base/net_util.cc index 559f887..704add2 100644 --- a/net/base/net_util.cc +++ b/net/base/net_util.cc @@ -1040,4 +1040,7 @@ unsigned MaskPrefixLength(const IPAddressNumber& mask) { return CommonPrefixLength(mask, all_ones); } +ScopedWifiOptions::~ScopedWifiOptions() { +} + } // namespace net diff --git a/net/base/net_util.h b/net/base/net_util.h index 5999ad2..49780e8 100644 --- a/net/base/net_util.h +++ b/net/base/net_util.h @@ -518,6 +518,28 @@ enum WifiPHYLayerProtocol { // Currently only available on OS_WIN. NET_EXPORT WifiPHYLayerProtocol GetWifiPHYLayerProtocol(); +enum WifiOptions { + // Disables background SSID scans. + WIFI_OPTIONS_DISABLE_SCAN = 1 << 0, + // Enables media streaming mode. + WIFI_OPTIONS_MEDIA_STREAMING_MODE = 1 << 1 +}; + +class NET_EXPORT ScopedWifiOptions { + public: + ScopedWifiOptions() {} + virtual ~ScopedWifiOptions(); + + private: + DISALLOW_COPY_AND_ASSIGN(ScopedWifiOptions); +}; + +// Set temporary options on all wifi interfaces. +// |options| is an ORed bitfield of WifiOptions. +// Options are automatically disabled when the scoped pointer +// is freed. Currently only available on OS_WIN. +NET_EXPORT scoped_ptr<ScopedWifiOptions> SetWifiOptions(int options); + // Returns number of matching initial bits between the addresses |a1| and |a2|. unsigned CommonPrefixLength(const IPAddressNumber& a1, const IPAddressNumber& a2); diff --git a/net/base/net_util_posix.cc b/net/base/net_util_posix.cc index 7f88ef6..73704cd 100644 --- a/net/base/net_util_posix.cc +++ b/net/base/net_util_posix.cc @@ -9,6 +9,7 @@ #include "base/files/file_path.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" @@ -284,4 +285,9 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN; } +scoped_ptr<ScopedWifiOptions> SetWifiOptions(int options) { + return scoped_ptr<ScopedWifiOptions>(); +} + + } // namespace net diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc index 8306db5..3bb518f 100644 --- a/net/base/net_util_unittest.cc +++ b/net/base/net_util_unittest.cc @@ -24,6 +24,7 @@ #include <iphlpapi.h> #include <objbase.h> #include "base/win/windows_version.h" +#include "net/base/net_util_win.h" #elif !defined(OS_ANDROID) #include <net/if.h> #endif // OS_WIN @@ -790,6 +791,114 @@ TEST(NetUtilTest, GetNetworkList) { } } +namespace { + +#if defined(OS_WIN) +bool read_int_or_bool(DWORD data_size, + PVOID data) { + switch (data_size) { + case 1: + return !!*reinterpret_cast<uint8*>(data); + case 4: + return !!*reinterpret_cast<uint32*>(data); + default: + LOG(FATAL) << "That is not a type I know!"; + return false; + } +} + +int GetWifiOptions() { + const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance(); + if (!wlanapi.initialized) + return -1; + + internal::WlanHandle client; + DWORD cur_version = 0; + const DWORD kMaxClientVersion = 2; + DWORD result = wlanapi.OpenHandle( + kMaxClientVersion, &cur_version, &client); + if (result != ERROR_SUCCESS) + return -1; + + WLAN_INTERFACE_INFO_LIST* interface_list_ptr = NULL; + result = wlanapi.enum_interfaces_func(client, NULL, &interface_list_ptr); + if (result != ERROR_SUCCESS) + return -1; + scoped_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter> interface_list( + interface_list_ptr); + + for (unsigned i = 0; i < interface_list->dwNumberOfItems; ++i) { + WLAN_INTERFACE_INFO* info = &interface_list->InterfaceInfo[i]; + DWORD data_size; + PVOID data; + int options = 0; + result = wlanapi.query_interface_func( + client, + &info->InterfaceGuid, + wlan_intf_opcode_background_scan_enabled, + NULL, + &data_size, + &data, + NULL); + if (result != ERROR_SUCCESS) + continue; + if (!read_int_or_bool(data_size, data)) { + options |= WIFI_OPTIONS_DISABLE_SCAN; + } + internal::WlanApi::GetInstance().free_memory_func(data); + + result = wlanapi.query_interface_func( + client, + &info->InterfaceGuid, + wlan_intf_opcode_media_streaming_mode, + NULL, + &data_size, + &data, + NULL); + if (result != ERROR_SUCCESS) + continue; + if (read_int_or_bool(data_size, data)) { + options |= WIFI_OPTIONS_MEDIA_STREAMING_MODE; + } + internal::WlanApi::GetInstance().free_memory_func(data); + + // Just the the options from the first succesful + // interface. + return options; + } + + // No wifi interface found. + return -1; +} + +#else // OS_WIN + +int GetWifiOptions() { + // Not supported. + return -1; +} + +#endif // OS_WIN + +void TryChangeWifiOptions(int options) { + int previous_options = GetWifiOptions(); + scoped_ptr<ScopedWifiOptions> scoped_options = SetWifiOptions(options); + EXPECT_EQ(previous_options | options, GetWifiOptions()); + scoped_options.reset(); + EXPECT_EQ(previous_options, GetWifiOptions()); +} + +}; // namespace + +// Test SetWifiOptions(). +TEST(NetUtilTest, SetWifiOptionsTest) { + TryChangeWifiOptions(0); + TryChangeWifiOptions(WIFI_OPTIONS_DISABLE_SCAN); + TryChangeWifiOptions(WIFI_OPTIONS_MEDIA_STREAMING_MODE); + TryChangeWifiOptions(WIFI_OPTIONS_DISABLE_SCAN | + WIFI_OPTIONS_MEDIA_STREAMING_MODE); +} + struct NonUniqueNameTestData { bool is_unique; const char* hostname; diff --git a/net/base/net_util_win.cc b/net/base/net_util_win.cc index 6f331ec..4f59d6d 100644 --- a/net/base/net_util_win.cc +++ b/net/base/net_util_win.cc @@ -22,67 +22,13 @@ #include "net/base/escape.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" +#include "net/base/net_util_win.h" #include "url/gurl.h" namespace net { namespace { -struct WlanApi { - typedef DWORD (WINAPI *WlanOpenHandleFunc)( - DWORD, VOID*, DWORD*, HANDLE*); - typedef DWORD (WINAPI *WlanEnumInterfacesFunc)( - HANDLE, VOID*, WLAN_INTERFACE_INFO_LIST**); - typedef DWORD (WINAPI *WlanQueryInterfaceFunc)( - HANDLE, const GUID*, WLAN_INTF_OPCODE, VOID*, DWORD*, VOID**, - WLAN_OPCODE_VALUE_TYPE*); - typedef VOID (WINAPI *WlanFreeMemoryFunc)(VOID*); - typedef DWORD (WINAPI *WlanCloseHandleFunc)(HANDLE, VOID*); - - WlanApi() : initialized(false) { - // Use an absolute path to load the DLL to avoid DLL preloading attacks. - static const wchar_t* const kDLL = L"%WINDIR%\\system32\\wlanapi.dll"; - wchar_t path[MAX_PATH] = {0}; - ExpandEnvironmentStrings(kDLL, path, arraysize(path)); - module = ::LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - if (!module) - return; - - open_handle_func = reinterpret_cast<WlanOpenHandleFunc>( - ::GetProcAddress(module, "WlanOpenHandle")); - enum_interfaces_func = reinterpret_cast<WlanEnumInterfacesFunc>( - ::GetProcAddress(module, "WlanEnumInterfaces")); - query_interface_func = reinterpret_cast<WlanQueryInterfaceFunc>( - ::GetProcAddress(module, "WlanQueryInterface")); - free_memory_func = reinterpret_cast<WlanFreeMemoryFunc>( - ::GetProcAddress(module, "WlanFreeMemory")); - close_handle_func = reinterpret_cast<WlanCloseHandleFunc>( - ::GetProcAddress(module, "WlanCloseHandle")); - initialized = open_handle_func && enum_interfaces_func && - query_interface_func && free_memory_func && - close_handle_func; - } - - template <typename T> - DWORD OpenHandle(DWORD client_version, DWORD* cur_version, T* handle) const { - HANDLE temp_handle; - DWORD result = open_handle_func(client_version, NULL, cur_version, - &temp_handle); - if (result != ERROR_SUCCESS) - return result; - handle->Set(temp_handle); - return ERROR_SUCCESS; - } - - HMODULE module; - WlanOpenHandleFunc open_handle_func; - WlanEnumInterfacesFunc enum_interfaces_func; - WlanQueryInterfaceFunc query_interface_func; - WlanFreeMemoryFunc free_memory_func; - WlanCloseHandleFunc close_handle_func; - bool initialized; -}; - // Converts Windows defined types to NetworkInterfaceType. NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType(DWORD ifType) { // Bail out for pre-Vista versions of Windows which are documented to give @@ -104,6 +50,43 @@ NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType(DWORD ifType) { } // namespace +namespace internal { + +base::LazyInstance<WlanApi>::Leaky lazy_wlanapi = + LAZY_INSTANCE_INITIALIZER; + +WlanApi& WlanApi::GetInstance() { + return lazy_wlanapi.Get(); +} + +WlanApi::WlanApi() : initialized(false) { + // Use an absolute path to load the DLL to avoid DLL preloading attacks. + static const wchar_t* const kDLL = L"%WINDIR%\\system32\\wlanapi.dll"; + wchar_t path[MAX_PATH] = {0}; + ExpandEnvironmentStrings(kDLL, path, arraysize(path)); + module = ::LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!module) + return; + + open_handle_func = reinterpret_cast<WlanOpenHandleFunc>( + ::GetProcAddress(module, "WlanOpenHandle")); + enum_interfaces_func = reinterpret_cast<WlanEnumInterfacesFunc>( + ::GetProcAddress(module, "WlanEnumInterfaces")); + query_interface_func = reinterpret_cast<WlanQueryInterfaceFunc>( + ::GetProcAddress(module, "WlanQueryInterface")); + set_interface_func = reinterpret_cast<WlanSetInterfaceFunc>( + ::GetProcAddress(module, "WlanSetInterface")); + free_memory_func = reinterpret_cast<WlanFreeMemoryFunc>( + ::GetProcAddress(module, "WlanFreeMemory")); + close_handle_func = reinterpret_cast<WlanCloseHandleFunc>( + ::GetProcAddress(module, "WlanCloseHandle")); + initialized = open_handle_func && enum_interfaces_func && + query_interface_func && set_interface_func && + free_memory_func && close_handle_func; +} + +} // namespace internal + bool GetNetworkList(NetworkInterfaceList* networks, int policy) { // GetAdaptersAddresses() may require IO operations. base::ThreadRestrictions::AssertIOAllowed(); @@ -221,39 +204,11 @@ bool GetNetworkList(NetworkInterfaceList* networks, int policy) { } WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { - static base::LazyInstance<WlanApi>::Leaky lazy_wlanapi = - LAZY_INSTANCE_INITIALIZER; - - struct WlanApiHandleTraits { - typedef HANDLE Handle; - - static bool CloseHandle(HANDLE handle) { - return lazy_wlanapi.Get().close_handle_func(handle, NULL) == - ERROR_SUCCESS; - } - static bool IsHandleValid(HANDLE handle) { - return base::win::HandleTraits::IsHandleValid(handle); - } - static HANDLE NullHandle() { - return base::win::HandleTraits::NullHandle(); - } - }; - - typedef base::win::GenericScopedHandle< - WlanApiHandleTraits, - base::win::DummyVerifierTraits> WlanHandle; - - struct WlanApiDeleter { - inline void operator()(void* ptr) const { - lazy_wlanapi.Get().free_memory_func(ptr); - } - }; - - const WlanApi& wlanapi = lazy_wlanapi.Get(); + const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance(); if (!wlanapi.initialized) return WIFI_PHY_LAYER_PROTOCOL_NONE; - WlanHandle client; + internal::WlanHandle client; DWORD cur_version = 0; const DWORD kMaxClientVersion = 2; DWORD result = wlanapi.OpenHandle(kMaxClientVersion, &cur_version, &client); @@ -264,7 +219,7 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { result = wlanapi.enum_interfaces_func(client, NULL, &interface_list_ptr); if (result != ERROR_SUCCESS) return WIFI_PHY_LAYER_PROTOCOL_NONE; - scoped_ptr<WLAN_INTERFACE_INFO_LIST, WlanApiDeleter> interface_list( + scoped_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter> interface_list( interface_list_ptr); // Assume at most one connected wifi interface. @@ -288,7 +243,7 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { &conn_info_size, reinterpret_cast<VOID**>(&conn_info_ptr), &op_code); if (result != ERROR_SUCCESS) return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN; - scoped_ptr<WLAN_CONNECTION_ATTRIBUTES, WlanApiDeleter> conn_info( + scoped_ptr<WLAN_CONNECTION_ATTRIBUTES, internal::WlanApiDeleter> conn_info( conn_info_ptr); switch (conn_info->wlanAssociationAttributes.dot11PhyType) { @@ -311,4 +266,59 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { } } +// Note: There is no need to explicitly set the options back +// as the OS will automatically set them back when the WlanHandle +// is closed. +class WifiOptionSetter : public ScopedWifiOptions { + public: + WifiOptionSetter(int options) { + const internal::WlanApi& wlanapi = internal::WlanApi::GetInstance(); + if (!wlanapi.initialized) + return; + + DWORD cur_version = 0; + const DWORD kMaxClientVersion = 2; + DWORD result = wlanapi.OpenHandle( + kMaxClientVersion, &cur_version, &client_); + if (result != ERROR_SUCCESS) + return; + + WLAN_INTERFACE_INFO_LIST* interface_list_ptr = NULL; + result = wlanapi.enum_interfaces_func(client_, NULL, &interface_list_ptr); + if (result != ERROR_SUCCESS) + return; + scoped_ptr<WLAN_INTERFACE_INFO_LIST, internal::WlanApiDeleter> + interface_list(interface_list_ptr); + + for (unsigned i = 0; i < interface_list->dwNumberOfItems; ++i) { + WLAN_INTERFACE_INFO* info = &interface_list->InterfaceInfo[i]; + if (options & WIFI_OPTIONS_DISABLE_SCAN) { + BOOL data = false; + wlanapi.set_interface_func(client_, + &info->InterfaceGuid, + wlan_intf_opcode_background_scan_enabled, + sizeof(data), + &data, + NULL); + } + if (options & WIFI_OPTIONS_MEDIA_STREAMING_MODE) { + BOOL data = true; + wlanapi.set_interface_func(client_, + &info->InterfaceGuid, + wlan_intf_opcode_media_streaming_mode, + sizeof(data), + &data, + NULL); + } + } + } + + private: + internal::WlanHandle client_; +}; + +scoped_ptr<ScopedWifiOptions> SetWifiOptions(int options) { + return scoped_ptr<ScopedWifiOptions>(new WifiOptionSetter(options)); +} + } // namespace net diff --git a/net/base/net_util_win.h b/net/base/net_util_win.h new file mode 100644 index 0000000..afa888b --- /dev/null +++ b/net/base/net_util_win.h @@ -0,0 +1,85 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_NET_UTIL_WIN_H_ +#define NET_BASE_NET_UTIL_WIN_H_ + +// This file is only used to expose some of the internals +// of net_util_win.cc to tests. + +#include <wlanapi.h> + +#include "base/win/scoped_handle.h" +#include "net/base/net_export.h" + +namespace net { +namespace internal { + +struct NET_EXPORT WlanApi { + typedef DWORD (WINAPI *WlanOpenHandleFunc)( + DWORD, VOID*, DWORD*, HANDLE*); + typedef DWORD (WINAPI *WlanEnumInterfacesFunc)( + HANDLE, VOID*, WLAN_INTERFACE_INFO_LIST**); + typedef DWORD (WINAPI *WlanQueryInterfaceFunc)( + HANDLE, const GUID*, WLAN_INTF_OPCODE, VOID*, DWORD*, VOID**, + WLAN_OPCODE_VALUE_TYPE*); + typedef DWORD (WINAPI *WlanSetInterfaceFunc)( + HANDLE, const GUID*, WLAN_INTF_OPCODE, DWORD, const VOID*, VOID*); + typedef VOID (WINAPI *WlanFreeMemoryFunc)(VOID*); + typedef DWORD (WINAPI *WlanCloseHandleFunc)(HANDLE, VOID*); + + WlanApi(); + static WlanApi& GetInstance(); + + template <typename T> + DWORD OpenHandle(DWORD client_version, DWORD* cur_version, T* handle) const { + HANDLE temp_handle; + DWORD result = open_handle_func(client_version, NULL, cur_version, + &temp_handle); + if (result != ERROR_SUCCESS) + return result; + handle->Set(temp_handle); + return ERROR_SUCCESS; + } + + HMODULE module; + WlanOpenHandleFunc open_handle_func; + WlanEnumInterfacesFunc enum_interfaces_func; + WlanQueryInterfaceFunc query_interface_func; + WlanSetInterfaceFunc set_interface_func; + WlanFreeMemoryFunc free_memory_func; + WlanCloseHandleFunc close_handle_func; + bool initialized; +}; + +struct WlanApiHandleTraits { + typedef HANDLE Handle; + + static bool CloseHandle(HANDLE handle) { + return WlanApi::GetInstance().close_handle_func(handle, NULL) == + ERROR_SUCCESS; + } + static bool IsHandleValid(HANDLE handle) { + return base::win::HandleTraits::IsHandleValid(handle); + } + static HANDLE NullHandle() { + return base::win::HandleTraits::NullHandle(); + } +}; + +typedef base::win::GenericScopedHandle< + WlanApiHandleTraits, + base::win::DummyVerifierTraits> WlanHandle; + +struct WlanApiDeleter { + inline void operator()(void* ptr) const { + WlanApi::GetInstance().free_memory_func(ptr); + } +}; + +} // namespace internal + +} // namespace net + +#endif // NET_BASE_NET_UTIL_WIN_H_ |