Index: chrome/utility/wifi/wifi_service_win.cc |
diff --git a/chrome/utility/wifi/wifi_service_win.cc b/chrome/utility/wifi/wifi_service_win.cc |
index d9de098143bf8db2845b44983f9dd782646d8256..1009442643b7b26ac614b862a5f5271c16c7a88d 100644 |
--- a/chrome/utility/wifi/wifi_service_win.cc |
+++ b/chrome/utility/wifi/wifi_service_win.cc |
@@ -19,10 +19,10 @@ |
namespace { |
const char kWiFiServiceError[] = "Error.WiFiService"; |
-const wchar_t kNwCategoryWizardRegKey[] = |
- L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Network\\" |
- L"NwCategoryWizard"; |
-const wchar_t kNwCategoryWizardRegValue[] = L"Show"; |
+const wchar_t kNwCategoryWizardRegKey[] = |
+ L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Network\\" |
+ L"NwCategoryWizard"; |
+const wchar_t kNwCategoryWizardRegValue[] = L"Show"; |
} // namespace |
namespace wifi { |
@@ -59,6 +59,7 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { |
virtual void RequestNetworkScan() OVERRIDE; |
virtual void StartConnect(const std::string& network_guid, |
+ Frequency frequency, |
const StringResultCallback& callback, |
const ErrorCallback& error_callback) OVERRIDE; |
@@ -179,12 +180,20 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { |
DWORD FindConnectedNetwork(std::string* connected_network_guid); |
// Connect to network |network_guid| using previosly stored profile if exists, |
- // or just network sid. |
- DWORD Connect(const std::string& network_guid); |
+ // or just network sid. If |frequency| is not |kFrequencyUnknown| then |
+ // connects only to BSS which uses that frequency and returns |
+ // |ERROR_NOT_FOUND| if such BSS cannot be found. |
+ DWORD Connect(const std::string& network_guid, Frequency frequency); |
// Disconnect from currently connected network if any. |
DWORD Disconnect(); |
+ // 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); |
+ |
// Save temporary wireless profile for |network_guid|. |
DWORD SaveTempProfile(const std::string& network_guid); |
@@ -306,9 +315,10 @@ void WiFiServiceImpl::RequestNetworkScan() { |
} |
void WiFiServiceImpl::StartConnect(const std::string& network_guid, |
+ Frequency frequency, |
const StringResultCallback& callback, |
const ErrorCallback& error_callback) { |
- DLOG(INFO) << "Start Connect: " << network_guid; |
+ DLOG(INFO) << "Start Connect: " << network_guid << " " << frequency << " MHz"; |
DWORD error = EnsureInitialized(); |
if (error == ERROR_SUCCESS) { |
std::string connected_network_guid; |
@@ -316,14 +326,14 @@ void WiFiServiceImpl::StartConnect(const std::string& network_guid, |
if (error == ERROR_SUCCESS) { |
// Connect only if network |network_guid| is not connected already. |
if (network_guid != connected_network_guid) |
- error = Connect(network_guid); |
+ error = Connect(network_guid, frequency); |
if (error == ERROR_SUCCESS) { |
- DisableNwCategoryWizard(); |
callback.Run(network_guid); |
// Notify that previously connected network has changed. |
NotifyNetworkChanged(connected_network_guid); |
// Start waiting for network connection state change. |
if (!networks_changed_observer_.is_null()) { |
+ DisableNwCategoryWizard(); |
// Disable automatic network change notifications as they get fired |
// when network is just connected, but not yet accessible (doesn't |
// have valid IP address). |
@@ -376,6 +386,9 @@ void WiFiServiceImpl::OnWlanNotificationCallback( |
void WiFiServiceImpl::OnWlanNotification( |
PWLAN_NOTIFICATION_DATA wlan_notification_data) { |
+ if (!task_runner_) |
+ return; |
+ |
switch (wlan_notification_data->NotificationCode) { |
case wlan_notification_acm_disconnected: |
case wlan_notification_acm_connection_complete: |
@@ -496,7 +509,7 @@ DWORD WiFiServiceImpl::OpenClientHandle() { |
DWORD service_version = 0; |
// Open a handle to the service. |
- error = ::WlanOpenHandle(1, NULL, &service_version, &client_); |
+ error = ::WlanOpenHandle(WLAN_API_VERSION, NULL, &service_version, &client_); |
PWLAN_INTERFACE_INFO_LIST interface_list = NULL; |
if (error == ERROR_SUCCESS) { |
@@ -779,37 +792,123 @@ DWORD WiFiServiceImpl::FindConnectedNetwork( |
return error; |
} |
-DWORD WiFiServiceImpl::Connect(const std::string& network_guid) { |
+DWORD WiFiServiceImpl::GetDesiredBssList( |
+ DOT11_SSID& ssid, |
+ Frequency frequency, |
+ scoped_ptr<DOT11_BSSID_LIST>* desired_list) { |
afontan
2013/10/24 18:18:20
I think you should consider adding hidden networks
mef
2013/10/24 19:13:54
Sounds good. I'll keep this CL going as placeholde
|
if (client_ == NULL) { |
NOTREACHED(); |
return ERROR_NOINTERFACE; |
} |
+ desired_list->reset(); |
+ |
+ if (frequency == kFrequencyUnknown) |
+ return ERROR_SUCCESS; |
+ |
DWORD error = ERROR_SUCCESS; |
- base::string16 profile_name = ProfileNameFromGUID(network_guid); |
+ PWLAN_BSS_LIST bss_list = NULL; |
- if (HaveProfile(network_guid)) { |
- WLAN_CONNECTION_PARAMETERS wlan_params = { |
- wlan_connection_mode_profile, |
- profile_name.c_str(), |
- NULL, |
- NULL, |
- dot11_BSS_type_any, |
- 0}; |
- error = ::WlanConnect(client_, &interface_guid_, &wlan_params, NULL); |
- } else { |
- // TODO(mef): wlan_connection_mode_discovery_unsecure is not available on |
- // XP. If XP support is needed, then temporary profile will have to be |
- // created. |
- DOT11_SSID ssid = SSIDFromGUID(network_guid); |
- WLAN_CONNECTION_PARAMETERS wlan_params = { |
- wlan_connection_mode_discovery_unsecure, |
- NULL, |
- &ssid, |
- NULL, |
- dot11_BSS_type_infrastructure, |
- 0}; |
- error = ::WlanConnect(client_, &interface_guid_, &wlan_params, NULL); |
+ // 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. |
+ error = ::WlanGetNetworkBssList(client_, |
+ &interface_guid_, |
+ NULL, |
+ dot11_BSS_type_any, |
+ FALSE, |
+ NULL, |
+ &bss_list); |
+ if (error == ERROR_SUCCESS && NULL != bss_list) { |
+ unsigned int best_quality = 0u; |
+ size_t best_index = 0; |
+ Frequency bss_frequency; |
+ |
+ // Go through bss_list and find best quality BSSID with matching frequency. |
+ for (size_t bss = 0; bss < bss_list->dwNumberOfItems; ++bss) { |
+ const WLAN_BSS_ENTRY& bss_entry(bss_list->wlanBssEntries[bss]); |
+ if (bss_entry.dot11Ssid.uSSIDLength != ssid.uSSIDLength || |
+ 0 != memcmp(bss_entry.dot11Ssid.ucSSID, |
+ ssid.ucSSID, |
+ bss_entry.dot11Ssid.uSSIDLength)) |
+ continue; |
+ |
+ if (bss_entry.ulChCenterFrequency < 3000000) |
+ bss_frequency = kFrequency2400; |
+ else |
+ bss_frequency = kFrequency5000; |
+ |
+ if (bss_frequency == frequency && |
+ bss_entry.uLinkQuality > best_quality) { |
+ best_quality = bss_entry.uLinkQuality; |
+ best_index = bss; |
+ } |
+ } |
+ |
+ // If any matching BSS were found, prepare the header. |
+ if (best_quality > 0) { |
+ const WLAN_BSS_ENTRY& bss_entry(bss_list->wlanBssEntries[best_index]); |
+ scoped_ptr<DOT11_BSSID_LIST> selected_list(new DOT11_BSSID_LIST); |
+ |
+ selected_list->Header.Revision = DOT11_BSSID_LIST_REVISION_1; |
+ selected_list->Header.Size = sizeof(DOT11_BSSID_LIST); |
+ selected_list->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; |
+ selected_list->uNumOfEntries = 1; |
+ selected_list->uTotalNumOfEntries = 1; |
+ std::copy(bss_entry.dot11Bssid, |
+ bss_entry.dot11Bssid+sizeof(bss_entry.dot11Bssid), |
+ selected_list->BSSIDs[0]); |
+ desired_list->swap(selected_list); |
+ DLOG(INFO) << "Quality: " << best_quality << " BSS: " |
+ << NetworkProperties::MacAddressAsString(bss_entry.dot11Bssid); |
+ } else { |
+ error = ERROR_NOT_FOUND; |
+ } |
+ } |
+ |
+ // clean up |
+ if (bss_list != NULL) { |
+ ::WlanFreeMemory(bss_list); |
+ } |
+ return error; |
+} |
+ |
+ |
+DWORD WiFiServiceImpl::Connect(const std::string& network_guid, |
+ Frequency frequency) { |
+ if (client_ == NULL) { |
+ NOTREACHED(); |
+ return ERROR_NOINTERFACE; |
+ } |
+ |
+ DWORD error = ERROR_SUCCESS; |
+ DOT11_SSID ssid = SSIDFromGUID(network_guid); |
+ scoped_ptr<DOT11_BSSID_LIST> desired_bss_list; |
+ error = GetDesiredBssList(ssid, frequency, &desired_bss_list); |
+ if (error == ERROR_SUCCESS) { |
+ if (HaveProfile(network_guid)) { |
+ base::string16 profile_name = ProfileNameFromGUID(network_guid); |
+ WLAN_CONNECTION_PARAMETERS wlan_params = { |
+ wlan_connection_mode_profile, |
+ profile_name.c_str(), |
+ NULL, |
+ desired_bss_list.get(), |
+ dot11_BSS_type_any, |
+ 0}; |
+ error = ::WlanConnect(client_, &interface_guid_, &wlan_params, NULL); |
+ } else { |
+ // TODO(mef): wlan_connection_mode_discovery_unsecure is not available on |
+ // XP. If XP support is needed, then temporary profile will have to be |
+ // created. |
+ WLAN_CONNECTION_PARAMETERS wlan_params = { |
+ wlan_connection_mode_discovery_unsecure, |
+ NULL, |
+ &ssid, |
+ desired_bss_list.get(), |
+ dot11_BSS_type_infrastructure, |
+ 0}; |
+ error = ::WlanConnect(client_, &interface_guid_, &wlan_params, NULL); |
+ } |
} |
return error; |