| 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);
|
| }
|
|
|