1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/wifi/wifi_service.h"
13 #include "base/base_paths_win.h"
14 #include "base/bind.h"
15 #include "base/files/file_path.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/path_service.h"
19 #include "base/strings/string16.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/win/registry.h"
23 #include "components/onc/onc_constants.h"
24 #include "components/wifi/network_properties.h"
25 #include "third_party/libxml/chromium/libxml_utils.h"
28 const wchar_t kNwCategoryWizardRegKey
[] =
29 L
"Software\\Microsoft\\Windows NT\\CurrentVersion\\Network\\"
31 const wchar_t kNwCategoryWizardRegValue
[] = L
"Show";
32 const wchar_t kNwCategoryWizardSavedRegValue
[] = L
"ShowSaved";
33 const wchar_t kNwCategoryWizardDeleteRegValue
[] = L
"ShowDelete";
34 const wchar_t kWlanApiDll
[] = L
"wlanapi.dll";
36 // Created Profile Dictionary keys
37 const char kProfileXmlKey
[] = "xml";
38 const char kProfileSharedKey
[] = "shared";
40 // WlanApi function names
41 const char kWlanConnect
[] = "WlanConnect";
42 const char kWlanCloseHandle
[] = "WlanCloseHandle";
43 const char kWlanDeleteProfile
[] = "WlanDeleteProfile";
44 const char kWlanDisconnect
[] = "WlanDisconnect";
45 const char kWlanEnumInterfaces
[] = "WlanEnumInterfaces";
46 const char kWlanFreeMemory
[] = "WlanFreeMemory";
47 const char kWlanGetAvailableNetworkList
[] = "WlanGetAvailableNetworkList";
48 const char kWlanGetNetworkBssList
[] = "WlanGetNetworkBssList";
49 const char kWlanGetProfile
[] = "WlanGetProfile";
50 const char kWlanOpenHandle
[] = "WlanOpenHandle";
51 const char kWlanQueryInterface
[] = "WlanQueryInterface";
52 const char kWlanRegisterNotification
[] = "WlanRegisterNotification";
53 const char kWlanSaveTemporaryProfile
[] = "WlanSaveTemporaryProfile";
54 const char kWlanScan
[] = "WlanScan";
55 const char kWlanSetProfile
[] = "WlanSetProfile";
57 // WlanApi function definitions
58 typedef DWORD(WINAPI
* WlanConnectFunction
)(
60 CONST GUID
* pInterfaceGuid
,
61 CONST PWLAN_CONNECTION_PARAMETERS pConnectionParameters
,
64 typedef DWORD (WINAPI
* WlanCloseHandleFunction
)(
68 typedef DWORD(WINAPI
* WlanDeleteProfileFunction
)(HANDLE hClientHandle
,
69 const GUID
* pInterfaceGuid
,
70 LPCWSTR strProfileName
,
73 typedef DWORD(WINAPI
* WlanDisconnectFunction
)(HANDLE hClientHandle
,
74 CONST GUID
* pInterfaceGuid
,
77 typedef DWORD(WINAPI
* WlanEnumInterfacesFunction
)(
80 PWLAN_INTERFACE_INFO_LIST
* ppInterfaceList
);
82 typedef VOID (WINAPI
* WlanFreeMemoryFunction
)(
85 typedef DWORD(WINAPI
* WlanGetAvailableNetworkListFunction
)(
87 CONST GUID
* pInterfaceGuid
,
90 PWLAN_AVAILABLE_NETWORK_LIST
* ppAvailableNetworkList
);
92 typedef DWORD (WINAPI
* WlanGetNetworkBssListFunction
)(
94 const GUID
* pInterfaceGuid
,
95 const PDOT11_SSID pDot11Ssid
,
96 DOT11_BSS_TYPE dot11BssType
,
97 BOOL bSecurityEnabled
,
99 PWLAN_BSS_LIST
* ppWlanBssList
);
101 typedef DWORD(WINAPI
* WlanGetProfileFunction
)(HANDLE hClientHandle
,
102 CONST GUID
* pInterfaceGuid
,
103 LPCWSTR strProfileName
,
105 LPWSTR
* pstrProfileXml
,
107 DWORD
* pdwGrantedAccess
);
109 typedef DWORD (WINAPI
* WlanOpenHandleFunction
)(
110 DWORD dwClientVersion
,
112 PDWORD pdwNegotiatedVersion
,
113 PHANDLE phClientHandle
);
115 typedef DWORD(WINAPI
* WlanQueryInterfaceFunction
)(
116 HANDLE hClientHandle
,
117 const GUID
* pInterfaceGuid
,
118 WLAN_INTF_OPCODE OpCode
,
122 PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType
);
124 typedef DWORD (WINAPI
* WlanRegisterNotificationFunction
)(
125 HANDLE hClientHandle
,
127 BOOL bIgnoreDuplicate
,
128 WLAN_NOTIFICATION_CALLBACK funcCallback
,
129 PVOID pCallbackContext
,
131 PDWORD pdwPrevNotifSource
);
133 typedef DWORD (WINAPI
* WlanSaveTemporaryProfileFunction
)(
134 HANDLE hClientHandle
,
135 CONST GUID
* pInterfaceGuid
,
136 LPCWSTR strProfileName
,
137 LPCWSTR strAllUserProfileSecurity
,
142 typedef DWORD(WINAPI
* WlanScanFunction
)(HANDLE hClientHandle
,
143 CONST GUID
* pInterfaceGuid
,
144 CONST PDOT11_SSID pDot11Ssid
,
145 CONST PWLAN_RAW_DATA pIeData
,
148 typedef DWORD(WINAPI
* WlanSetProfileFunction
)(HANDLE hClientHandle
,
149 const GUID
* pInterfaceGuid
,
151 LPCWSTR strProfileXml
,
152 LPCWSTR strAllUserProfileSecurity
,
155 DWORD
* pdwReasonCode
);
157 // Values for WLANProfile XML.
158 const char kAuthenticationOpen
[] = "open";
159 const char kAuthenticationWepPsk
[] = "WEP";
160 const char kAuthenticationWpaPsk
[] = "WPAPSK";
161 const char kAuthenticationWpa2Psk
[] = "WPA2PSK";
162 const char kEncryptionAES
[] = "AES";
163 const char kEncryptionNone
[] = "none";
164 const char kEncryptionTKIP
[] = "TKIP";
165 const char kEncryptionWEP
[] = "WEP";
166 const char kKeyTypeNetwork
[] = "networkKey";
167 const char kKeyTypePassphrase
[] = "passPhrase";
173 // Implementation of WiFiService for Windows.
174 class WiFiServiceImpl
: public WiFiService
{
177 virtual ~WiFiServiceImpl();
179 // WiFiService interface implementation.
180 virtual void Initialize(
181 scoped_refptr
<base::SequencedTaskRunner
> task_runner
) override
;
183 virtual void UnInitialize() override
;
185 virtual void GetProperties(const std::string
& network_guid
,
186 base::DictionaryValue
* properties
,
187 std::string
* error
) override
;
189 virtual void GetManagedProperties(const std::string
& network_guid
,
190 base::DictionaryValue
* managed_properties
,
191 std::string
* error
) override
;
193 virtual void GetState(const std::string
& network_guid
,
194 base::DictionaryValue
* properties
,
195 std::string
* error
) override
;
197 virtual void SetProperties(const std::string
& network_guid
,
198 scoped_ptr
<base::DictionaryValue
> properties
,
199 std::string
* error
) override
;
201 virtual void CreateNetwork(bool shared
,
202 scoped_ptr
<base::DictionaryValue
> properties
,
203 std::string
* network_guid
,
204 std::string
* error
) override
;
206 virtual void GetVisibleNetworks(const std::string
& network_type
,
207 base::ListValue
* network_list
,
208 bool include_details
) override
;
210 virtual void RequestNetworkScan() override
;
212 virtual void StartConnect(const std::string
& network_guid
,
213 std::string
* error
) override
;
215 virtual void StartDisconnect(const std::string
& network_guid
,
216 std::string
* error
) override
;
218 virtual void GetKeyFromSystem(const std::string
& network_guid
,
219 std::string
* key_data
,
220 std::string
* error
) override
;
222 virtual void SetEventObservers(
223 scoped_refptr
<base::MessageLoopProxy
> message_loop_proxy
,
224 const NetworkGuidListCallback
& networks_changed_observer
,
225 const NetworkGuidListCallback
& network_list_changed_observer
) override
;
227 virtual void RequestConnectedNetworkUpdate() override
{}
229 virtual void GetConnectedNetworkSSID(std::string
* ssid
,
230 std::string
* error
) override
;
233 typedef int32 EncryptionType
;
234 enum EncryptionTypeEnum
{
235 kEncryptionTypeAny
= 0,
236 kEncryptionTypeAES
= 1,
237 kEncryptionTypeTKIP
= 2
240 // Static callback for Windows WLAN_NOTIFICATION. Calls OnWlanNotification
241 // on WiFiServiceImpl passed back as |context|.
242 static void __stdcall
OnWlanNotificationCallback(
243 PWLAN_NOTIFICATION_DATA wlan_notification_data
,
246 // Callback for Windows WLAN_NOTIFICATION. Called on random thread from
247 // OnWlanNotificationCallback. Handles network connectivity and scan complete
248 // notification and posts tasks to main thread.
249 void OnWlanNotification(PWLAN_NOTIFICATION_DATA wlan_notification_data
);
251 // Handles NetworkScanComplete notification on main thread. Sends
252 // |NetworkListChanged| event with new list of visible networks.
253 void OnNetworkScanCompleteOnMainThread();
255 // Wait up to |kMaxAttempts| with |kAttemptDelayMs| delay for connection
256 // to network with |network_guid|. Reset DHCP and Notify that |NetworkChanged|
258 void WaitForNetworkConnect(const std::string
& network_guid
, int attempt
);
260 // Check |error_code| and if is not |ERROR_SUCCESS|, then store |error_name|
262 bool CheckError(DWORD error_code
,
263 const std::string
& error_name
,
264 std::string
* error
) const;
266 // Return |iterator| to network identified by |network_guid| in |networks|
268 NetworkList::iterator
FindNetwork(NetworkList
& networks
,
269 const std::string
& network_guid
);
271 // Save currently connected network profile so it can be re-connected later.
272 DWORD
SaveCurrentConnectedNetwork(const NetworkProperties
& properties
);
274 // Sort networks, so connected/connecting is up front, then by type:
275 // Ethernet, WiFi, Cellular, VPN
276 static void SortNetworks(NetworkList
* networks
);
278 // Open a WLAN client handle, register for WLAN notifications.
279 DWORD
OpenClientHandle();
281 // Reset DHCP on wireless network to work around an issue when Windows
282 // takes forever to connect to the network, e.g. after Chromecast
286 // Find |adapter_index_map| by |interface_guid| for DHCP reset.
287 DWORD
FindAdapterIndexMapByGUID(const GUID
& interface_guid
,
288 IP_ADAPTER_INDEX_MAP
* adapter_index_map
);
290 // Avoid the network location wizard to pop up when network is connected.
291 // Preserve current value in |saved_nw_category_wizard_|.
292 DWORD
DisableNwCategoryWizard();
294 // Restore network location wizard to value saved by DisableNwCategoryWizard.
295 DWORD
RestoreNwCategoryWizard();
297 // Ensure that |client_| handle is initialized.
298 DWORD
EnsureInitialized();
300 // Close |client_| handle if it is open.
301 DWORD
CloseClientHandle();
303 // Get |profile_name| from unique |network_guid|.
304 base::string16
ProfileNameFromGUID(const std::string
& network_guid
) const {
305 return base::UTF8ToUTF16(network_guid
);
308 // Get |dot11_ssid| from unique |network_guid|.
309 DOT11_SSID
SSIDFromGUID(const std::string
& network_guid
) const;
311 // Get unique |network_guid| string based on |dot11_ssid|.
312 std::string
GUIDFromSSID(const DOT11_SSID
& dot11_ssid
) const {
313 return std::string(reinterpret_cast<const char*>(dot11_ssid
.ucSSID
),
314 dot11_ssid
.uSSIDLength
);
317 // Get network |ssid| string based on |wlan|.
318 std::string
SSIDFromWLAN(const WLAN_AVAILABLE_NETWORK
& wlan
) const {
319 return GUIDFromSSID(wlan
.dot11Ssid
);
322 // Get unique |network_guid| string based on |wlan|.
323 std::string
GUIDFromWLAN(const WLAN_AVAILABLE_NETWORK
& wlan
) const {
324 return SSIDFromWLAN(wlan
);
327 // Deduce |onc::wifi| security from |alg|.
328 std::string
SecurityFromDot11AuthAlg(DOT11_AUTH_ALGORITHM alg
) const;
330 // Deduce |onc::connection_state| from |wlan_state|.
331 std::string
ConnectionStateFromInterfaceState(
332 WLAN_INTERFACE_STATE wlan_state
) const;
334 // Convert |EncryptionType| into WPA(2) encryption type string.
335 std::string
WpaEncryptionFromEncryptionType(
336 EncryptionType encryption_type
) const;
338 // Deduce WLANProfile |authEncryption| values from |onc::wifi| security.
339 bool AuthEncryptionFromSecurity(const std::string
& security
,
340 EncryptionType encryption_type
,
341 std::string
* authentication
,
342 std::string
* encryption
,
343 std::string
* key_type
) const;
345 // Populate |properties| based on |wlan|.
346 void NetworkPropertiesFromAvailableNetwork(const WLAN_AVAILABLE_NETWORK
& wlan
,
347 NetworkProperties
* properties
);
349 // Update |properties| based on bss info from |wlan_bss_list|. If |bssid| in
350 // |properties| is not empty, then it is not changed and |frequency| is set
351 // based on that bssid.
352 void UpdateNetworkPropertiesFromBssList(const std::string
& network_guid
,
353 const WLAN_BSS_LIST
& wlan_bss_list
,
354 NetworkProperties
* properties
);
356 // Get the list of visible wireless networks.
357 DWORD
GetVisibleNetworkList(NetworkList
* network_list
);
359 // Get properties of the network currently used (connected or in transition)
360 // by interface. Populate |current_properties| on success.
361 DWORD
GetCurrentProperties(NetworkProperties
* current_properties
);
363 // Get the SSID of the network currently used (connected or in transition)
364 // by interface. Populate |ssid| on success. This is a stripped down version
365 // of GetCurrentProperties that doesn't use the BSS list;
366 DWORD
GetCurrentSSID(std::string
* ssid
);
368 // Connect to network |network_guid| using previosly stored profile if exists,
369 // or just network sid. If |frequency| is not |kFrequencyUnknown| then
370 // connects only to BSS which uses that frequency and returns
371 // |ERROR_NOT_FOUND| if such BSS cannot be found.
372 DWORD
Connect(const std::string
& network_guid
, Frequency frequency
);
374 // Disconnect from currently connected network if any.
377 // Get desired connection freqency if it was set using |SetProperties|.
378 // Default to |kFrequencyAny|.
379 Frequency
GetFrequencyToConnect(const std::string
& network_guid
) const;
381 // Get DOT11_BSSID_LIST of desired BSSIDs to connect to |ssid| network on
382 // given |frequency|.
383 DWORD
GetDesiredBssList(DOT11_SSID
& ssid
,
385 scoped_ptr
<DOT11_BSSID_LIST
>* desired_list
);
387 // Normalizes |frequency_in_mhz| into one of |Frequency| values.
388 Frequency
GetNormalizedFrequency(int frequency_in_mhz
) const;
390 // Create |profile_xml| based on |network_properties|. If |encryption_type|
391 // is |kEncryptionTypeAny| applies the type most suitable for parameters in
392 // |network_properties|.
393 bool CreateProfile(const NetworkProperties
& network_properties
,
394 EncryptionType encryption_type
,
395 std::string
* profile_xml
);
397 // Save temporary wireless profile for |network_guid|.
398 DWORD
SaveTempProfile(const std::string
& network_guid
);
400 // Get previously stored |profile_xml| for |network_guid|.
401 // If |get_plaintext_key| is true, and process has sufficient privileges, then
402 // <sharedKey> data in |profile_xml| will be unprotected.
403 DWORD
GetProfile(const std::string
& network_guid
,
404 bool get_plaintext_key
,
405 std::string
* profile_xml
);
407 // Set |profile_xml| to current user or all users depending on |shared| flag.
408 // If |overwrite| is false, then returns an error if profile exists.
409 DWORD
SetProfile(bool shared
, const std::string
& profile_xml
, bool overwrite
);
411 // Return true if there is previously stored profile xml for |network_guid|.
412 bool HaveProfile(const std::string
& network_guid
);
414 // Delete profile that was created, but failed to connect.
415 DWORD
DeleteCreatedProfile(const std::string
& network_guid
);
417 // Notify |network_list_changed_observer_| that list of visible networks has
418 // changed to |networks|.
419 void NotifyNetworkListChanged(const NetworkList
& networks
);
421 // Notify |networks_changed_observer_| that network |network_guid| status has
423 void NotifyNetworkChanged(const std::string
& network_guid
);
425 // Load WlanApi.dll from SystemDirectory and get Api function pointers.
426 DWORD
LoadWlanLibrary();
427 // Instance of WlanApi.dll.
428 HINSTANCE wlan_api_library_
;
429 // WlanApi function pointers
430 WlanConnectFunction WlanConnect_function_
;
431 WlanCloseHandleFunction WlanCloseHandle_function_
;
432 WlanDeleteProfileFunction WlanDeleteProfile_function_
;
433 WlanDisconnectFunction WlanDisconnect_function_
;
434 WlanEnumInterfacesFunction WlanEnumInterfaces_function_
;
435 WlanFreeMemoryFunction WlanFreeMemory_function_
;
436 WlanGetAvailableNetworkListFunction WlanGetAvailableNetworkList_function_
;
437 // WlanGetNetworkBssList function may not be avaiable on Windows XP.
438 WlanGetNetworkBssListFunction WlanGetNetworkBssList_function_
;
439 WlanGetProfileFunction WlanGetProfile_function_
;
440 WlanOpenHandleFunction WlanOpenHandle_function_
;
441 WlanQueryInterfaceFunction WlanQueryInterface_function_
;
442 WlanRegisterNotificationFunction WlanRegisterNotification_function_
;
443 WlanScanFunction WlanScan_function_
;
444 WlanSetProfileFunction WlanSetProfile_function_
;
445 // WlanSaveTemporaryProfile function may not be avaiable on Windows XP.
446 WlanSaveTemporaryProfileFunction WlanSaveTemporaryProfile_function_
;
448 // WLAN service handle.
450 // GUID of the currently connected interface, if any, otherwise the GUID of
451 // one of the WLAN interfaces.
452 GUID interface_guid_
;
453 // Temporary storage of network properties indexed by |network_guid|. Persist
455 base::DictionaryValue connect_properties_
;
456 // Preserved WLAN profile xml.
457 std::map
<std::string
, std::string
> saved_profiles_xml_
;
458 // Created WLAN Profiles, indexed by |network_guid|. Contains xml with TKIP
459 // encryption type saved by |CreateNetwork| if applicable. Profile has to be
460 // deleted if connection fails. Implicitly created profiles have to be deleted
461 // if connection succeeds. Persist only in memory.
462 base::DictionaryValue created_profiles_
;
463 // Observer to get notified when network(s) have changed (e.g. connect).
464 NetworkGuidListCallback networks_changed_observer_
;
465 // Observer to get notified when network list has changed (scan complete).
466 NetworkGuidListCallback network_list_changed_observer_
;
467 // Saved value of network location wizard show value.
468 scoped_ptr
<DWORD
> saved_nw_category_wizard_
;
469 // MessageLoopProxy to post events on UI thread.
470 scoped_refptr
<base::MessageLoopProxy
> message_loop_proxy_
;
471 // Task runner for worker tasks.
472 scoped_refptr
<base::SequencedTaskRunner
> task_runner_
;
473 // If |false|, then |networks_changed_observer_| is not notified.
474 bool enable_notify_network_changed_
;
475 // Number of attempts to check that network has connected successfully.
476 static const int kMaxAttempts
= 100;
477 // Delay between attempts to check that network has connected successfully.
478 static const int kAttemptDelayMs
= 100;
479 DISALLOW_COPY_AND_ASSIGN(WiFiServiceImpl
);
482 WiFiServiceImpl::WiFiServiceImpl()
483 : wlan_api_library_(NULL
),
484 WlanConnect_function_(NULL
),
485 WlanCloseHandle_function_(NULL
),
486 WlanDeleteProfile_function_(NULL
),
487 WlanDisconnect_function_(NULL
),
488 WlanEnumInterfaces_function_(NULL
),
489 WlanFreeMemory_function_(NULL
),
490 WlanGetAvailableNetworkList_function_(NULL
),
491 WlanGetNetworkBssList_function_(NULL
),
492 WlanGetProfile_function_(NULL
),
493 WlanOpenHandle_function_(NULL
),
494 WlanRegisterNotification_function_(NULL
),
495 WlanSaveTemporaryProfile_function_(NULL
),
496 WlanScan_function_(NULL
),
497 WlanSetProfile_function_(NULL
),
499 enable_notify_network_changed_(true) {}
501 WiFiServiceImpl::~WiFiServiceImpl() { UnInitialize(); }
503 void WiFiServiceImpl::Initialize(
504 scoped_refptr
<base::SequencedTaskRunner
> task_runner
) {
506 task_runner_
.swap(task_runner
);
507 // Restore NwCategoryWizard in case if we crashed during connect.
508 RestoreNwCategoryWizard();
512 void WiFiServiceImpl::UnInitialize() {
516 void WiFiServiceImpl::GetProperties(const std::string
& network_guid
,
517 base::DictionaryValue
* properties
,
518 std::string
* error
) {
519 DWORD error_code
= EnsureInitialized();
520 if (CheckError(error_code
, kErrorWiFiService
, error
))
523 NetworkProperties connected_properties
;
524 error_code
= GetCurrentProperties(&connected_properties
);
525 if (error_code
== ERROR_SUCCESS
&&
526 connected_properties
.guid
== network_guid
) {
527 properties
->Swap(connected_properties
.ToValue(false).get());
531 NetworkList network_list
;
532 error_code
= GetVisibleNetworkList(&network_list
);
533 if (error_code
== ERROR_SUCCESS
) {
534 NetworkList::const_iterator it
= FindNetwork(network_list
, network_guid
);
535 if (it
!= network_list
.end()) {
536 DVLOG(1) << "Get Properties: " << network_guid
<< ":"
537 << it
->connection_state
;
538 properties
->Swap(it
->ToValue(false).get());
541 error_code
= ERROR_NOT_FOUND
;
544 CheckError(error_code
, kErrorWiFiService
, error
);
547 void WiFiServiceImpl::GetManagedProperties(
548 const std::string
& network_guid
,
549 base::DictionaryValue
* managed_properties
,
550 std::string
* error
) {
551 CheckError(ERROR_CALL_NOT_IMPLEMENTED
, kErrorWiFiService
, error
);
554 void WiFiServiceImpl::GetState(const std::string
& network_guid
,
555 base::DictionaryValue
* properties
,
556 std::string
* error
) {
557 CheckError(ERROR_CALL_NOT_IMPLEMENTED
, kErrorWiFiService
, error
);
560 void WiFiServiceImpl::SetProperties(
561 const std::string
& network_guid
,
562 scoped_ptr
<base::DictionaryValue
> properties
,
563 std::string
* error
) {
564 // Temporary preserve WiFi properties (desired frequency, wifi password) to
565 // use in StartConnect.
566 DCHECK(properties
.get());
567 if (!properties
->HasKey(onc::network_type::kWiFi
)) {
568 DVLOG(0) << "Missing WiFi properties:" << *properties
;
569 *error
= kErrorWiFiService
;
573 base::DictionaryValue
* existing_properties
;
574 // If the network properties already exist, don't override previously set
575 // properties, unless they are set in |properties|.
576 if (connect_properties_
.GetDictionaryWithoutPathExpansion(
577 network_guid
, &existing_properties
)) {
578 existing_properties
->MergeDictionary(properties
.get());
580 connect_properties_
.SetWithoutPathExpansion(network_guid
,
581 properties
.release());
585 void WiFiServiceImpl::CreateNetwork(
587 scoped_ptr
<base::DictionaryValue
> properties
,
588 std::string
* network_guid
,
589 std::string
* error
) {
590 DWORD error_code
= EnsureInitialized();
591 if (CheckError(error_code
, kErrorWiFiService
, error
))
594 NetworkProperties network_properties
;
595 if (!network_properties
.UpdateFromValue(*properties
)) {
596 CheckError(ERROR_INVALID_DATA
, kErrorWiFiService
, error
);
600 network_properties
.guid
= network_properties
.ssid
;
601 std::string profile_xml
;
602 if (!CreateProfile(network_properties
, kEncryptionTypeAny
, &profile_xml
)) {
603 CheckError(ERROR_INVALID_DATA
, kErrorWiFiService
, error
);
607 error_code
= SetProfile(shared
, profile_xml
, false);
608 if (CheckError(error_code
, kErrorWiFiService
, error
)) {
609 DVLOG(0) << profile_xml
;
613 // WAP and WAP2 networks could use either AES or TKIP encryption type.
614 // Preserve alternative profile to use in case if connection with default
615 // encryption type fails.
616 std::string tkip_profile_xml
;
617 if (!CreateProfile(network_properties
,
619 &tkip_profile_xml
)) {
620 CheckError(ERROR_INVALID_DATA
, kErrorWiFiService
, error
);
624 if (tkip_profile_xml
!= profile_xml
) {
625 scoped_ptr
<base::DictionaryValue
> tkip_profile(new base::DictionaryValue());
626 tkip_profile
->SetString(kProfileXmlKey
, tkip_profile_xml
);
627 tkip_profile
->SetBoolean(kProfileSharedKey
, shared
);
628 created_profiles_
.SetWithoutPathExpansion(network_properties
.guid
,
629 tkip_profile
.release());
632 *network_guid
= network_properties
.guid
;
635 void WiFiServiceImpl::GetVisibleNetworks(const std::string
& network_type
,
636 base::ListValue
* network_list
,
637 bool include_details
) {
638 if (!network_type
.empty() &&
639 network_type
!= onc::network_type::kAllTypes
&&
640 network_type
!= onc::network_type::kWiFi
) {
644 DWORD error
= EnsureInitialized();
645 if (error
== ERROR_SUCCESS
) {
646 NetworkList networks
;
647 error
= GetVisibleNetworkList(&networks
);
648 if (error
== ERROR_SUCCESS
&& !networks
.empty()) {
649 SortNetworks(&networks
);
650 for (NetworkList::const_iterator it
= networks
.begin();
651 it
!= networks
.end();
653 scoped_ptr
<base::DictionaryValue
> network(
654 it
->ToValue(!include_details
));
655 network_list
->Append(network
.release());
661 void WiFiServiceImpl::RequestNetworkScan() {
662 DWORD error
= EnsureInitialized();
663 if (error
== ERROR_SUCCESS
) {
664 WlanScan_function_(client_
, &interface_guid_
, NULL
, NULL
, NULL
);
668 void WiFiServiceImpl::StartConnect(const std::string
& network_guid
,
669 std::string
* error
) {
670 DVLOG(1) << "Start Connect: " << network_guid
;
671 DWORD error_code
= EnsureInitialized();
672 if (CheckError(error_code
, kErrorWiFiService
, error
))
675 // Check, if the network is already connected on desired frequency.
676 Frequency frequency
= GetFrequencyToConnect(network_guid
);
677 NetworkProperties properties
;
678 GetCurrentProperties(&properties
);
679 bool already_connected
=
680 network_guid
== properties
.guid
&&
681 properties
.connection_state
== onc::connection_state::kConnected
&&
682 (frequency
== kFrequencyAny
|| frequency
== properties
.frequency
);
684 // Connect only if network |network_guid| is not connected already.
685 if (!already_connected
) {
686 SaveCurrentConnectedNetwork(properties
);
687 error_code
= Connect(network_guid
, frequency
);
689 if (error_code
== ERROR_SUCCESS
) {
690 // Notify that previously connected network has changed.
691 NotifyNetworkChanged(properties
.guid
);
692 // Start waiting for network connection state change.
693 if (!networks_changed_observer_
.is_null()) {
694 DisableNwCategoryWizard();
695 // Disable automatic network change notifications as they get fired
696 // when network is just connected, but not yet accessible (doesn't
697 // have valid IP address).
698 enable_notify_network_changed_
= false;
699 WaitForNetworkConnect(network_guid
, 0);
702 } else if (error_code
== ERROR_ACCESS_DENIED
) {
703 CheckError(error_code
, kErrorNotConfigured
, error
);
705 CheckError(error_code
, kErrorWiFiService
, error
);
709 void WiFiServiceImpl::StartDisconnect(const std::string
& network_guid
,
710 std::string
* error
) {
711 DVLOG(1) << "Start Disconnect: " << network_guid
;
712 DWORD error_code
= EnsureInitialized();
713 if (CheckError(error_code
, kErrorWiFiService
, error
))
716 // Check, if the network is currently connected.
717 NetworkProperties properties
;
718 GetCurrentProperties(&properties
);
719 if (network_guid
== properties
.guid
) {
720 if (properties
.connection_state
== onc::connection_state::kConnected
)
721 SaveCurrentConnectedNetwork(properties
);
722 error_code
= Disconnect();
723 if (error_code
== ERROR_SUCCESS
) {
724 NotifyNetworkChanged(network_guid
);
728 CheckError(error_code
, kErrorWiFiService
, error
);
731 void WiFiServiceImpl::GetKeyFromSystem(const std::string
& network_guid
,
732 std::string
* key_data
,
733 std::string
* error
) {
734 DWORD error_code
= EnsureInitialized();
735 if (CheckError(error_code
, kErrorWiFiService
, error
))
738 std::string profile_xml
;
739 error_code
= GetProfile(network_guid
, true, &profile_xml
);
740 if (CheckError(error_code
, kErrorWiFiService
, error
))
743 const char kSharedKeyElement
[] = "sharedKey";
744 const char kProtectedElement
[] = "protected";
745 const char kKeyMaterialElement
[] = "keyMaterial";
747 // Quick check to verify presence of <sharedKey> element.
748 if (profile_xml
.find(kSharedKeyElement
) == std::string::npos
) {
749 *error
= kErrorWiFiService
;
754 if (reader
.Load(profile_xml
)) {
755 while (reader
.Read()) {
756 reader
.SkipToElement();
757 if (reader
.NodeName() == kSharedKeyElement
) {
758 while (reader
.Read()) {
759 reader
.SkipToElement();
760 if (reader
.NodeName() == kKeyMaterialElement
) {
761 reader
.ReadElementContent(key_data
);
762 } else if (reader
.NodeName() == kProtectedElement
) {
763 std::string protected_data
;
764 reader
.ReadElementContent(&protected_data
);
765 // Without UAC privilege escalation call to |GetProfile| with
766 // |WLAN_PROFILE_GET_PLAINTEXT_KEY| flag returns success, but has
767 // protected keyMaterial. Report an error in this case.
768 if (protected_data
!= "false") {
769 *error
= kErrorWiFiService
;
779 // Did not find passphrase in the profile.
780 *error
= kErrorWiFiService
;
783 void WiFiServiceImpl::SetEventObservers(
784 scoped_refptr
<base::MessageLoopProxy
> message_loop_proxy
,
785 const NetworkGuidListCallback
& networks_changed_observer
,
786 const NetworkGuidListCallback
& network_list_changed_observer
) {
787 DWORD error_code
= EnsureInitialized();
788 if (error_code
!= ERROR_SUCCESS
)
790 message_loop_proxy_
.swap(message_loop_proxy
);
791 if (!networks_changed_observer_
.is_null() ||
792 !network_list_changed_observer_
.is_null()) {
793 // Stop listening to WLAN notifications.
794 WlanRegisterNotification_function_(client_
,
795 WLAN_NOTIFICATION_SOURCE_NONE
,
797 OnWlanNotificationCallback
,
802 networks_changed_observer_
= networks_changed_observer
;
803 network_list_changed_observer_
= network_list_changed_observer
;
804 if (!networks_changed_observer_
.is_null() ||
805 !network_list_changed_observer_
.is_null()) {
806 // Start listening to WLAN notifications.
807 WlanRegisterNotification_function_(client_
,
808 WLAN_NOTIFICATION_SOURCE_ALL
,
810 OnWlanNotificationCallback
,
817 void WiFiServiceImpl::GetConnectedNetworkSSID(std::string
* ssid
,
818 std::string
* error
) {
819 DWORD error_code
= EnsureInitialized();
820 if (CheckError(error_code
, kErrorWiFiService
, error
))
822 std::string current_ssid
;
823 error_code
= GetCurrentSSID(¤t_ssid
);
824 if (CheckError(error_code
, kErrorWiFiService
, error
))
826 *ssid
= current_ssid
;
829 void WiFiServiceImpl::OnWlanNotificationCallback(
830 PWLAN_NOTIFICATION_DATA wlan_notification_data
,
832 WiFiServiceImpl
* service
= reinterpret_cast<WiFiServiceImpl
*>(context
);
833 service
->OnWlanNotification(wlan_notification_data
);
836 void WiFiServiceImpl::OnWlanNotification(
837 PWLAN_NOTIFICATION_DATA wlan_notification_data
) {
838 if (message_loop_proxy_
.get() == NULL
)
840 switch (wlan_notification_data
->NotificationCode
) {
841 case wlan_notification_acm_disconnected
:
842 case wlan_notification_acm_connection_complete
:
843 case wlan_notification_acm_connection_attempt_fail
: {
844 PWLAN_CONNECTION_NOTIFICATION_DATA wlan_connection_data
=
845 reinterpret_cast<PWLAN_CONNECTION_NOTIFICATION_DATA
>(
846 wlan_notification_data
->pData
);
847 message_loop_proxy_
->PostTask(
849 base::Bind(&WiFiServiceImpl::NotifyNetworkChanged
,
850 base::Unretained(this),
851 GUIDFromSSID(wlan_connection_data
->dot11Ssid
)));
854 case wlan_notification_acm_scan_complete
:
855 case wlan_notification_acm_interface_removal
:
856 message_loop_proxy_
->PostTask(
858 base::Bind(&WiFiServiceImpl::OnNetworkScanCompleteOnMainThread
,
859 base::Unretained(this)));
864 void WiFiServiceImpl::OnNetworkScanCompleteOnMainThread() {
865 NetworkList networks
;
866 // Get current list of visible networks and notify that network list has
868 DWORD error
= GetVisibleNetworkList(&networks
);
869 if (error
!= ERROR_SUCCESS
)
871 NotifyNetworkListChanged(networks
);
874 void WiFiServiceImpl::WaitForNetworkConnect(const std::string
& network_guid
,
876 // If network didn't get connected in |kMaxAttempts|, then try to connect
877 // using different profile if it was created recently.
878 if (attempt
> kMaxAttempts
) {
879 LOG(ERROR
) << kMaxAttempts
<< " attempts exceeded waiting for connect to "
882 base::DictionaryValue
* created_profile
= NULL
;
883 // Check, whether this connection is using newly created profile.
884 if (created_profiles_
.GetDictionaryWithoutPathExpansion(
885 network_guid
, &created_profile
)) {
886 std::string tkip_profile_xml
;
888 // Check, if this connection there is alternative TKIP profile xml that
889 // should be tried. If there is, then set it up and try to connect again.
890 if (created_profile
->GetString(kProfileXmlKey
, &tkip_profile_xml
) &&
891 created_profile
->GetBoolean(kProfileSharedKey
, &shared
)) {
892 // Remove TKIP profile xml, so it will not be tried again.
893 created_profile
->Remove(kProfileXmlKey
, NULL
);
894 created_profile
->Remove(kProfileSharedKey
, NULL
);
895 DWORD error_code
= SetProfile(shared
, tkip_profile_xml
, true);
896 if (error_code
== ERROR_SUCCESS
) {
897 // Try to connect with new profile.
898 error_code
= Connect(network_guid
,
899 GetFrequencyToConnect(network_guid
));
900 if (error_code
== ERROR_SUCCESS
) {
901 // Start waiting again.
902 WaitForNetworkConnect(network_guid
, 0);
905 LOG(ERROR
) << "Failed to set created profile for " << network_guid
906 << " error=" << error_code
;
910 // Connection has failed, so delete bad created profile.
911 DWORD error_code
= DeleteCreatedProfile(network_guid
);
912 if (error_code
!= ERROR_SUCCESS
) {
913 LOG(ERROR
) << "Failed to delete created profile for " << network_guid
914 << " error=" << error_code
;
918 // Restore automatic network change notifications and stop waiting.
919 enable_notify_network_changed_
= true;
920 RestoreNwCategoryWizard();
923 NetworkProperties current_properties
;
924 DWORD error
= GetCurrentProperties(¤t_properties
);
925 if (network_guid
== current_properties
.guid
&&
926 current_properties
.connection_state
==
927 onc::connection_state::kConnected
) {
928 DVLOG(1) << "WiFi Connected, Reset DHCP: " << network_guid
;
929 // Even though wireless network is now connected, it may still be unusable,
930 // e.g. after Chromecast device reset. Reset DHCP on wireless network to
931 // work around this issue.
933 if (error
!= ERROR_SUCCESS
)
935 // There is no need to keep created profile as network is connected.
936 created_profiles_
.RemoveWithoutPathExpansion(network_guid
, NULL
);
937 // Restore previously suppressed notifications.
938 enable_notify_network_changed_
= true;
939 RestoreNwCategoryWizard();
940 NotifyNetworkChanged(network_guid
);
942 // Continue waiting for network connection state change.
943 task_runner_
->PostDelayedTask(
945 base::Bind(&WiFiServiceImpl::WaitForNetworkConnect
,
946 base::Unretained(this),
949 base::TimeDelta::FromMilliseconds(kAttemptDelayMs
));
953 bool WiFiServiceImpl::CheckError(DWORD error_code
,
954 const std::string
& error_name
,
955 std::string
* error
) const {
956 if (error_code
!= ERROR_SUCCESS
) {
957 DLOG(ERROR
) << "WiFiService Error " << error_code
<< ": " << error_name
;
964 NetworkList::iterator
WiFiServiceImpl::FindNetwork(
965 NetworkList
& networks
,
966 const std::string
& network_guid
) {
967 for (NetworkList::iterator it
= networks
.begin(); it
!= networks
.end();
969 if (it
->guid
== network_guid
)
972 return networks
.end();
975 DWORD
WiFiServiceImpl::SaveCurrentConnectedNetwork(
976 const NetworkProperties
& current_properties
) {
977 DWORD error
= ERROR_SUCCESS
;
978 // Save currently connected network.
979 if (!current_properties
.guid
.empty() &&
980 current_properties
.connection_state
==
981 onc::connection_state::kConnected
) {
982 error
= SaveTempProfile(current_properties
.guid
);
987 void WiFiServiceImpl::SortNetworks(NetworkList
* networks
) {
988 networks
->sort(NetworkProperties::OrderByType
);
991 DWORD
WiFiServiceImpl::LoadWlanLibrary() {
992 // Use an absolute path to load the DLL to avoid DLL preloading attacks.
994 if (!PathService::Get(base::DIR_SYSTEM
, &path
)) {
995 LOG(ERROR
) << "Unable to get system path.";
996 return ERROR_NOT_FOUND
;
998 wlan_api_library_
= ::LoadLibraryEx(path
.Append(kWlanApiDll
).value().c_str(),
1000 LOAD_WITH_ALTERED_SEARCH_PATH
);
1001 if (!wlan_api_library_
) {
1002 LOG(ERROR
) << "Unable to load WlanApi.dll.";
1003 return ERROR_NOT_FOUND
;
1006 // Initialize WlanApi function pointers
1007 WlanConnect_function_
=
1008 reinterpret_cast<WlanConnectFunction
>(
1009 ::GetProcAddress(wlan_api_library_
, kWlanConnect
));
1010 WlanCloseHandle_function_
=
1011 reinterpret_cast<WlanCloseHandleFunction
>(
1012 ::GetProcAddress(wlan_api_library_
, kWlanCloseHandle
));
1013 WlanDeleteProfile_function_
=
1014 reinterpret_cast<WlanDeleteProfileFunction
>(
1015 ::GetProcAddress(wlan_api_library_
, kWlanDeleteProfile
));
1016 WlanDisconnect_function_
=
1017 reinterpret_cast<WlanDisconnectFunction
>(
1018 ::GetProcAddress(wlan_api_library_
, kWlanDisconnect
));
1019 WlanEnumInterfaces_function_
=
1020 reinterpret_cast<WlanEnumInterfacesFunction
>(
1021 ::GetProcAddress(wlan_api_library_
, kWlanEnumInterfaces
));
1022 WlanFreeMemory_function_
=
1023 reinterpret_cast<WlanFreeMemoryFunction
>(
1024 ::GetProcAddress(wlan_api_library_
, kWlanFreeMemory
));
1025 WlanGetAvailableNetworkList_function_
=
1026 reinterpret_cast<WlanGetAvailableNetworkListFunction
>(
1027 ::GetProcAddress(wlan_api_library_
, kWlanGetAvailableNetworkList
));
1028 WlanGetNetworkBssList_function_
=
1029 reinterpret_cast<WlanGetNetworkBssListFunction
>(
1030 ::GetProcAddress(wlan_api_library_
, kWlanGetNetworkBssList
));
1031 WlanGetProfile_function_
=
1032 reinterpret_cast<WlanGetProfileFunction
>(
1033 ::GetProcAddress(wlan_api_library_
, kWlanGetProfile
));
1034 WlanOpenHandle_function_
=
1035 reinterpret_cast<WlanOpenHandleFunction
>(
1036 ::GetProcAddress(wlan_api_library_
, kWlanOpenHandle
));
1037 WlanQueryInterface_function_
=
1038 reinterpret_cast<WlanQueryInterfaceFunction
>(
1039 ::GetProcAddress(wlan_api_library_
, kWlanQueryInterface
));
1040 WlanRegisterNotification_function_
=
1041 reinterpret_cast<WlanRegisterNotificationFunction
>(
1042 ::GetProcAddress(wlan_api_library_
, kWlanRegisterNotification
));
1043 WlanSaveTemporaryProfile_function_
=
1044 reinterpret_cast<WlanSaveTemporaryProfileFunction
>(
1045 ::GetProcAddress(wlan_api_library_
, kWlanSaveTemporaryProfile
));
1046 WlanScan_function_
=
1047 reinterpret_cast<WlanScanFunction
>(
1048 ::GetProcAddress(wlan_api_library_
, kWlanScan
));
1049 WlanSetProfile_function_
=
1050 reinterpret_cast<WlanSetProfileFunction
>(
1051 ::GetProcAddress(wlan_api_library_
, kWlanSetProfile
));
1053 if (!WlanConnect_function_
||
1054 !WlanCloseHandle_function_
||
1055 !WlanDeleteProfile_function_
||
1056 !WlanDisconnect_function_
||
1057 !WlanEnumInterfaces_function_
||
1058 !WlanFreeMemory_function_
||
1059 !WlanGetAvailableNetworkList_function_
||
1060 !WlanGetProfile_function_
||
1061 !WlanOpenHandle_function_
||
1062 !WlanQueryInterface_function_
||
1063 !WlanRegisterNotification_function_
||
1064 !WlanScan_function_
||
1065 !WlanSetProfile_function_
) {
1066 LOG(ERROR
) << "Unable to find required WlanApi function.";
1067 FreeLibrary(wlan_api_library_
);
1068 wlan_api_library_
= NULL
;
1069 return ERROR_NOT_FOUND
;
1072 // Some WlanApi functions may not be available on XP.
1073 if (!WlanGetNetworkBssList_function_
||
1074 !WlanSaveTemporaryProfile_function_
) {
1075 DVLOG(1) << "WlanApi function is not be available on XP.";
1078 return ERROR_SUCCESS
;
1081 DWORD
WiFiServiceImpl::OpenClientHandle() {
1082 DWORD error
= LoadWlanLibrary();
1083 DWORD service_version
= 0;
1085 if (error
!= ERROR_SUCCESS
)
1088 // Open a handle to the service.
1089 error
= WlanOpenHandle_function_(1, NULL
, &service_version
, &client_
);
1091 PWLAN_INTERFACE_INFO_LIST interface_list
= NULL
;
1092 if (error
== ERROR_SUCCESS
) {
1093 // Enumerate wireless interfaces.
1094 error
= WlanEnumInterfaces_function_(client_
, NULL
, &interface_list
);
1095 if (error
== ERROR_SUCCESS
) {
1096 if (interface_list
!= NULL
&& interface_list
->dwNumberOfItems
!= 0) {
1097 // Remember first interface just in case if none are connected.
1098 interface_guid_
= interface_list
->InterfaceInfo
[0].InterfaceGuid
;
1099 // Try to find a connected interface.
1100 for (DWORD itf
= 0; itf
< interface_list
->dwNumberOfItems
; ++itf
) {
1101 if (interface_list
->InterfaceInfo
[itf
].isState
==
1102 wlan_interface_state_connected
) {
1103 // Found connected interface, remember it!
1104 interface_guid_
= interface_list
->InterfaceInfo
[itf
].InterfaceGuid
;
1109 error
= ERROR_NOINTERFACE
;
1113 if (interface_list
!= NULL
)
1114 WlanFreeMemory_function_(interface_list
);
1119 DWORD
WiFiServiceImpl::ResetDHCP() {
1120 IP_ADAPTER_INDEX_MAP adapter_index_map
= {0};
1121 DWORD error
= FindAdapterIndexMapByGUID(interface_guid_
, &adapter_index_map
);
1122 if (error
!= ERROR_SUCCESS
) {
1123 LOG(ERROR
) << error
;
1126 error
= ::IpReleaseAddress(&adapter_index_map
);
1127 if (error
!= ERROR_SUCCESS
) {
1128 if (error
!= ERROR_ADDRESS_NOT_ASSOCIATED
) {
1129 LOG(ERROR
) << error
;
1132 DVLOG(1) << "Ignoring IpReleaseAddress Error: " << error
;
1134 error
= ::IpRenewAddress(&adapter_index_map
);
1135 if (error
!= ERROR_SUCCESS
)
1136 LOG(ERROR
) << error
;
1140 DWORD
WiFiServiceImpl::FindAdapterIndexMapByGUID(
1141 const GUID
& interface_guid
,
1142 IP_ADAPTER_INDEX_MAP
* adapter_index_map
) {
1143 base::string16 guid_string
;
1144 const int kGUIDSize
= 39;
1146 interface_guid
, WriteInto(&guid_string
, kGUIDSize
), kGUIDSize
);
1148 ULONG buffer_length
= 0;
1149 DWORD error
= ::GetInterfaceInfo(NULL
, &buffer_length
);
1150 if (error
== ERROR_INSUFFICIENT_BUFFER
) {
1151 scoped_ptr
<unsigned char[]> buffer(new unsigned char[buffer_length
]);
1152 IP_INTERFACE_INFO
* interface_info
=
1153 reinterpret_cast<IP_INTERFACE_INFO
*>(buffer
.get());
1154 error
= GetInterfaceInfo(interface_info
, &buffer_length
);
1155 if (error
== ERROR_SUCCESS
) {
1156 for (int adapter
= 0; adapter
< interface_info
->NumAdapters
; ++adapter
) {
1158 interface_info
->Adapter
[adapter
].Name
, guid_string
, false)) {
1159 *adapter_index_map
= interface_info
->Adapter
[adapter
];
1168 DWORD
WiFiServiceImpl::DisableNwCategoryWizard() {
1169 base::win::RegKey nw_category_wizard
;
1170 DWORD error
= nw_category_wizard
.Open(HKEY_CURRENT_USER
,
1171 kNwCategoryWizardRegKey
,
1172 KEY_READ
| KEY_SET_VALUE
);
1173 if (error
== ERROR_SUCCESS
) {
1174 // Save current value if present.
1175 if (nw_category_wizard
.HasValue(kNwCategoryWizardRegValue
)) {
1177 error
= nw_category_wizard
.ReadValueDW(kNwCategoryWizardRegValue
,
1179 if (error
== ERROR_SUCCESS
) {
1180 error
= nw_category_wizard
.WriteValue(kNwCategoryWizardSavedRegValue
,
1184 // Mark that temporary value has to be deleted.
1185 error
= nw_category_wizard
.WriteValue(kNwCategoryWizardDeleteRegValue
,
1189 // Disable network location wizard.
1190 error
= nw_category_wizard
.WriteValue(kNwCategoryWizardRegValue
,
1191 static_cast<DWORD
>(0));
1197 DWORD
WiFiServiceImpl::RestoreNwCategoryWizard() {
1198 base::win::RegKey nw_category_wizard
;
1199 DWORD error
= nw_category_wizard
.Open(HKEY_CURRENT_USER
,
1200 kNwCategoryWizardRegKey
,
1202 if (error
== ERROR_SUCCESS
) {
1203 // Restore saved value if present.
1204 if (nw_category_wizard
.HasValue(kNwCategoryWizardSavedRegValue
)) {
1206 error
= nw_category_wizard
.ReadValueDW(kNwCategoryWizardSavedRegValue
,
1208 if (error
== ERROR_SUCCESS
) {
1209 error
= nw_category_wizard
.WriteValue(kNwCategoryWizardRegValue
,
1211 error
= nw_category_wizard
.DeleteValue(kNwCategoryWizardSavedRegValue
);
1213 } else if (nw_category_wizard
.HasValue(kNwCategoryWizardDeleteRegValue
)) {
1214 error
= nw_category_wizard
.DeleteValue(kNwCategoryWizardRegValue
);
1215 error
= nw_category_wizard
.DeleteValue(kNwCategoryWizardDeleteRegValue
);
1222 DWORD
WiFiServiceImpl::EnsureInitialized() {
1223 if (client_
!= NULL
)
1224 return ERROR_SUCCESS
;
1225 return ERROR_NOINTERFACE
;
1228 DWORD
WiFiServiceImpl::CloseClientHandle() {
1229 DWORD error
= ERROR_SUCCESS
;
1230 if (client_
!= NULL
) {
1231 error
= WlanCloseHandle_function_(client_
, NULL
);
1234 if (wlan_api_library_
!= NULL
) {
1235 WlanConnect_function_
= NULL
;
1236 WlanCloseHandle_function_
= NULL
;
1237 WlanDeleteProfile_function_
= NULL
;
1238 WlanDisconnect_function_
= NULL
;
1239 WlanEnumInterfaces_function_
= NULL
;
1240 WlanFreeMemory_function_
= NULL
;
1241 WlanGetAvailableNetworkList_function_
= NULL
;
1242 WlanGetNetworkBssList_function_
= NULL
;
1243 WlanGetProfile_function_
= NULL
;
1244 WlanOpenHandle_function_
= NULL
;
1245 WlanRegisterNotification_function_
= NULL
;
1246 WlanSaveTemporaryProfile_function_
= NULL
;
1247 WlanScan_function_
= NULL
;
1248 WlanSetProfile_function_
= NULL
;
1249 ::FreeLibrary(wlan_api_library_
);
1250 wlan_api_library_
= NULL
;
1255 DOT11_SSID
WiFiServiceImpl::SSIDFromGUID(
1256 const std::string
& network_guid
) const {
1257 DOT11_SSID ssid
= {0};
1258 if (network_guid
.length() <= DOT11_SSID_MAX_LENGTH
) {
1259 ssid
.uSSIDLength
= static_cast<ULONG
>(network_guid
.length());
1260 strncpy(reinterpret_cast<char*>(ssid
.ucSSID
),
1261 network_guid
.c_str(),
1269 std::string
WiFiServiceImpl::SecurityFromDot11AuthAlg(
1270 DOT11_AUTH_ALGORITHM alg
) const {
1272 case DOT11_AUTH_ALGO_RSNA
:
1273 return onc::wifi::kWPA_EAP
;
1274 case DOT11_AUTH_ALGO_RSNA_PSK
:
1275 return onc::wifi::kWPA_PSK
;
1276 case DOT11_AUTH_ALGO_80211_SHARED_KEY
:
1277 return onc::wifi::kWEP_PSK
;
1278 case DOT11_AUTH_ALGO_80211_OPEN
:
1279 return onc::wifi::kSecurityNone
;
1281 return onc::wifi::kWPA_EAP
;
1285 std::string
WiFiServiceImpl::ConnectionStateFromInterfaceState(
1286 WLAN_INTERFACE_STATE wlan_state
) const {
1287 switch (wlan_state
) {
1288 case wlan_interface_state_connected
:
1289 // TODO(mef): Even if |wlan_state| is connected, the network may still
1290 // not be reachable, and should be resported as |kConnecting|.
1291 return onc::connection_state::kConnected
;
1292 case wlan_interface_state_associating
:
1293 case wlan_interface_state_discovering
:
1294 case wlan_interface_state_authenticating
:
1295 return onc::connection_state::kConnecting
;
1297 return onc::connection_state::kNotConnected
;
1301 void WiFiServiceImpl::NetworkPropertiesFromAvailableNetwork(
1302 const WLAN_AVAILABLE_NETWORK
& wlan
,
1303 NetworkProperties
* properties
) {
1304 // TODO(mef): It would be nice for the connection states in
1305 // getVisibleNetworks and getProperties results to be consistent.
1306 if (wlan
.dwFlags
& WLAN_AVAILABLE_NETWORK_CONNECTED
) {
1307 properties
->connection_state
= onc::connection_state::kConnected
;
1309 properties
->connection_state
= onc::connection_state::kNotConnected
;
1312 properties
->ssid
= SSIDFromWLAN(wlan
);
1313 properties
->name
= properties
->ssid
;
1314 properties
->guid
= GUIDFromWLAN(wlan
);
1315 properties
->type
= onc::network_type::kWiFi
;
1316 properties
->security
=
1317 SecurityFromDot11AuthAlg(wlan
.dot11DefaultAuthAlgorithm
);
1318 properties
->signal_strength
= wlan
.wlanSignalQuality
;
1321 void WiFiServiceImpl::UpdateNetworkPropertiesFromBssList(
1322 const std::string
& network_guid
,
1323 const WLAN_BSS_LIST
& wlan_bss_list
,
1324 NetworkProperties
* properties
) {
1325 if (network_guid
.empty())
1328 DOT11_SSID ssid
= SSIDFromGUID(network_guid
);
1329 for (size_t bss
= 0; bss
< wlan_bss_list
.dwNumberOfItems
; ++bss
) {
1330 const WLAN_BSS_ENTRY
& bss_entry(wlan_bss_list
.wlanBssEntries
[bss
]);
1331 if (bss_entry
.dot11Ssid
.uSSIDLength
== ssid
.uSSIDLength
&&
1332 0 == memcmp(bss_entry
.dot11Ssid
.ucSSID
,
1334 bss_entry
.dot11Ssid
.uSSIDLength
)) {
1335 std::string bssid
= NetworkProperties::MacAddressAsString(
1336 bss_entry
.dot11Bssid
);
1337 Frequency frequency
= GetNormalizedFrequency(
1338 bss_entry
.ulChCenterFrequency
/ 1000);
1339 properties
->frequency_set
.insert(frequency
);
1340 if (properties
->bssid
.empty() || properties
->bssid
== bssid
) {
1341 properties
->frequency
= frequency
;
1342 properties
->bssid
= bssid
;
1348 // Get the list of visible wireless networks
1349 DWORD
WiFiServiceImpl::GetVisibleNetworkList(NetworkList
* network_list
) {
1350 if (client_
== NULL
) {
1352 return ERROR_NOINTERFACE
;
1355 DWORD error
= ERROR_SUCCESS
;
1356 PWLAN_AVAILABLE_NETWORK_LIST available_network_list
= NULL
;
1357 PWLAN_BSS_LIST bss_list
= NULL
;
1359 error
= WlanGetAvailableNetworkList_function_(
1362 WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES
,
1364 &available_network_list
);
1366 std::set
<std::string
> network_guids
;
1368 if (error
== ERROR_SUCCESS
&&
1369 available_network_list
&&
1370 WlanGetNetworkBssList_function_
) {
1371 // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
1372 // needed, then different method of getting BSS (e.g. OID query) will have
1374 error
= WlanGetNetworkBssList_function_(client_
,
1381 if (error
== ERROR_SUCCESS
&& NULL
!= bss_list
) {
1382 for (DWORD i
= 0; i
< available_network_list
->dwNumberOfItems
; ++i
) {
1383 NetworkProperties network_properties
;
1384 NetworkPropertiesFromAvailableNetwork(
1385 available_network_list
->Network
[i
],
1386 &network_properties
);
1387 UpdateNetworkPropertiesFromBssList(network_properties
.guid
,
1389 &network_properties
);
1390 // Check for duplicate network guids.
1391 if (network_guids
.count(network_properties
.guid
)) {
1392 // There should be no difference between properties except for
1393 // |connection_state|, so mark it as |kConnected| if either one is.
1394 if (network_properties
.connection_state
==
1395 onc::connection_state::kConnected
) {
1396 NetworkList::iterator previous_network_properties
=
1397 FindNetwork(*network_list
, network_properties
.guid
);
1398 DCHECK(previous_network_properties
!= network_list
->end());
1399 previous_network_properties
->connection_state
=
1400 network_properties
.connection_state
;
1403 network_list
->push_back(network_properties
);
1405 network_guids
.insert(network_properties
.guid
);
1411 if (available_network_list
!= NULL
) {
1412 WlanFreeMemory_function_(available_network_list
);
1414 if (bss_list
!= NULL
) {
1415 WlanFreeMemory_function_(bss_list
);
1420 DWORD
WiFiServiceImpl::GetCurrentProperties(NetworkProperties
* properties
) {
1421 if (client_
== NULL
) {
1423 return ERROR_NOINTERFACE
;
1426 // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
1427 // needed, then different method of getting BSS (e.g. OID query) will have
1429 if (WlanGetNetworkBssList_function_
== NULL
)
1430 return ERROR_NOINTERFACE
;
1432 DWORD error
= ERROR_SUCCESS
;
1433 DWORD data_size
= 0;
1434 PWLAN_CONNECTION_ATTRIBUTES wlan_connection_attributes
= NULL
;
1435 PWLAN_BSS_LIST bss_list
= NULL
;
1436 error
= WlanQueryInterface_function_(
1439 wlan_intf_opcode_current_connection
,
1442 reinterpret_cast<PVOID
*>(&wlan_connection_attributes
),
1444 if (error
== ERROR_SUCCESS
&&
1445 wlan_connection_attributes
!= NULL
) {
1446 WLAN_ASSOCIATION_ATTRIBUTES
& connected_wlan
=
1447 wlan_connection_attributes
->wlanAssociationAttributes
;
1449 properties
->connection_state
= ConnectionStateFromInterfaceState(
1450 wlan_connection_attributes
->isState
);
1451 properties
->ssid
= GUIDFromSSID(connected_wlan
.dot11Ssid
);
1452 properties
->name
= properties
->ssid
;
1453 properties
->guid
= GUIDFromSSID(connected_wlan
.dot11Ssid
);
1454 properties
->type
= onc::network_type::kWiFi
;
1455 properties
->bssid
= NetworkProperties::MacAddressAsString(
1456 connected_wlan
.dot11Bssid
);
1457 properties
->security
= SecurityFromDot11AuthAlg(
1458 wlan_connection_attributes
->wlanSecurityAttributes
.dot11AuthAlgorithm
);
1459 properties
->signal_strength
= connected_wlan
.wlanSignalQuality
;
1461 error
= WlanGetNetworkBssList_function_(client_
,
1463 &connected_wlan
.dot11Ssid
,
1464 connected_wlan
.dot11BssType
,
1468 if (error
== ERROR_SUCCESS
&& NULL
!= bss_list
) {
1469 UpdateNetworkPropertiesFromBssList(properties
->guid
,
1476 if (wlan_connection_attributes
!= NULL
)
1477 WlanFreeMemory_function_(wlan_connection_attributes
);
1479 if (bss_list
!= NULL
)
1480 WlanFreeMemory_function_(bss_list
);
1486 DWORD
WiFiServiceImpl::GetCurrentSSID(std::string
* ssid
) {
1487 if (client_
== NULL
) {
1489 return ERROR_NOINTERFACE
;
1491 DWORD error
= ERROR_SUCCESS
;
1492 DWORD data_size
= 0;
1493 PWLAN_CONNECTION_ATTRIBUTES wlan_connection_attributes
= NULL
;
1494 error
= WlanQueryInterface_function_(
1497 wlan_intf_opcode_current_connection
,
1500 reinterpret_cast<PVOID
*>(&wlan_connection_attributes
),
1502 if (error
== ERROR_SUCCESS
&&
1503 wlan_connection_attributes
!= NULL
) {
1504 WLAN_ASSOCIATION_ATTRIBUTES
& connected_wlan
=
1505 wlan_connection_attributes
->wlanAssociationAttributes
;
1506 *ssid
= GUIDFromSSID(connected_wlan
.dot11Ssid
);
1510 if (wlan_connection_attributes
!= NULL
)
1511 WlanFreeMemory_function_(wlan_connection_attributes
);
1516 Frequency
WiFiServiceImpl::GetFrequencyToConnect(
1517 const std::string
& network_guid
) const {
1518 // Check whether desired frequency is set in |connect_properties_|.
1519 const base::DictionaryValue
* properties
;
1520 if (connect_properties_
.GetDictionaryWithoutPathExpansion(network_guid
,
1522 const base::DictionaryValue
* wifi
;
1523 if (properties
->GetDictionary(onc::network_type::kWiFi
, &wifi
)) {
1525 if (wifi
->GetInteger(onc::wifi::kFrequency
, &frequency
))
1526 return GetNormalizedFrequency(frequency
);
1529 return kFrequencyAny
;
1532 DWORD
WiFiServiceImpl::GetDesiredBssList(
1534 Frequency frequency
,
1535 scoped_ptr
<DOT11_BSSID_LIST
>* desired_list
) {
1536 if (client_
== NULL
) {
1538 return ERROR_NOINTERFACE
;
1541 desired_list
->reset();
1543 if (frequency
== kFrequencyAny
)
1544 return ERROR_SUCCESS
;
1546 // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
1547 // needed, then different method of getting BSS (e.g. OID query) will have
1549 if (!WlanGetNetworkBssList_function_
)
1550 return ERROR_NOT_SUPPORTED
;
1552 DWORD error
= ERROR_SUCCESS
;
1553 PWLAN_BSS_LIST bss_list
= NULL
;
1555 error
= WlanGetNetworkBssList_function_(client_
,
1558 dot11_BSS_type_infrastructure
,
1562 if (error
== ERROR_SUCCESS
&& NULL
!= bss_list
) {
1563 unsigned int best_quality
= 0u;
1564 size_t best_index
= 0;
1565 Frequency bss_frequency
;
1567 // Go through bss_list and find best quality BSSID with matching frequency.
1568 for (size_t bss
= 0; bss
< bss_list
->dwNumberOfItems
; ++bss
) {
1569 const WLAN_BSS_ENTRY
& bss_entry(bss_list
->wlanBssEntries
[bss
]);
1570 if (bss_entry
.dot11Ssid
.uSSIDLength
!= ssid
.uSSIDLength
||
1571 0 != memcmp(bss_entry
.dot11Ssid
.ucSSID
,
1573 bss_entry
.dot11Ssid
.uSSIDLength
))
1576 bss_frequency
= GetNormalizedFrequency(
1577 bss_entry
.ulChCenterFrequency
/ 1000);
1578 if (bss_frequency
== frequency
&&
1579 bss_entry
.uLinkQuality
> best_quality
) {
1580 best_quality
= bss_entry
.uLinkQuality
;
1585 // If any matching BSS were found, prepare the header.
1586 if (best_quality
> 0) {
1587 const WLAN_BSS_ENTRY
& bss_entry(bss_list
->wlanBssEntries
[best_index
]);
1588 scoped_ptr
<DOT11_BSSID_LIST
> selected_list(new DOT11_BSSID_LIST
);
1590 selected_list
->Header
.Revision
= DOT11_BSSID_LIST_REVISION_1
;
1591 selected_list
->Header
.Size
= sizeof(DOT11_BSSID_LIST
);
1592 selected_list
->Header
.Type
= NDIS_OBJECT_TYPE_DEFAULT
;
1593 selected_list
->uNumOfEntries
= 1;
1594 selected_list
->uTotalNumOfEntries
= 1;
1595 std::copy(bss_entry
.dot11Bssid
,
1596 bss_entry
.dot11Bssid
+sizeof(bss_entry
.dot11Bssid
),
1597 selected_list
->BSSIDs
[0]);
1598 desired_list
->swap(selected_list
);
1599 DVLOG(1) << "Quality: " << best_quality
<< " BSS: "
1600 << NetworkProperties::MacAddressAsString(bss_entry
.dot11Bssid
);
1602 error
= ERROR_NOT_FOUND
;
1607 if (bss_list
!= NULL
) {
1608 WlanFreeMemory_function_(bss_list
);
1613 Frequency
WiFiServiceImpl::GetNormalizedFrequency(int frequency_in_mhz
) const {
1614 if (frequency_in_mhz
== 0)
1615 return kFrequencyAny
;
1616 if (frequency_in_mhz
< 3000)
1617 return kFrequency2400
;
1618 return kFrequency5000
;
1621 DWORD
WiFiServiceImpl::Connect(const std::string
& network_guid
,
1622 Frequency frequency
) {
1623 if (client_
== NULL
) {
1625 return ERROR_NOINTERFACE
;
1628 DWORD error
= ERROR_SUCCESS
;
1629 DOT11_SSID ssid
= SSIDFromGUID(network_guid
);
1630 scoped_ptr
<DOT11_BSSID_LIST
> desired_bss_list
;
1631 error
= GetDesiredBssList(ssid
, frequency
, &desired_bss_list
);
1632 if (error
== ERROR_SUCCESS
) {
1633 if (HaveProfile(network_guid
)) {
1634 base::string16 profile_name
= ProfileNameFromGUID(network_guid
);
1635 WLAN_CONNECTION_PARAMETERS wlan_params
= {
1636 wlan_connection_mode_profile
,
1637 profile_name
.c_str(),
1639 desired_bss_list
.get(),
1642 error
= WlanConnect_function_(
1643 client_
, &interface_guid_
, &wlan_params
, NULL
);
1645 // If network is available, but is not open security, then it cannot be
1646 // connected without profile, so return 'access denied' error.
1647 scoped_ptr
<base::DictionaryValue
> properties (new base::DictionaryValue
);
1648 const base::DictionaryValue
* wifi
;
1649 std::string wifi_security
;
1650 std::string error_string
;
1651 GetProperties(network_guid
, properties
.get(), &error_string
);
1652 if (error_string
.empty() &&
1653 properties
->GetDictionary(onc::network_type::kWiFi
, &wifi
) &&
1654 wifi
->GetString(onc::wifi::kSecurity
, &wifi_security
) &&
1655 wifi_security
!= onc::wifi::kSecurityNone
) {
1656 error
= ERROR_ACCESS_DENIED
;
1657 LOG(ERROR
) << error
;
1660 WLAN_CONNECTION_PARAMETERS wlan_params
= {
1661 wlan_connection_mode_discovery_unsecure
,
1664 desired_bss_list
.get(),
1665 dot11_BSS_type_infrastructure
,
1667 error
= WlanConnect_function_(
1668 client_
, &interface_guid_
, &wlan_params
, NULL
);
1675 DWORD
WiFiServiceImpl::Disconnect() {
1676 if (client_
== NULL
) {
1678 return ERROR_NOINTERFACE
;
1681 DWORD error
= ERROR_SUCCESS
;
1682 error
= WlanDisconnect_function_(client_
, &interface_guid_
, NULL
);
1686 DWORD
WiFiServiceImpl::SaveTempProfile(const std::string
& network_guid
) {
1687 if (client_
== NULL
) {
1689 return ERROR_NOINTERFACE
;
1692 DWORD error
= ERROR_SUCCESS
;
1693 base::string16 profile_name
= ProfileNameFromGUID(network_guid
);
1694 // TODO(mef): WlanSaveTemporaryProfile is not available on XP. If XP support
1695 // is needed, then different method of saving network profile will have to be
1697 if (WlanSaveTemporaryProfile_function_
) {
1698 error
= WlanSaveTemporaryProfile_function_(client_
,
1700 profile_name
.c_str(),
1706 error
= ERROR_NOT_SUPPORTED
;
1711 DWORD
WiFiServiceImpl::GetProfile(const std::string
& network_guid
,
1712 bool get_plaintext_key
,
1713 std::string
* profile_xml
) {
1714 if (client_
== NULL
) {
1716 return ERROR_NOINTERFACE
;
1719 DWORD error
= ERROR_SUCCESS
;
1720 base::string16 profile_name
= ProfileNameFromGUID(network_guid
);
1721 DWORD flags
= get_plaintext_key
? WLAN_PROFILE_GET_PLAINTEXT_KEY
: 0;
1722 LPWSTR str_profile_xml
= NULL
;
1723 error
= WlanGetProfile_function_(client_
,
1725 profile_name
.c_str(),
1731 if (error
== ERROR_SUCCESS
&& str_profile_xml
!= NULL
) {
1732 *profile_xml
= base::UTF16ToUTF8(str_profile_xml
);
1735 if (str_profile_xml
!= NULL
) {
1736 WlanFreeMemory_function_(str_profile_xml
);
1742 DWORD
WiFiServiceImpl::SetProfile(bool shared
,
1743 const std::string
& profile_xml
,
1745 DWORD error_code
= ERROR_SUCCESS
;
1747 base::string16
profile_xml16(base::UTF8ToUTF16(profile_xml
));
1748 DWORD reason_code
= 0u;
1750 error_code
= WlanSetProfile_function_(client_
,
1752 shared
? 0 : WLAN_PROFILE_USER
,
1753 profile_xml16
.c_str(),
1761 bool WiFiServiceImpl::HaveProfile(const std::string
& network_guid
) {
1762 std::string profile_xml
;
1763 return GetProfile(network_guid
, false, &profile_xml
) == ERROR_SUCCESS
;
1767 DWORD
WiFiServiceImpl::DeleteCreatedProfile(const std::string
& network_guid
) {
1768 base::DictionaryValue
* created_profile
= NULL
;
1769 DWORD error_code
= ERROR_SUCCESS
;
1770 // Check, whether this connection is using new created profile, and remove it.
1771 if (created_profiles_
.GetDictionaryWithoutPathExpansion(
1772 network_guid
, &created_profile
)) {
1773 // Connection has failed, so delete it.
1774 base::string16 profile_name
= ProfileNameFromGUID(network_guid
);
1775 error_code
= WlanDeleteProfile_function_(client_
,
1777 profile_name
.c_str(),
1779 created_profiles_
.RemoveWithoutPathExpansion(network_guid
, NULL
);
1784 std::string
WiFiServiceImpl::WpaEncryptionFromEncryptionType(
1785 EncryptionType encryption_type
) const {
1786 if (encryption_type
== kEncryptionTypeTKIP
)
1787 return kEncryptionTKIP
;
1788 return kEncryptionAES
;
1791 bool WiFiServiceImpl::AuthEncryptionFromSecurity(
1792 const std::string
& security
,
1793 EncryptionType encryption_type
,
1794 std::string
* authentication
,
1795 std::string
* encryption
,
1796 std::string
* key_type
) const {
1797 if (security
== onc::wifi::kSecurityNone
) {
1798 *authentication
= kAuthenticationOpen
;
1799 *encryption
= kEncryptionNone
;
1800 } else if (security
== onc::wifi::kWEP_PSK
) {
1801 *authentication
= kAuthenticationOpen
;
1802 *encryption
= kEncryptionWEP
;
1803 *key_type
= kKeyTypeNetwork
;
1804 } else if (security
== onc::wifi::kWPA_PSK
) {
1805 *authentication
= kAuthenticationWpaPsk
;
1806 *encryption
= WpaEncryptionFromEncryptionType(encryption_type
);
1807 *key_type
= kKeyTypePassphrase
;
1808 } else if (security
== onc::wifi::kWPA2_PSK
) {
1809 *authentication
= kAuthenticationWpa2Psk
;
1810 *encryption
= WpaEncryptionFromEncryptionType(encryption_type
);
1811 *key_type
= kKeyTypePassphrase
;
1818 bool WiFiServiceImpl::CreateProfile(
1819 const NetworkProperties
& network_properties
,
1820 EncryptionType encryption_type
,
1821 std::string
* profile_xml
) {
1822 // Get authentication and encryption values from security.
1823 std::string authentication
;
1824 std::string encryption
;
1825 std::string key_type
;
1826 bool valid
= AuthEncryptionFromSecurity(network_properties
.security
,
1834 // Generate profile XML.
1835 XmlWriter xml_writer
;
1836 xml_writer
.StartWriting();
1837 xml_writer
.StartElement("WLANProfile");
1838 xml_writer
.AddAttribute(
1840 "http://www.microsoft.com/networking/WLAN/profile/v1");
1841 xml_writer
.WriteElement("name", network_properties
.guid
);
1842 xml_writer
.StartElement("SSIDConfig");
1843 xml_writer
.StartElement("SSID");
1844 xml_writer
.WriteElement("name", network_properties
.ssid
);
1845 xml_writer
.EndElement(); // Ends "SSID" element.
1846 xml_writer
.EndElement(); // Ends "SSIDConfig" element.
1847 xml_writer
.WriteElement("connectionType", "ESS");
1848 xml_writer
.WriteElement("connectionMode", "manual");
1849 xml_writer
.StartElement("MSM");
1850 xml_writer
.StartElement("security");
1851 xml_writer
.StartElement("authEncryption");
1852 xml_writer
.WriteElement("authentication", authentication
);
1853 xml_writer
.WriteElement("encryption", encryption
);
1854 xml_writer
.WriteElement("useOneX", "false");
1855 xml_writer
.EndElement(); // Ends "authEncryption" element.
1856 if (!key_type
.empty()) {
1857 xml_writer
.StartElement("sharedKey");
1858 xml_writer
.WriteElement("keyType", key_type
);
1859 xml_writer
.WriteElement("protected", "false");
1860 xml_writer
.WriteElement("keyMaterial", network_properties
.password
);
1861 xml_writer
.EndElement(); // Ends "sharedKey" element.
1863 xml_writer
.EndElement(); // Ends "security" element.
1864 xml_writer
.EndElement(); // Ends "MSM" element.
1865 xml_writer
.EndElement(); // Ends "WLANProfile" element.
1866 xml_writer
.StopWriting();
1867 *profile_xml
= xml_writer
.GetWrittenString();
1872 void WiFiServiceImpl::NotifyNetworkListChanged(const NetworkList
& networks
) {
1873 if (network_list_changed_observer_
.is_null())
1876 NetworkGuidList current_networks
;
1877 for (NetworkList::const_iterator it
= networks
.begin();
1878 it
!= networks
.end();
1880 current_networks
.push_back(it
->guid
);
1883 message_loop_proxy_
->PostTask(
1885 base::Bind(network_list_changed_observer_
, current_networks
));
1888 void WiFiServiceImpl::NotifyNetworkChanged(const std::string
& network_guid
) {
1889 if (enable_notify_network_changed_
&& !networks_changed_observer_
.is_null()) {
1890 DVLOG(1) << "NotifyNetworkChanged: " << network_guid
;
1891 NetworkGuidList
changed_networks(1, network_guid
);
1892 message_loop_proxy_
->PostTask(
1894 base::Bind(networks_changed_observer_
, changed_networks
));
1898 WiFiService
* WiFiService::Create() { return new WiFiServiceImpl(); }