Index: components/wifi/wifi_service_win.cc |
diff --git a/components/wifi/wifi_service_win.cc b/components/wifi/wifi_service_win.cc |
index 5f837fcbb7314e642334dab999cefbd4cd0c4997..efaaa9b18250fd32064a2a2b426ad4a0bef26625 100644 |
--- a/components/wifi/wifi_service_win.cc |
+++ b/components/wifi/wifi_service_win.cc |
@@ -42,6 +42,7 @@ const char kWlanGetAvailableNetworkList[] = "WlanGetAvailableNetworkList"; |
const char kWlanGetNetworkBssList[] = "WlanGetNetworkBssList"; |
const char kWlanGetProfile[] = "WlanGetProfile"; |
const char kWlanOpenHandle[] = "WlanOpenHandle"; |
+const char kWlanQueryInterface[] = "WlanQueryInterface"; |
const char kWlanRegisterNotification[] = "WlanRegisterNotification"; |
const char kWlanSaveTemporaryProfile[] = "WlanSaveTemporaryProfile"; |
const char kWlanScan[] = "WlanScan"; |
@@ -101,6 +102,15 @@ typedef DWORD (WINAPI* WlanOpenHandleFunction)( |
PDWORD pdwNegotiatedVersion, |
PHANDLE phClientHandle); |
+typedef DWORD (WINAPI* WlanQueryInterfaceFunction)( |
+ HANDLE hClientHandle, |
+ const GUID *pInterfaceGuid, |
+ WLAN_INTF_OPCODE OpCode, |
+ PVOID pReserved, |
+ PDWORD pdwDataSize, |
+ PVOID *ppData, |
+ PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType); |
+ |
typedef DWORD (WINAPI* WlanRegisterNotificationFunction)( |
HANDLE hClientHandle, |
DWORD dwNotifSource, |
@@ -293,12 +303,24 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { |
// Disconnect from currently connected network if any. |
DWORD Disconnect(); |
+ // Get Frequency of currently connected network |network_guid|. If network is |
+ // not connected, then return |kFrequencyUnknown|. |
+ Frequency WiFiServiceImpl::GetConnectedFrequency( |
+ const std::string& network_guid); |
+ |
+ // Get desired connection freqency if it was set using |SetProperties|. |
+ // Default to |kFrequencyAny|. |
+ Frequency GetFrequencyToConnect(const std::string& network_guid) const; |
+ |
// Get DOT11_BSSID_LIST of desired BSSIDs to connect to |ssid| network on |
// given |frequency|. |
DWORD GetDesiredBssList(DOT11_SSID& ssid, |
Frequency frequency, |
scoped_ptr<DOT11_BSSID_LIST>* desired_list); |
+ // Normalizes |frequency_in_mhz| into one of |Frequency| values. |
+ Frequency GetNormalizedFrequency(int frequency_in_mhz) const; |
+ |
// Save temporary wireless profile for |network_guid|. |
DWORD SaveTempProfile(const std::string& network_guid); |
@@ -331,6 +353,7 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { |
WlanGetNetworkBssListFunction WlanGetNetworkBssList_function_; |
WlanGetProfileFunction WlanGetProfile_function_; |
WlanOpenHandleFunction WlanOpenHandle_function_; |
+ WlanQueryInterfaceFunction WlanQueryInterface_function_; |
WlanRegisterNotificationFunction WlanRegisterNotification_function_; |
WlanScanFunction WlanScan_function_; |
// WlanSaveTemporaryProfile function may not be avaiable on Windows XP. |
@@ -341,6 +364,9 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { |
// GUID of the currently connected interface, if any, otherwise the GUID of |
// one of the WLAN interfaces. |
GUID interface_guid_; |
+ // Temporary storage of network properties indexed by |network_guid|. Persist |
+ // only in memory. |
+ DictionaryValue connect_properties_; |
// Preserved WLAN profile xml. |
std::map<std::string, std::string> saved_profiles_xml_; |
// Observer to get notified when network(s) have changed (e.g. connect). |
@@ -421,9 +447,16 @@ void WiFiServiceImpl::SetProperties( |
const std::string& network_guid, |
scoped_ptr<base::DictionaryValue> properties, |
std::string* error) { |
- // This method is not implemented in first version as it is not used by |
- // Google Cast extension. |
- CheckError(ERROR_CALL_NOT_IMPLEMENTED, kWiFiServiceError, error); |
+ // Temporary preserve WiFi properties (desired frequency, wifi password) to |
+ // use in StartConnect. |
+ DCHECK(properties.get()); |
+ if (!properties->HasKey(onc::network_type::kWiFi)) { |
+ DVLOG(0) << "Missing WiFi properties:" << *properties; |
+ *error = kWiFiServiceError; |
+ return; |
+ } |
+ connect_properties_.SetWithoutPathExpansion(network_guid, |
+ properties.release()); |
} |
void WiFiServiceImpl::GetVisibleNetworks(const std::string& network_type, |
@@ -465,9 +498,15 @@ void WiFiServiceImpl::StartConnect(const std::string& network_guid, |
std::string connected_network_guid; |
error_code = SaveCurrentConnectedNetwork(&connected_network_guid); |
if (error_code == ERROR_SUCCESS) { |
- Frequency frequency = kFrequencyAny; |
+ // Check, if the network is already connected on desired frequency. |
+ bool already_connected = (network_guid == connected_network_guid); |
+ Frequency frequency = GetFrequencyToConnect(network_guid); |
+ if (already_connected && frequency != kFrequencyAny) { |
+ Frequency connected_frequency = GetConnectedFrequency(network_guid); |
+ already_connected = (frequency == connected_frequency); |
+ } |
// Connect only if network |network_guid| is not connected already. |
- if (network_guid != connected_network_guid) |
+ if (!already_connected) |
error_code = Connect(network_guid, frequency); |
if (error_code == ERROR_SUCCESS) { |
// Notify that previously connected network has changed. |
@@ -680,6 +719,9 @@ DWORD WiFiServiceImpl::LoadWlanLibrary() { |
WlanOpenHandle_function_ = |
reinterpret_cast<WlanOpenHandleFunction>( |
::GetProcAddress(wlan_api_library_, kWlanOpenHandle)); |
+ WlanQueryInterface_function_ = |
+ reinterpret_cast<WlanQueryInterfaceFunction>( |
+ ::GetProcAddress(wlan_api_library_, kWlanQueryInterface)); |
WlanRegisterNotification_function_ = |
reinterpret_cast<WlanRegisterNotificationFunction>( |
::GetProcAddress(wlan_api_library_, kWlanRegisterNotification)); |
@@ -698,6 +740,7 @@ DWORD WiFiServiceImpl::LoadWlanLibrary() { |
!WlanGetAvailableNetworkList_function_ || |
!WlanGetProfile_function_ || |
!WlanOpenHandle_function_ || |
+ !WlanQueryInterface_function_ || |
!WlanRegisterNotification_function_ || |
!WlanScan_function_) { |
DLOG(ERROR) << "Unable to find required WlanApi function."; |
@@ -753,7 +796,7 @@ DWORD WiFiServiceImpl::OpenClientHandle() { |
error = ERROR_NOINTERFACE; |
} |
} |
- // Clean up. |
+ // Clean up.. |
if (interface_list != NULL) |
WlanFreeMemory_function_(interface_list); |
} |
@@ -936,10 +979,8 @@ void WiFiServiceImpl::NetworkPropertiesFromAvailableNetwork( |
0 == memcmp(bss_entry.dot11Ssid.ucSSID, |
wlan.dot11Ssid.ucSSID, |
bss_entry.dot11Ssid.uSSIDLength)) { |
- if (bss_entry.ulChCenterFrequency < 3000000) |
- properties->frequency = kFrequency2400; |
- else |
- properties->frequency = kFrequency5000; |
+ properties->frequency = GetNormalizedFrequency( |
+ bss_entry.ulChCenterFrequency / 1000); |
properties->frequency_list.push_back(properties->frequency); |
properties->bssid = NetworkProperties::MacAddressAsString( |
bss_entry.dot11Bssid); |
@@ -1012,7 +1053,7 @@ DWORD WiFiServiceImpl::GetVisibleNetworkList(NetworkList* network_list) { |
} |
} |
- // clean up |
+ // Clean up. |
if (available_network_list != NULL) { |
WlanFreeMemory_function_(available_network_list); |
} |
@@ -1045,7 +1086,7 @@ DWORD WiFiServiceImpl::FindConnectedNetwork( |
} |
} |
- // clean up |
+ // Clean up. |
if (available_network_list != NULL) { |
WlanFreeMemory_function_(available_network_list); |
} |
@@ -1053,6 +1094,90 @@ DWORD WiFiServiceImpl::FindConnectedNetwork( |
return error; |
} |
+WiFiService::Frequency WiFiServiceImpl::GetConnectedFrequency( |
+ const std::string& network_guid) { |
+ if (client_ == NULL) { |
+ NOTREACHED(); |
+ return kFrequencyUnknown; |
+ } |
+ |
+ // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is |
+ // needed, then different method of getting BSS (e.g. OID query) will have |
+ // to be used. |
+ if (WlanGetNetworkBssList_function_ == NULL) |
+ return kFrequencyUnknown; |
+ |
+ Frequency frequency = kFrequencyUnknown; |
+ DWORD error = ERROR_SUCCESS; |
+ DWORD data_size = 0; |
+ PWLAN_CONNECTION_ATTRIBUTES wlan_connection_attributes = NULL; |
+ PWLAN_BSS_LIST bss_list = NULL; |
+ error = WlanQueryInterface_function_( |
+ client_, |
+ &interface_guid_, |
+ wlan_intf_opcode_current_connection, |
+ NULL, |
+ &data_size, |
+ reinterpret_cast<PVOID*>(&wlan_connection_attributes), |
+ NULL); |
+ if (error == ERROR_SUCCESS && |
+ wlan_connection_attributes != NULL && |
+ wlan_connection_attributes->isState == wlan_interface_state_connected) { |
+ WLAN_ASSOCIATION_ATTRIBUTES& connected_wlan = |
+ wlan_connection_attributes->wlanAssociationAttributes; |
+ // Try to find connected frequency based on bss. |
+ if (GUIDFromSSID(connected_wlan.dot11Ssid) == network_guid && |
+ WlanGetNetworkBssList_function_ != NULL) { |
+ error = WlanGetNetworkBssList_function_(client_, |
+ &interface_guid_, |
+ &connected_wlan.dot11Ssid, |
+ connected_wlan.dot11BssType, |
+ FALSE, |
+ NULL, |
+ &bss_list); |
+ if (error == ERROR_SUCCESS && NULL != bss_list) { |
+ // Go through bss_list and find matching BSSID. |
+ for (size_t bss = 0; bss < bss_list->dwNumberOfItems; ++bss) { |
+ const WLAN_BSS_ENTRY& bss_entry(bss_list->wlanBssEntries[bss]); |
+ if (0 == memcmp(bss_entry.dot11Bssid, |
+ connected_wlan.dot11Bssid, |
+ sizeof(bss_entry.dot11Bssid))) { |
+ frequency = GetNormalizedFrequency( |
+ bss_entry.ulChCenterFrequency / 1000); |
+ break; |
+ } |
+ } |
+ } |
+ } |
+ } |
+ |
+ // Clean up. |
+ if (wlan_connection_attributes != NULL) { |
+ WlanFreeMemory_function_(wlan_connection_attributes); |
+ } |
+ |
+ if (bss_list != NULL) { |
+ WlanFreeMemory_function_(bss_list); |
+ } |
+ |
+ return frequency; |
+} |
+ |
+WiFiService::Frequency WiFiServiceImpl::GetFrequencyToConnect( |
+ const std::string& network_guid) const { |
+ // Check whether desired frequency is set in |connect_properties_|. |
+ const DictionaryValue* properties; |
+ const DictionaryValue* wifi; |
+ int frequency; |
+ if (connect_properties_.GetDictionaryWithoutPathExpansion( |
+ network_guid, &properties) && |
+ properties->GetDictionary(onc::network_type::kWiFi, &wifi) && |
+ wifi->GetInteger(onc::wifi::kFrequency, &frequency)) { |
+ return GetNormalizedFrequency(frequency); |
+ } |
+ return kFrequencyAny; |
+} |
+ |
DWORD WiFiServiceImpl::GetDesiredBssList( |
DOT11_SSID& ssid, |
Frequency frequency, |
@@ -1078,8 +1203,8 @@ DWORD WiFiServiceImpl::GetDesiredBssList( |
error = WlanGetNetworkBssList_function_(client_, |
&interface_guid_, |
- NULL, |
- dot11_BSS_type_any, |
+ &ssid, |
+ dot11_BSS_type_infrastructure, |
FALSE, |
NULL, |
&bss_list); |
@@ -1097,11 +1222,8 @@ DWORD WiFiServiceImpl::GetDesiredBssList( |
bss_entry.dot11Ssid.uSSIDLength)) |
continue; |
- if (bss_entry.ulChCenterFrequency < 3000000) |
- bss_frequency = kFrequency2400; |
- else |
- bss_frequency = kFrequency5000; |
- |
+ bss_frequency = GetNormalizedFrequency( |
+ bss_entry.ulChCenterFrequency / 1000); |
if (bss_frequency == frequency && |
bss_entry.uLinkQuality > best_quality) { |
best_quality = bss_entry.uLinkQuality; |
@@ -1130,13 +1252,21 @@ DWORD WiFiServiceImpl::GetDesiredBssList( |
} |
} |
- // clean up |
+ // Clean up. |
if (bss_list != NULL) { |
WlanFreeMemory_function_(bss_list); |
} |
return error; |
} |
+WiFiService::Frequency WiFiServiceImpl::GetNormalizedFrequency( |
+ int frequency_in_mhz) const { |
+ if (frequency_in_mhz == 0) |
+ return kFrequencyAny; |
+ if (frequency_in_mhz < 3000) |
+ return kFrequency2400; |
+ return kFrequency5000; |
+} |
DWORD WiFiServiceImpl::Connect(const std::string& network_guid, |
Frequency frequency) { |
@@ -1237,7 +1367,7 @@ DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid, |
if (error == ERROR_SUCCESS && str_profile_xml != NULL) { |
*profile_xml = base::UTF16ToUTF8(str_profile_xml); |
} |
- // clean up |
+ // Clean up. |
if (str_profile_xml != NULL) { |
WlanFreeMemory_function_(str_profile_xml); |
} |