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 1278cb28805e8134219ba6ea093cee5d2c0d312f..9ec9b7f816e76ed77a434b1ebc3ee79b0b1358c1 100644 |
| --- a/components/wifi/wifi_service_win.cc |
| +++ b/components/wifi/wifi_service_win.cc |
| @@ -35,6 +35,11 @@ const wchar_t kNwCategoryWizardSavedRegValue[] = L"ShowSaved"; |
| const wchar_t kNwCategoryWizardDeleteRegValue[] = L"ShowDelete"; |
| const wchar_t kWlanApiDll[] = L"wlanapi.dll"; |
| +// TKIP Profile Dictionary keys |
| +const char kNetworkGuidKey[] = "guid"; |
| +const char kProfileXmlKey[] = "profile"; |
| +const char kSharedProfileKey[] = "shared"; |
| + |
| // WlanApi function names |
| const char kWlanConnect[] = "WlanConnect"; |
| const char kWlanCloseHandle[] = "WlanCloseHandle"; |
| @@ -315,6 +320,7 @@ class WiFiServiceImpl : public WiFiService { |
| // Deduce WLANProfile |authEncryption| values from |onc::wifi| security. |
| bool AuthEncryptionFromSecurity(const std::string& security, |
| + bool use_default_encryption, |
|
tbarzic
2014/03/14 22:34:45
can you pass an enum {TKIP, AES} instead of bool
mef
2014/03/15 13:44:32
Done.
|
| std::string* authentication, |
| std::string* encryption, |
| std::string* key_type) const; |
| @@ -358,8 +364,11 @@ class WiFiServiceImpl : public WiFiService { |
| // Normalizes |frequency_in_mhz| into one of |Frequency| values. |
| Frequency GetNormalizedFrequency(int frequency_in_mhz) const; |
| - // Create |profile_xml| based on |network_properties|. |
| + // Create |profile_xml| based on |network_properties|. If |
| + // |use_default_encryption| is true, then profile uses default |
| + // encryption type (AES), otherwise it uses alternative (TKIP). |
| bool CreateProfile(const NetworkProperties& network_properties, |
| + bool use_default_encryption, |
| std::string* profile_xml); |
| // Save temporary wireless profile for |network_guid|. |
| @@ -372,6 +381,10 @@ class WiFiServiceImpl : public WiFiService { |
| bool get_plaintext_key, |
| std::string* profile_xml); |
| + // Set |profile_xml| to current user or all users depending on |shared| flag. |
| + // If |overwrite| is false, then returns an error if profile exists. |
| + DWORD SetProfile(bool shared, const std::string& profile_xml, bool overwrite); |
| + |
| // Return true if there is previously stored profile xml for |network_guid|. |
| bool HaveProfile(const std::string& network_guid); |
| @@ -415,6 +428,8 @@ class WiFiServiceImpl : public WiFiService { |
| base::DictionaryValue connect_properties_; |
| // Preserved WLAN profile xml. |
| std::map<std::string, std::string> saved_profiles_xml_; |
| + // WLAN profile xml with TKIP encryption type saved by |CreateNetwork|. |
| + base::DictionaryValue tkip_profile_; |
| // Observer to get notified when network(s) have changed (e.g. connect). |
| NetworkGuidListCallback networks_changed_observer_; |
| // Observer to get notified when network list has changed (scan complete). |
| @@ -519,6 +534,25 @@ void WiFiServiceImpl::SetProperties( |
| properties.release()); |
| } |
| +DWORD WiFiServiceImpl::SetProfile(bool shared, |
| + const std::string& profile_xml, |
| + bool overwrite) { |
| + DWORD error_code = ERROR_SUCCESS; |
| + |
| + base::string16 profile_xml16(base::UTF8ToUTF16(profile_xml)); |
| + DWORD reason_code = 0u; |
| + |
| + error_code = WlanSetProfile_function_(client_, |
| + &interface_guid_, |
| + shared ? 0 : WLAN_PROFILE_USER, |
| + profile_xml16.c_str(), |
| + NULL, |
| + overwrite, |
| + NULL, |
| + &reason_code); |
| + return error_code; |
| +} |
| + |
| void WiFiServiceImpl::CreateNetwork( |
| bool shared, |
| scoped_ptr<base::DictionaryValue> properties, |
| @@ -536,28 +570,32 @@ void WiFiServiceImpl::CreateNetwork( |
| network_properties.guid = network_properties.ssid; |
| std::string profile_xml; |
| - if (!CreateProfile(network_properties, &profile_xml)) { |
| + if (!CreateProfile(network_properties, true, &profile_xml)) { |
| CheckError(ERROR_INVALID_DATA, kWiFiServiceError, error); |
| return; |
| } |
| - base::string16 profile_xml16(base::UTF8ToUTF16(profile_xml)); |
| - DWORD reason_code = 0u; |
| - |
| - error_code = WlanSetProfile_function_(client_, |
| - &interface_guid_, |
| - shared ? 0 : WLAN_PROFILE_USER, |
| - profile_xml16.c_str(), |
| - NULL, |
| - FALSE, |
| - NULL, |
| - &reason_code); |
| + error_code = SetProfile(shared, profile_xml, false); |
| if (CheckError(error_code, kWiFiServiceError, error)) { |
| DVLOG(0) << profile_xml; |
| - DVLOG(0) << "SetProfile Reason Code:" << reason_code; |
| return; |
| } |
| + // WAP and WAP2 networks could use either AES or TKIP encryption type. |
| + // Preserve alternative profile to use in case if connection with default |
| + // encryption type fails. |
| + std::string tkip_profile_xml; |
| + if (!CreateProfile(network_properties, false, &tkip_profile_xml)) { |
| + CheckError(ERROR_INVALID_DATA, kWiFiServiceError, error); |
| + return; |
| + } |
| + |
| + if (tkip_profile_xml != profile_xml) { |
| + tkip_profile_.SetString(kNetworkGuidKey, network_properties.guid); |
|
tbarzic
2014/03/14 22:34:45
Should tkip_profile be saved be per network_guid?
mef
2014/03/15 13:44:32
Done.
|
| + tkip_profile_.SetString(kProfileXmlKey, tkip_profile_xml); |
| + tkip_profile_.SetBoolean(kSharedProfileKey, shared); |
| + } |
| + |
| *network_guid = network_properties.guid; |
| } |
| @@ -781,8 +819,30 @@ void WiFiServiceImpl::WaitForNetworkConnect(const std::string& network_guid, |
| if (attempt > kMaxAttempts) { |
| DLOG(ERROR) << kMaxAttempts << " attempts exceeded waiting for connect to " |
| << network_guid; |
| - enable_notify_network_changed_ = true; |
| - RestoreNwCategoryWizard(); |
| + |
| + // Check, if there is alternative TKIP profile that should be tried. |
| + // If there is, then set it up and try to connect again. |
| + if (!tkip_profile_.empty()) { |
| + std::string tkip_network_guid; |
| + std::string tkip_profile_xml; |
| + bool shared = false; |
| + if (tkip_profile_.GetString(kNetworkGuidKey, &tkip_network_guid) && |
| + tkip_profile_.GetString(kProfileXmlKey, &tkip_profile_xml) && |
| + tkip_profile_.GetBoolean(kSharedProfileKey, &shared) && |
| + tkip_network_guid == network_guid) { |
| + DWORD error_code = SetProfile(shared, tkip_profile_xml, true); |
| + if (error_code == ERROR_SUCCESS) { |
| + // Try to connect with new profile. |
| + error_code = Connect(network_guid, kFrequencyAny); |
|
tbarzic
2014/03/14 22:34:45
original connect request may have had the frequenc
mef
2014/03/15 13:44:32
Done.
|
| + if (error_code == ERROR_SUCCESS) |
| + WaitForNetworkConnect(network_guid, 0); |
| + } |
| + } |
| + tkip_profile_.Clear(); |
| + } else { |
| + enable_notify_network_changed_ = true; |
| + RestoreNwCategoryWizard(); |
| + } |
| return; |
| } |
| std::string connected_network_guid; |
| @@ -793,6 +853,8 @@ void WiFiServiceImpl::WaitForNetworkConnect(const std::string& network_guid, |
| // e.g. after Chromecast device reset. Reset DHCP on wireless network to |
| // work around this issue. |
| error = ResetDHCP(); |
| + // There is no need to keep TKIP profile as network is connected. |
| + tkip_profile_.Clear(); |
| // Restore previously suppressed notifications. |
| enable_notify_network_changed_ = true; |
| RestoreNwCategoryWizard(); |
| @@ -1557,6 +1619,7 @@ bool WiFiServiceImpl::HaveProfile(const std::string& network_guid) { |
| bool WiFiServiceImpl::AuthEncryptionFromSecurity( |
| const std::string& security, |
| + bool use_default_encryption, |
| std::string* authentication, |
| std::string* encryption, |
| std::string* key_type) const { |
| @@ -1569,15 +1632,11 @@ bool WiFiServiceImpl::AuthEncryptionFromSecurity( |
| *key_type = kKeyTypeNetwork; |
| } else if (security == onc::wifi::kWPA_PSK) { |
| *authentication = kAuthenticationWpaPsk; |
| - // TODO(mef): WAP |encryption| could be either |AES| or |TKIP|. It has to be |
| - // determined and adjusted properly during |Connect|. |
| - *encryption = kEncryptionAES; |
| + *encryption = use_default_encryption ? kEncryptionAES : kEncryptionTKIP; |
| *key_type = kKeyTypePassphrase; |
| } else if (security == onc::wifi::kWPA2_PSK) { |
| *authentication = kAuthenticationWpa2Psk; |
| - // TODO(mef): WAP |encryption| could be either |AES| or |TKIP|. It has to be |
| - // determined and adjusted properly during |Connect|. |
| - *encryption = kEncryptionAES; |
| + *encryption = use_default_encryption ? kEncryptionAES : kEncryptionTKIP; |
| *key_type = kKeyTypePassphrase; |
| } else { |
| return false; |
| @@ -1587,12 +1646,14 @@ bool WiFiServiceImpl::AuthEncryptionFromSecurity( |
| bool WiFiServiceImpl::CreateProfile( |
| const NetworkProperties& network_properties, |
| + bool use_default_encryption, |
| std::string* profile_xml) { |
| // Get authentication and encryption values from security. |
| std::string authentication; |
| std::string encryption; |
| std::string key_type; |
| bool valid = AuthEncryptionFromSecurity(network_properties.security, |
| + use_default_encryption, |
| &authentication, |
| &encryption, |
| &key_type); |