Chromium Code Reviews| Index: components/wifi/wifi_service_win.cc |
| diff --git a/components/wifi/wifi_service_win.cc b/components/wifi/wifi_service_win.cc |
| index 052062db1a757f5f4bfa617b74cf9e96bc186876..039836453132dad879b4b75bfb59e9fb6d8d6197 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, |
| @@ -291,12 +301,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); |
| @@ -329,6 +351,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. |
| @@ -339,6 +362,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). |
| @@ -419,9 +445,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(ListValue* network_list) { |
| @@ -457,9 +490,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. |
| @@ -672,6 +711,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)); |
| @@ -690,6 +732,7 @@ DWORD WiFiServiceImpl::LoadWlanLibrary() { |
| !WlanGetAvailableNetworkList_function_ || |
| !WlanGetProfile_function_ || |
| !WlanOpenHandle_function_ || |
| + !WlanQueryInterface_function_ || |
| !WlanRegisterNotification_function_ || |
| !WlanScan_function_) { |
| DLOG(ERROR) << "Unable to find required WlanApi function."; |
| @@ -745,7 +788,7 @@ DWORD WiFiServiceImpl::OpenClientHandle() { |
| error = ERROR_NOINTERFACE; |
| } |
| } |
| - // Clean up. |
| + // Clean up.. |
| if (interface_list != NULL) |
| WlanFreeMemory_function_(interface_list); |
| } |
| @@ -928,10 +971,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); |
| @@ -1004,7 +1045,7 @@ DWORD WiFiServiceImpl::GetVisibleNetworkList(NetworkList* network_list) { |
| } |
| } |
| - // clean up |
| + // Clean up. |
| if (available_network_list != NULL) { |
| WlanFreeMemory_function_(available_network_list); |
| } |
| @@ -1037,7 +1078,7 @@ DWORD WiFiServiceImpl::FindConnectedNetwork( |
| } |
| } |
| - // clean up |
| + // Clean up. |
| if (available_network_list != NULL) { |
| WlanFreeMemory_function_(available_network_list); |
| } |
| @@ -1045,6 +1086,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) { |
| + const 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_, |
| + NULL, |
|
afontan
2013/12/03 01:32:34
NULL means no filtering but if you pass the DOT11_
mef
2013/12/03 15:00:25
Theoretically yes, but practically on my machine i
mef
2013/12/03 17:08:11
Done. Specifying correct dot11BssType has fixed th
|
| + dot11_BSS_type_any, |
| + 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, |
| @@ -1089,11 +1214,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; |
| @@ -1122,13 +1244,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) { |
| @@ -1229,7 +1359,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); |
| } |