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 f34e3b769f95716ba85c8da18cd630c417f90ddd..70a55212eb93dc1296f0b60eeddd9d31c79df824 100644 |
| --- a/components/wifi/wifi_service_win.cc |
| +++ b/components/wifi/wifi_service_win.cc |
| @@ -21,6 +21,7 @@ |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/win/registry.h" |
| #include "components/onc/onc_constants.h" |
| +#include "third_party/libxml/chromium/libxml_utils.h" |
| namespace { |
| const char kWiFiServiceError[] = "Error.WiFiService"; |
| @@ -46,6 +47,7 @@ const char kWlanQueryInterface[] = "WlanQueryInterface"; |
| const char kWlanRegisterNotification[] = "WlanRegisterNotification"; |
| const char kWlanSaveTemporaryProfile[] = "WlanSaveTemporaryProfile"; |
| const char kWlanScan[] = "WlanScan"; |
| +const char kWlanSetProfile[] = "WlanSetProfile"; |
| // WlanApi function definitions |
| typedef DWORD (WINAPI* WlanConnectFunction)( |
| @@ -136,6 +138,27 @@ typedef DWORD (WINAPI* WlanScanFunction)( |
| CONST PWLAN_RAW_DATA pIeData, |
| PVOID pReserved); |
| +typedef DWORD (WINAPI* WlanSetProfileFunction)( |
| + HANDLE hClientHandle, |
| + const GUID *pInterfaceGuid, |
| + DWORD dwFlags, |
| + LPCWSTR strProfileXml, |
| + LPCWSTR strAllUserProfileSecurity, |
| + BOOL bOverwrite, |
| + PVOID pReserved, |
| + DWORD* pdwReasonCode); |
| + |
| +// Values for WLANProfile XML. |
| +const char kAuthenticationOpen[] = "open"; |
| +const char kAuthenticationWepPsk[] = "WEP"; |
| +const char kAuthenticationWpaPsk[] = "WPAPSK"; |
| +const char kAuthenticationWpa2Psk[] = "WPA2PSK"; |
| +const char kEncryptionAES[] = "AES"; |
| +const char kEncryptionNone[] = "none"; |
| +const char kEncryptionWEP[] = "WEP"; |
| +const char kKeyTypeNetwork[] = "networkKey"; |
| +const char kKeyTypePassphrase[] = "passPhrase"; |
| + |
| } // namespace |
| namespace wifi { |
| @@ -281,6 +304,13 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { |
| // Deduce |onc::wifi| security from |alg|. |
| std::string SecurityFromDot11AuthAlg(DOT11_AUTH_ALGORITHM alg) const; |
| + // Deduce WLANProfile |authEncryption| values from |onc::wifi| security. |
| + bool AuthEncryptionFromSecurity(const std::string& security, |
| + bool* security_none, |
| + std::string* authentication, |
| + std::string* encryption, |
| + std::string* key_type) const; |
| + |
| // Populate |properties| based on |wlan| and its corresponding bss info from |
| // |wlan_bss_list|. |
| void NetworkPropertiesFromAvailableNetwork(const WLAN_AVAILABLE_NETWORK& wlan, |
| @@ -321,6 +351,10 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { |
| // Normalizes |frequency_in_mhz| into one of |Frequency| values. |
| Frequency GetNormalizedFrequency(int frequency_in_mhz) const; |
| + // Create |profile_xml| based on |network_properties|. |
| + bool CreateProfile(const NetworkProperties& network_properties, |
| + std::string* profile_xml); |
| + |
| // Save temporary wireless profile for |network_guid|. |
| DWORD SaveTempProfile(const std::string& network_guid); |
| @@ -356,6 +390,7 @@ class WiFiServiceImpl : public WiFiService, base::NonThreadSafe { |
| WlanQueryInterfaceFunction WlanQueryInterface_function_; |
| WlanRegisterNotificationFunction WlanRegisterNotification_function_; |
| WlanScanFunction WlanScan_function_; |
| + WlanSetProfileFunction WlanSetProfile_function_; |
| // WlanSaveTemporaryProfile function may not be avaiable on Windows XP. |
| WlanSaveTemporaryProfileFunction WlanSaveTemporaryProfile_function_; |
| @@ -402,6 +437,7 @@ WiFiServiceImpl::WiFiServiceImpl() |
| WlanRegisterNotification_function_(NULL), |
| WlanSaveTemporaryProfile_function_(NULL), |
| WlanScan_function_(NULL), |
| + WlanSetProfile_function_(NULL), |
| client_(NULL), |
| enable_notify_network_changed_(true) {} |
| @@ -476,7 +512,41 @@ void WiFiServiceImpl::CreateNetwork( |
| scoped_ptr<base::DictionaryValue> properties, |
| std::string* network_guid, |
| std::string* error) { |
| - CheckError(ERROR_CALL_NOT_IMPLEMENTED, kWiFiServiceError, error); |
| + DWORD error_code = EnsureInitialized(); |
| + if (CheckError(error_code, kWiFiServiceError, error)) |
| + return; |
| + |
| + WiFiService::NetworkProperties network_properties; |
| + if (!network_properties.UpdateFromValue(*properties)) { |
| + CheckError(ERROR_INVALID_DATA, kWiFiServiceError, error); |
| + return; |
| + } |
| + |
| + network_properties.guid = network_properties.ssid; |
| + std::string profile_xml; |
| + if (!CreateProfile(network_properties, &profile_xml)) { |
| + CheckError(ERROR_INVALID_DATA, kWiFiServiceError, error); |
| + return; |
| + } |
| + |
| + string16 profile_xml16(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); |
| + if (CheckError(error_code, kWiFiServiceError, error)) { |
| + DVLOG(0) << profile_xml; |
| + DVLOG(0) << "SetProfile Reason Code:" << reason_code; |
| + return; |
| + } |
| + |
| + *network_guid = network_properties.guid; |
| } |
| void WiFiServiceImpl::GetVisibleNetworks(const std::string& network_type, |
| @@ -751,6 +821,9 @@ DWORD WiFiServiceImpl::LoadWlanLibrary() { |
| WlanScan_function_ = |
| reinterpret_cast<WlanScanFunction>( |
| ::GetProcAddress(wlan_api_library_, kWlanScan)); |
| + WlanSetProfile_function_ = |
| + reinterpret_cast<WlanSetProfileFunction>( |
| + ::GetProcAddress(wlan_api_library_, kWlanSetProfile)); |
| if (!WlanConnect_function_ || |
| !WlanCloseHandle_function_ || |
| @@ -762,7 +835,8 @@ DWORD WiFiServiceImpl::LoadWlanLibrary() { |
| !WlanOpenHandle_function_ || |
| !WlanQueryInterface_function_ || |
| !WlanRegisterNotification_function_ || |
| - !WlanScan_function_) { |
| + !WlanScan_function_ || |
| + !WlanSetProfile_function_) { |
| DLOG(ERROR) << "Unable to find required WlanApi function."; |
| FreeLibrary(wlan_api_library_); |
| wlan_api_library_ = NULL; |
| @@ -942,6 +1016,7 @@ DWORD WiFiServiceImpl::CloseClientHandle() { |
| WlanRegisterNotification_function_ = NULL; |
| WlanSaveTemporaryProfile_function_ = NULL; |
| WlanScan_function_ = NULL; |
| + WlanSetProfile_function_ = NULL; |
| ::FreeLibrary(wlan_api_library_); |
| wlan_api_library_ = NULL; |
| } |
| @@ -1401,6 +1476,88 @@ bool WiFiServiceImpl::HaveProfile(const std::string& network_guid) { |
| return GetProfile(network_guid, &profile_xml) == ERROR_SUCCESS; |
| } |
| +bool WiFiServiceImpl::AuthEncryptionFromSecurity( |
| + const std::string& security, |
| + bool* security_open, |
| + std::string* authentication, |
| + std::string* encryption, |
| + std::string* key_type) const { |
| + *security_open = security == onc::wifi::kNone; |
| + if (*security_open) { |
| + *authentication = kAuthenticationOpen; |
| + *encryption = kEncryptionNone; |
| + } else if (security == onc::wifi::kWEP_PSK) { |
| + *authentication = kAuthenticationOpen; |
| + *encryption = kEncryptionWEP; |
| + *key_type = kKeyTypeNetwork; |
| + } else if (security == onc::wifi::kWPA_PSK) { |
| + *authentication = kAuthenticationWpaPsk; |
| + *encryption = kEncryptionAES; |
| + *key_type = kKeyTypePassphrase; |
| + } else if (security == onc::wifi::kWPA2_PSK) { |
| + *authentication = kAuthenticationWpa2Psk; |
| + *encryption = kEncryptionAES; |
| + *key_type = kKeyTypePassphrase; |
| + } else { |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +bool WiFiServiceImpl::CreateProfile( |
| + const NetworkProperties& network_properties, |
| + std::string* profile_xml) { |
| + // Get authentication and encryption values from security. |
| + bool security_open = true; |
| + std::string authentication; |
| + std::string encryption; |
| + std::string key_type; |
| + bool valid = AuthEncryptionFromSecurity(network_properties.security, |
| + &security_open, |
|
tbarzic
2013/12/10 19:42:39
instead of setting |security_open| in AuthEncrypti
mef
2013/12/10 20:51:43
Done.
|
| + &authentication, |
| + &encryption, |
| + &key_type); |
| + if (!valid) |
| + return valid; |
| + |
| + // Generate profile XML. |
| + XmlWriter xml_writer; |
| + xml_writer.StartWriting(); |
| + xml_writer.StartElement("WLANProfile"); |
| + xml_writer.AddAttribute( |
| + "xmlns", |
| + "http://www.microsoft.com/networking/WLAN/profile/v1"); |
| + xml_writer.WriteElement("name", network_properties.guid); |
| + xml_writer.StartElement("SSIDConfig"); |
| + xml_writer.StartElement("SSID"); |
| + xml_writer.WriteElement("name", network_properties.ssid); |
| + xml_writer.EndElement(); // Ends "SSID" element. |
| + xml_writer.EndElement(); // Ends "SSIDConfig" element. |
| + xml_writer.WriteElement("connectionType", "ESS"); |
| + xml_writer.WriteElement("connectionMode", "manual"); |
| + xml_writer.StartElement("MSM"); |
| + xml_writer.StartElement("security"); |
| + xml_writer.StartElement("authEncryption"); |
| + xml_writer.WriteElement("authentication", authentication); |
| + xml_writer.WriteElement("encryption", encryption); |
| + xml_writer.WriteElement("useOneX", "false"); |
| + xml_writer.EndElement(); // Ends "authEncryption" element. |
| + if (!security_open) { |
| + xml_writer.StartElement("sharedKey"); |
| + xml_writer.WriteElement("keyType", key_type); |
| + xml_writer.WriteElement("protected", "false"); |
| + xml_writer.WriteElement("keyMaterial", network_properties.password); |
| + xml_writer.EndElement(); // Ends "sharedKey" element. |
| + } |
| + xml_writer.EndElement(); // Ends "security" element. |
| + xml_writer.EndElement(); // Ends "MSM" element. |
| + xml_writer.EndElement(); // Ends "WLANProfile" element. |
| + xml_writer.StopWriting(); |
| + *profile_xml = xml_writer.GetWrittenString(); |
| + |
| + return true; |
| +} |
| + |
| void WiFiServiceImpl::NotifyNetworkListChanged(const NetworkList& networks) { |
| if (network_list_changed_observer_.is_null()) |
| return; |