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 ~WiFiServiceImpl() override
;
179 // WiFiService interface implementation.
181 scoped_refptr
<base::SequencedTaskRunner
> task_runner
) override
;
183 void UnInitialize() override
;
185 void GetProperties(const std::string
& network_guid
,
186 base::DictionaryValue
* properties
,
187 std::string
* error
) override
;
189 void GetManagedProperties(const std::string
& network_guid
,
190 base::DictionaryValue
* managed_properties
,
191 std::string
* error
) override
;
193 void GetState(const std::string
& network_guid
,
194 base::DictionaryValue
* properties
,
195 std::string
* error
) override
;
197 void SetProperties(const std::string
& network_guid
,
198 scoped_ptr
<base::DictionaryValue
> properties
,
199 std::string
* error
) override
;
201 void CreateNetwork(bool shared
,
202 scoped_ptr
<base::DictionaryValue
> properties
,
203 std::string
* network_guid
,
204 std::string
* error
) override
;
206 void GetVisibleNetworks(const std::string
& network_type
,
207 base::ListValue
* network_list
,
208 bool include_details
) override
;
210 void RequestNetworkScan() override
;
212 void StartConnect(const std::string
& network_guid
,
213 std::string
* error
) override
;
215 void StartDisconnect(const std::string
& network_guid
,
216 std::string
* error
) override
;
218 void GetKeyFromSystem(const std::string
& network_guid
,
219 std::string
* key_data
,
220 std::string
* error
) override
;
222 void SetEventObservers(
223 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
,
224 const NetworkGuidListCallback
& networks_changed_observer
,
225 const NetworkGuidListCallback
& network_list_changed_observer
) override
;
227 void RequestConnectedNetworkUpdate() override
{}
229 void GetConnectedNetworkSSID(std::string
* ssid
, std::string
* error
) override
;
232 typedef int32 EncryptionType
;
233 enum EncryptionTypeEnum
{
234 kEncryptionTypeAny
= 0,
235 kEncryptionTypeAES
= 1,
236 kEncryptionTypeTKIP
= 2
239 // Static callback for Windows WLAN_NOTIFICATION. Calls OnWlanNotification
240 // on WiFiServiceImpl passed back as |context|.
241 static void __stdcall
OnWlanNotificationCallback(
242 PWLAN_NOTIFICATION_DATA wlan_notification_data
,
245 // Callback for Windows WLAN_NOTIFICATION. Called on random thread from
246 // OnWlanNotificationCallback. Handles network connectivity and scan complete
247 // notification and posts tasks to main thread.
248 void OnWlanNotification(PWLAN_NOTIFICATION_DATA wlan_notification_data
);
250 // Handles NetworkScanComplete notification on main thread. Sends
251 // |NetworkListChanged| event with new list of visible networks.
252 void OnNetworkScanCompleteOnMainThread();
254 // Wait up to |kMaxAttempts| with |kAttemptDelayMs| delay for connection
255 // to network with |network_guid|. Reset DHCP and Notify that |NetworkChanged|
257 void WaitForNetworkConnect(const std::string
& network_guid
, int attempt
);
259 // Check |error_code| and if is not |ERROR_SUCCESS|, then store |error_name|
261 bool CheckError(DWORD error_code
,
262 const std::string
& error_name
,
263 std::string
* error
) const;
265 // Return |iterator| to network identified by |network_guid| in |networks|
267 NetworkList::iterator
FindNetwork(NetworkList
& networks
,
268 const std::string
& network_guid
);
270 // Save currently connected network profile so it can be re-connected later.
271 DWORD
SaveCurrentConnectedNetwork(const NetworkProperties
& properties
);
273 // Sort networks, so connected/connecting is up front, then by type:
274 // Ethernet, WiFi, Cellular, VPN
275 static void SortNetworks(NetworkList
* networks
);
277 // Open a WLAN client handle, register for WLAN notifications.
278 DWORD
OpenClientHandle();
280 // Reset DHCP on wireless network to work around an issue when Windows
281 // takes forever to connect to the network, e.g. after Chromecast
285 // Find |adapter_index_map| by |interface_guid| for DHCP reset.
286 DWORD
FindAdapterIndexMapByGUID(const GUID
& interface_guid
,
287 IP_ADAPTER_INDEX_MAP
* adapter_index_map
);
289 // Avoid the network location wizard to pop up when network is connected.
290 // Preserve current value in |saved_nw_category_wizard_|.
291 DWORD
DisableNwCategoryWizard();
293 // Restore network location wizard to value saved by DisableNwCategoryWizard.
294 DWORD
RestoreNwCategoryWizard();
296 // Ensure that |client_| handle is initialized.
297 DWORD
EnsureInitialized();
299 // Close |client_| handle if it is open.
300 DWORD
CloseClientHandle();
302 // Get |profile_name| from unique |network_guid|.
303 base::string16
ProfileNameFromGUID(const std::string
& network_guid
) const {
304 return base::UTF8ToUTF16(network_guid
);
307 // Get |dot11_ssid| from unique |network_guid|.
308 DOT11_SSID
SSIDFromGUID(const std::string
& network_guid
) const;
310 // Get unique |network_guid| string based on |dot11_ssid|.
311 std::string
GUIDFromSSID(const DOT11_SSID
& dot11_ssid
) const {
312 return std::string(reinterpret_cast<const char*>(dot11_ssid
.ucSSID
),
313 dot11_ssid
.uSSIDLength
);
316 // Get network |ssid| string based on |wlan|.
317 std::string
SSIDFromWLAN(const WLAN_AVAILABLE_NETWORK
& wlan
) const {
318 return GUIDFromSSID(wlan
.dot11Ssid
);
321 // Get unique |network_guid| string based on |wlan|.
322 std::string
GUIDFromWLAN(const WLAN_AVAILABLE_NETWORK
& wlan
) const {
323 return SSIDFromWLAN(wlan
);
326 // Deduce |onc::wifi| security from |alg|.
327 std::string
SecurityFromDot11AuthAlg(DOT11_AUTH_ALGORITHM alg
) const;
329 // Deduce |onc::connection_state| from |wlan_state|.
330 std::string
ConnectionStateFromInterfaceState(
331 WLAN_INTERFACE_STATE wlan_state
) const;
333 // Convert |EncryptionType| into WPA(2) encryption type string.
334 std::string
WpaEncryptionFromEncryptionType(
335 EncryptionType encryption_type
) const;
337 // Deduce WLANProfile |authEncryption| values from |onc::wifi| security.
338 bool AuthEncryptionFromSecurity(const std::string
& security
,
339 EncryptionType encryption_type
,
340 std::string
* authentication
,
341 std::string
* encryption
,
342 std::string
* key_type
) const;
344 // Populate |properties| based on |wlan|.
345 void NetworkPropertiesFromAvailableNetwork(const WLAN_AVAILABLE_NETWORK
& wlan
,
346 NetworkProperties
* properties
);
348 // Update |properties| based on bss info from |wlan_bss_list|. If |bssid| in
349 // |properties| is not empty, then it is not changed and |frequency| is set
350 // based on that bssid.
351 void UpdateNetworkPropertiesFromBssList(const std::string
& network_guid
,
352 const WLAN_BSS_LIST
& wlan_bss_list
,
353 NetworkProperties
* properties
);
355 // Get the list of visible wireless networks.
356 DWORD
GetVisibleNetworkList(NetworkList
* network_list
);
358 // Get properties of the network currently used (connected or in transition)
359 // by interface. Populate |current_properties| on success.
360 DWORD
GetCurrentProperties(NetworkProperties
* current_properties
);
362 // Get the SSID of the network currently used (connected or in transition)
363 // by interface. Populate |ssid| on success. This is a stripped down version
364 // of GetCurrentProperties that doesn't use the BSS list;
365 DWORD
GetCurrentSSID(std::string
* ssid
);
367 // Connect to network |network_guid| using previosly stored profile if exists,
368 // or just network sid. If |frequency| is not |kFrequencyUnknown| then
369 // connects only to BSS which uses that frequency and returns
370 // |ERROR_NOT_FOUND| if such BSS cannot be found.
371 DWORD
Connect(const std::string
& network_guid
, Frequency frequency
);
373 // Disconnect from currently connected network if any.
376 // Get desired connection freqency if it was set using |SetProperties|.
377 // Default to |kFrequencyAny|.
378 Frequency
GetFrequencyToConnect(const std::string
& network_guid
) const;
380 // Get DOT11_BSSID_LIST of desired BSSIDs to connect to |ssid| network on
381 // given |frequency|.
382 DWORD
GetDesiredBssList(DOT11_SSID
& ssid
,
384 scoped_ptr
<DOT11_BSSID_LIST
>* desired_list
);
386 // Normalizes |frequency_in_mhz| into one of |Frequency| values.
387 Frequency
GetNormalizedFrequency(int frequency_in_mhz
) const;
389 // Create |profile_xml| based on |network_properties|. If |encryption_type|
390 // is |kEncryptionTypeAny| applies the type most suitable for parameters in
391 // |network_properties|.
392 bool CreateProfile(const NetworkProperties
& network_properties
,
393 EncryptionType encryption_type
,
394 std::string
* profile_xml
);
396 // Save temporary wireless profile for |network_guid|.
397 DWORD
SaveTempProfile(const std::string
& network_guid
);
399 // Get previously stored |profile_xml| for |network_guid|.
400 // If |get_plaintext_key| is true, and process has sufficient privileges, then
401 // <sharedKey> data in |profile_xml| will be unprotected.
402 DWORD
GetProfile(const std::string
& network_guid
,
403 bool get_plaintext_key
,
404 std::string
* profile_xml
);
406 // Set |profile_xml| to current user or all users depending on |shared| flag.
407 // If |overwrite| is false, then returns an error if profile exists.
408 DWORD
SetProfile(bool shared
, const std::string
& profile_xml
, bool overwrite
);
410 // Return true if there is previously stored profile xml for |network_guid|.
411 bool HaveProfile(const std::string
& network_guid
);
413 // Delete profile that was created, but failed to connect.
414 DWORD
DeleteCreatedProfile(const std::string
& network_guid
);
416 // Notify |network_list_changed_observer_| that list of visible networks has
417 // changed to |networks|.
418 void NotifyNetworkListChanged(const NetworkList
& networks
);
420 // Notify |networks_changed_observer_| that network |network_guid| status has
422 void NotifyNetworkChanged(const std::string
& network_guid
);
424 // Load WlanApi.dll from SystemDirectory and get Api function pointers.
425 DWORD
LoadWlanLibrary();
426 // Instance of WlanApi.dll.
427 HINSTANCE wlan_api_library_
;
428 // WlanApi function pointers
429 WlanConnectFunction WlanConnect_function_
;
430 WlanCloseHandleFunction WlanCloseHandle_function_
;
431 WlanDeleteProfileFunction WlanDeleteProfile_function_
;
432 WlanDisconnectFunction WlanDisconnect_function_
;
433 WlanEnumInterfacesFunction WlanEnumInterfaces_function_
;
434 WlanFreeMemoryFunction WlanFreeMemory_function_
;
435 WlanGetAvailableNetworkListFunction WlanGetAvailableNetworkList_function_
;
436 // WlanGetNetworkBssList function may not be avaiable on Windows XP.
437 WlanGetNetworkBssListFunction WlanGetNetworkBssList_function_
;
438 WlanGetProfileFunction WlanGetProfile_function_
;
439 WlanOpenHandleFunction WlanOpenHandle_function_
;
440 WlanQueryInterfaceFunction WlanQueryInterface_function_
;
441 WlanRegisterNotificationFunction WlanRegisterNotification_function_
;
442 WlanScanFunction WlanScan_function_
;
443 WlanSetProfileFunction WlanSetProfile_function_
;
444 // WlanSaveTemporaryProfile function may not be avaiable on Windows XP.
445 WlanSaveTemporaryProfileFunction WlanSaveTemporaryProfile_function_
;
447 // WLAN service handle.
449 // GUID of the currently connected interface, if any, otherwise the GUID of
450 // one of the WLAN interfaces.
451 GUID interface_guid_
;
452 // Temporary storage of network properties indexed by |network_guid|. Persist
454 base::DictionaryValue connect_properties_
;
455 // Preserved WLAN profile xml.
456 std::map
<std::string
, std::string
> saved_profiles_xml_
;
457 // Created WLAN Profiles, indexed by |network_guid|. Contains xml with TKIP
458 // encryption type saved by |CreateNetwork| if applicable. Profile has to be
459 // deleted if connection fails. Implicitly created profiles have to be deleted
460 // if connection succeeds. Persist only in memory.
461 base::DictionaryValue created_profiles_
;
462 // Observer to get notified when network(s) have changed (e.g. connect).
463 NetworkGuidListCallback networks_changed_observer_
;
464 // Observer to get notified when network list has changed (scan complete).
465 NetworkGuidListCallback network_list_changed_observer_
;
466 // Saved value of network location wizard show value.
467 scoped_ptr
<DWORD
> saved_nw_category_wizard_
;
468 // Task runner to post events on UI thread.
469 scoped_refptr
<base::SingleThreadTaskRunner
> event_task_runner_
;
470 // Task runner for worker tasks.
471 scoped_refptr
<base::SequencedTaskRunner
> task_runner_
;
472 // If |false|, then |networks_changed_observer_| is not notified.
473 bool enable_notify_network_changed_
;
474 // Number of attempts to check that network has connected successfully.
475 static const int kMaxAttempts
= 100;
476 // Delay between attempts to check that network has connected successfully.
477 static const int kAttemptDelayMs
= 100;
478 DISALLOW_COPY_AND_ASSIGN(WiFiServiceImpl
);
481 WiFiServiceImpl::WiFiServiceImpl()
482 : wlan_api_library_(NULL
),
483 WlanConnect_function_(NULL
),
484 WlanCloseHandle_function_(NULL
),
485 WlanDeleteProfile_function_(NULL
),
486 WlanDisconnect_function_(NULL
),
487 WlanEnumInterfaces_function_(NULL
),
488 WlanFreeMemory_function_(NULL
),
489 WlanGetAvailableNetworkList_function_(NULL
),
490 WlanGetNetworkBssList_function_(NULL
),
491 WlanGetProfile_function_(NULL
),
492 WlanOpenHandle_function_(NULL
),
493 WlanRegisterNotification_function_(NULL
),
494 WlanSaveTemporaryProfile_function_(NULL
),
495 WlanScan_function_(NULL
),
496 WlanSetProfile_function_(NULL
),
498 enable_notify_network_changed_(true) {}
500 WiFiServiceImpl::~WiFiServiceImpl() { UnInitialize(); }
502 void WiFiServiceImpl::Initialize(
503 scoped_refptr
<base::SequencedTaskRunner
> task_runner
) {
505 task_runner_
.swap(task_runner
);
506 // Restore NwCategoryWizard in case if we crashed during connect.
507 RestoreNwCategoryWizard();
511 void WiFiServiceImpl::UnInitialize() {
515 void WiFiServiceImpl::GetProperties(const std::string
& network_guid
,
516 base::DictionaryValue
* properties
,
517 std::string
* error
) {
518 DWORD error_code
= EnsureInitialized();
519 if (CheckError(error_code
, kErrorWiFiService
, error
))
522 NetworkProperties connected_properties
;
523 error_code
= GetCurrentProperties(&connected_properties
);
524 if (error_code
== ERROR_SUCCESS
&&
525 connected_properties
.guid
== network_guid
) {
526 properties
->Swap(connected_properties
.ToValue(false).get());
530 NetworkList network_list
;
531 error_code
= GetVisibleNetworkList(&network_list
);
532 if (error_code
== ERROR_SUCCESS
) {
533 NetworkList::const_iterator it
= FindNetwork(network_list
, network_guid
);
534 if (it
!= network_list
.end()) {
535 DVLOG(1) << "Get Properties: " << network_guid
<< ":"
536 << it
->connection_state
;
537 properties
->Swap(it
->ToValue(false).get());
540 error_code
= ERROR_NOT_FOUND
;
543 CheckError(error_code
, kErrorWiFiService
, error
);
546 void WiFiServiceImpl::GetManagedProperties(
547 const std::string
& network_guid
,
548 base::DictionaryValue
* managed_properties
,
549 std::string
* error
) {
550 CheckError(ERROR_CALL_NOT_IMPLEMENTED
, kErrorWiFiService
, error
);
553 void WiFiServiceImpl::GetState(const std::string
& network_guid
,
554 base::DictionaryValue
* properties
,
555 std::string
* error
) {
556 CheckError(ERROR_CALL_NOT_IMPLEMENTED
, kErrorWiFiService
, error
);
559 void WiFiServiceImpl::SetProperties(
560 const std::string
& network_guid
,
561 scoped_ptr
<base::DictionaryValue
> properties
,
562 std::string
* error
) {
563 // Temporary preserve WiFi properties (desired frequency, wifi password) to
564 // use in StartConnect.
565 DCHECK(properties
.get());
566 if (!properties
->HasKey(onc::network_type::kWiFi
)) {
567 DVLOG(0) << "Missing WiFi properties:" << *properties
;
568 *error
= kErrorWiFiService
;
572 base::DictionaryValue
* existing_properties
;
573 // If the network properties already exist, don't override previously set
574 // properties, unless they are set in |properties|.
575 if (connect_properties_
.GetDictionaryWithoutPathExpansion(
576 network_guid
, &existing_properties
)) {
577 existing_properties
->MergeDictionary(properties
.get());
579 connect_properties_
.SetWithoutPathExpansion(network_guid
,
580 properties
.release());
584 void WiFiServiceImpl::CreateNetwork(
586 scoped_ptr
<base::DictionaryValue
> properties
,
587 std::string
* network_guid
,
588 std::string
* error
) {
589 DWORD error_code
= EnsureInitialized();
590 if (CheckError(error_code
, kErrorWiFiService
, error
))
593 NetworkProperties network_properties
;
594 if (!network_properties
.UpdateFromValue(*properties
)) {
595 CheckError(ERROR_INVALID_DATA
, kErrorWiFiService
, error
);
599 network_properties
.guid
= network_properties
.ssid
;
600 std::string profile_xml
;
601 if (!CreateProfile(network_properties
, kEncryptionTypeAny
, &profile_xml
)) {
602 CheckError(ERROR_INVALID_DATA
, kErrorWiFiService
, error
);
606 error_code
= SetProfile(shared
, profile_xml
, false);
607 if (CheckError(error_code
, kErrorWiFiService
, error
)) {
608 DVLOG(0) << profile_xml
;
612 // WAP and WAP2 networks could use either AES or TKIP encryption type.
613 // Preserve alternative profile to use in case if connection with default
614 // encryption type fails.
615 std::string tkip_profile_xml
;
616 if (!CreateProfile(network_properties
,
618 &tkip_profile_xml
)) {
619 CheckError(ERROR_INVALID_DATA
, kErrorWiFiService
, error
);
623 if (tkip_profile_xml
!= profile_xml
) {
624 scoped_ptr
<base::DictionaryValue
> tkip_profile(new base::DictionaryValue());
625 tkip_profile
->SetString(kProfileXmlKey
, tkip_profile_xml
);
626 tkip_profile
->SetBoolean(kProfileSharedKey
, shared
);
627 created_profiles_
.SetWithoutPathExpansion(network_properties
.guid
,
628 tkip_profile
.release());
631 *network_guid
= network_properties
.guid
;
634 void WiFiServiceImpl::GetVisibleNetworks(const std::string
& network_type
,
635 base::ListValue
* network_list
,
636 bool include_details
) {
637 if (!network_type
.empty() &&
638 network_type
!= onc::network_type::kAllTypes
&&
639 network_type
!= onc::network_type::kWiFi
) {
643 DWORD error
= EnsureInitialized();
644 if (error
== ERROR_SUCCESS
) {
645 NetworkList networks
;
646 error
= GetVisibleNetworkList(&networks
);
647 if (error
== ERROR_SUCCESS
&& !networks
.empty()) {
648 SortNetworks(&networks
);
649 for (NetworkList::const_iterator it
= networks
.begin();
650 it
!= networks
.end();
652 scoped_ptr
<base::DictionaryValue
> network(
653 it
->ToValue(!include_details
));
654 network_list
->Append(network
.release());
660 void WiFiServiceImpl::RequestNetworkScan() {
661 DWORD error
= EnsureInitialized();
662 if (error
== ERROR_SUCCESS
) {
663 WlanScan_function_(client_
, &interface_guid_
, NULL
, NULL
, NULL
);
667 void WiFiServiceImpl::StartConnect(const std::string
& network_guid
,
668 std::string
* error
) {
669 DVLOG(1) << "Start Connect: " << network_guid
;
670 DWORD error_code
= EnsureInitialized();
671 if (CheckError(error_code
, kErrorWiFiService
, error
))
674 // Check, if the network is already connected on desired frequency.
675 Frequency frequency
= GetFrequencyToConnect(network_guid
);
676 NetworkProperties properties
;
677 GetCurrentProperties(&properties
);
678 bool already_connected
=
679 network_guid
== properties
.guid
&&
680 properties
.connection_state
== onc::connection_state::kConnected
&&
681 (frequency
== kFrequencyAny
|| frequency
== properties
.frequency
);
683 // Connect only if network |network_guid| is not connected already.
684 if (!already_connected
) {
685 SaveCurrentConnectedNetwork(properties
);
686 error_code
= Connect(network_guid
, frequency
);
688 if (error_code
== ERROR_SUCCESS
) {
689 // Notify that previously connected network has changed.
690 NotifyNetworkChanged(properties
.guid
);
691 // Start waiting for network connection state change.
692 if (!networks_changed_observer_
.is_null()) {
693 DisableNwCategoryWizard();
694 // Disable automatic network change notifications as they get fired
695 // when network is just connected, but not yet accessible (doesn't
696 // have valid IP address).
697 enable_notify_network_changed_
= false;
698 WaitForNetworkConnect(network_guid
, 0);
701 } else if (error_code
== ERROR_ACCESS_DENIED
) {
702 CheckError(error_code
, kErrorNotConfigured
, error
);
704 CheckError(error_code
, kErrorWiFiService
, error
);
708 void WiFiServiceImpl::StartDisconnect(const std::string
& network_guid
,
709 std::string
* error
) {
710 DVLOG(1) << "Start Disconnect: " << network_guid
;
711 DWORD error_code
= EnsureInitialized();
712 if (CheckError(error_code
, kErrorWiFiService
, error
))
715 // Check, if the network is currently connected.
716 NetworkProperties properties
;
717 GetCurrentProperties(&properties
);
718 if (network_guid
== properties
.guid
) {
719 if (properties
.connection_state
== onc::connection_state::kConnected
)
720 SaveCurrentConnectedNetwork(properties
);
721 error_code
= Disconnect();
722 if (error_code
== ERROR_SUCCESS
) {
723 NotifyNetworkChanged(network_guid
);
727 CheckError(error_code
, kErrorWiFiService
, error
);
730 void WiFiServiceImpl::GetKeyFromSystem(const std::string
& network_guid
,
731 std::string
* key_data
,
732 std::string
* error
) {
733 DWORD error_code
= EnsureInitialized();
734 if (CheckError(error_code
, kErrorWiFiService
, error
))
737 std::string profile_xml
;
738 error_code
= GetProfile(network_guid
, true, &profile_xml
);
739 if (CheckError(error_code
, kErrorWiFiService
, error
))
742 const char kSharedKeyElement
[] = "sharedKey";
743 const char kProtectedElement
[] = "protected";
744 const char kKeyMaterialElement
[] = "keyMaterial";
746 // Quick check to verify presence of <sharedKey> element.
747 if (profile_xml
.find(kSharedKeyElement
) == std::string::npos
) {
748 *error
= kErrorWiFiService
;
753 if (reader
.Load(profile_xml
)) {
754 while (reader
.Read()) {
755 reader
.SkipToElement();
756 if (reader
.NodeName() == kSharedKeyElement
) {
757 while (reader
.Read()) {
758 reader
.SkipToElement();
759 if (reader
.NodeName() == kKeyMaterialElement
) {
760 reader
.ReadElementContent(key_data
);
761 } else if (reader
.NodeName() == kProtectedElement
) {
762 std::string protected_data
;
763 reader
.ReadElementContent(&protected_data
);
764 // Without UAC privilege escalation call to |GetProfile| with
765 // |WLAN_PROFILE_GET_PLAINTEXT_KEY| flag returns success, but has
766 // protected keyMaterial. Report an error in this case.
767 if (protected_data
!= "false") {
768 *error
= kErrorWiFiService
;
778 // Did not find passphrase in the profile.
779 *error
= kErrorWiFiService
;
782 void WiFiServiceImpl::SetEventObservers(
783 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
,
784 const NetworkGuidListCallback
& networks_changed_observer
,
785 const NetworkGuidListCallback
& network_list_changed_observer
) {
786 DWORD error_code
= EnsureInitialized();
787 if (error_code
!= ERROR_SUCCESS
)
789 event_task_runner_
.swap(task_runner
);
790 if (!networks_changed_observer_
.is_null() ||
791 !network_list_changed_observer_
.is_null()) {
792 // Stop listening to WLAN notifications.
793 WlanRegisterNotification_function_(client_
,
794 WLAN_NOTIFICATION_SOURCE_NONE
,
796 OnWlanNotificationCallback
,
801 networks_changed_observer_
= networks_changed_observer
;
802 network_list_changed_observer_
= network_list_changed_observer
;
803 if (!networks_changed_observer_
.is_null() ||
804 !network_list_changed_observer_
.is_null()) {
805 // Start listening to WLAN notifications.
806 WlanRegisterNotification_function_(client_
,
807 WLAN_NOTIFICATION_SOURCE_ALL
,
809 OnWlanNotificationCallback
,
816 void WiFiServiceImpl::GetConnectedNetworkSSID(std::string
* ssid
,
817 std::string
* error
) {
818 DWORD error_code
= EnsureInitialized();
819 if (CheckError(error_code
, kErrorWiFiService
, error
))
821 std::string current_ssid
;
822 error_code
= GetCurrentSSID(¤t_ssid
);
823 if (CheckError(error_code
, kErrorWiFiService
, error
))
825 *ssid
= current_ssid
;
828 void WiFiServiceImpl::OnWlanNotificationCallback(
829 PWLAN_NOTIFICATION_DATA wlan_notification_data
,
831 WiFiServiceImpl
* service
= reinterpret_cast<WiFiServiceImpl
*>(context
);
832 service
->OnWlanNotification(wlan_notification_data
);
835 void WiFiServiceImpl::OnWlanNotification(
836 PWLAN_NOTIFICATION_DATA wlan_notification_data
) {
837 if (event_task_runner_
.get() == NULL
)
839 switch (wlan_notification_data
->NotificationCode
) {
840 case wlan_notification_acm_disconnected
:
841 case wlan_notification_acm_connection_complete
:
842 case wlan_notification_acm_connection_attempt_fail
: {
843 PWLAN_CONNECTION_NOTIFICATION_DATA wlan_connection_data
=
844 reinterpret_cast<PWLAN_CONNECTION_NOTIFICATION_DATA
>(
845 wlan_notification_data
->pData
);
846 event_task_runner_
->PostTask(
847 FROM_HERE
, base::Bind(&WiFiServiceImpl::NotifyNetworkChanged
,
848 base::Unretained(this),
849 GUIDFromSSID(wlan_connection_data
->dot11Ssid
)));
852 case wlan_notification_acm_scan_complete
:
853 case wlan_notification_acm_interface_removal
:
854 event_task_runner_
->PostTask(
856 base::Bind(&WiFiServiceImpl::OnNetworkScanCompleteOnMainThread
,
857 base::Unretained(this)));
862 void WiFiServiceImpl::OnNetworkScanCompleteOnMainThread() {
863 NetworkList networks
;
864 // Get current list of visible networks and notify that network list has
866 DWORD error
= GetVisibleNetworkList(&networks
);
867 if (error
!= ERROR_SUCCESS
)
869 NotifyNetworkListChanged(networks
);
872 void WiFiServiceImpl::WaitForNetworkConnect(const std::string
& network_guid
,
874 // If network didn't get connected in |kMaxAttempts|, then try to connect
875 // using different profile if it was created recently.
876 if (attempt
> kMaxAttempts
) {
877 LOG(ERROR
) << kMaxAttempts
<< " attempts exceeded waiting for connect to "
880 base::DictionaryValue
* created_profile
= NULL
;
881 // Check, whether this connection is using newly created profile.
882 if (created_profiles_
.GetDictionaryWithoutPathExpansion(
883 network_guid
, &created_profile
)) {
884 std::string tkip_profile_xml
;
886 // Check, if this connection there is alternative TKIP profile xml that
887 // should be tried. If there is, then set it up and try to connect again.
888 if (created_profile
->GetString(kProfileXmlKey
, &tkip_profile_xml
) &&
889 created_profile
->GetBoolean(kProfileSharedKey
, &shared
)) {
890 // Remove TKIP profile xml, so it will not be tried again.
891 created_profile
->Remove(kProfileXmlKey
, NULL
);
892 created_profile
->Remove(kProfileSharedKey
, NULL
);
893 DWORD error_code
= SetProfile(shared
, tkip_profile_xml
, true);
894 if (error_code
== ERROR_SUCCESS
) {
895 // Try to connect with new profile.
896 error_code
= Connect(network_guid
,
897 GetFrequencyToConnect(network_guid
));
898 if (error_code
== ERROR_SUCCESS
) {
899 // Start waiting again.
900 WaitForNetworkConnect(network_guid
, 0);
903 LOG(ERROR
) << "Failed to set created profile for " << network_guid
904 << " error=" << error_code
;
908 // Connection has failed, so delete bad created profile.
909 DWORD error_code
= DeleteCreatedProfile(network_guid
);
910 if (error_code
!= ERROR_SUCCESS
) {
911 LOG(ERROR
) << "Failed to delete created profile for " << network_guid
912 << " error=" << error_code
;
916 // Restore automatic network change notifications and stop waiting.
917 enable_notify_network_changed_
= true;
918 RestoreNwCategoryWizard();
921 NetworkProperties current_properties
;
922 DWORD error
= GetCurrentProperties(¤t_properties
);
923 if (network_guid
== current_properties
.guid
&&
924 current_properties
.connection_state
==
925 onc::connection_state::kConnected
) {
926 DVLOG(1) << "WiFi Connected, Reset DHCP: " << network_guid
;
927 // Even though wireless network is now connected, it may still be unusable,
928 // e.g. after Chromecast device reset. Reset DHCP on wireless network to
929 // work around this issue.
931 if (error
!= ERROR_SUCCESS
)
933 // There is no need to keep created profile as network is connected.
934 created_profiles_
.RemoveWithoutPathExpansion(network_guid
, NULL
);
935 // Restore previously suppressed notifications.
936 enable_notify_network_changed_
= true;
937 RestoreNwCategoryWizard();
938 NotifyNetworkChanged(network_guid
);
940 // Continue waiting for network connection state change.
941 task_runner_
->PostDelayedTask(
943 base::Bind(&WiFiServiceImpl::WaitForNetworkConnect
,
944 base::Unretained(this),
947 base::TimeDelta::FromMilliseconds(kAttemptDelayMs
));
951 bool WiFiServiceImpl::CheckError(DWORD error_code
,
952 const std::string
& error_name
,
953 std::string
* error
) const {
954 if (error_code
!= ERROR_SUCCESS
) {
955 DLOG(ERROR
) << "WiFiService Error " << error_code
<< ": " << error_name
;
962 NetworkList::iterator
WiFiServiceImpl::FindNetwork(
963 NetworkList
& networks
,
964 const std::string
& network_guid
) {
965 for (NetworkList::iterator it
= networks
.begin(); it
!= networks
.end();
967 if (it
->guid
== network_guid
)
970 return networks
.end();
973 DWORD
WiFiServiceImpl::SaveCurrentConnectedNetwork(
974 const NetworkProperties
& current_properties
) {
975 DWORD error
= ERROR_SUCCESS
;
976 // Save currently connected network.
977 if (!current_properties
.guid
.empty() &&
978 current_properties
.connection_state
==
979 onc::connection_state::kConnected
) {
980 error
= SaveTempProfile(current_properties
.guid
);
985 void WiFiServiceImpl::SortNetworks(NetworkList
* networks
) {
986 networks
->sort(NetworkProperties::OrderByType
);
989 DWORD
WiFiServiceImpl::LoadWlanLibrary() {
990 // Use an absolute path to load the DLL to avoid DLL preloading attacks.
992 if (!PathService::Get(base::DIR_SYSTEM
, &path
)) {
993 LOG(ERROR
) << "Unable to get system path.";
994 return ERROR_NOT_FOUND
;
996 wlan_api_library_
= ::LoadLibraryEx(path
.Append(kWlanApiDll
).value().c_str(),
998 LOAD_WITH_ALTERED_SEARCH_PATH
);
999 if (!wlan_api_library_
) {
1000 LOG(ERROR
) << "Unable to load WlanApi.dll.";
1001 return ERROR_NOT_FOUND
;
1004 // Initialize WlanApi function pointers
1005 WlanConnect_function_
=
1006 reinterpret_cast<WlanConnectFunction
>(
1007 ::GetProcAddress(wlan_api_library_
, kWlanConnect
));
1008 WlanCloseHandle_function_
=
1009 reinterpret_cast<WlanCloseHandleFunction
>(
1010 ::GetProcAddress(wlan_api_library_
, kWlanCloseHandle
));
1011 WlanDeleteProfile_function_
=
1012 reinterpret_cast<WlanDeleteProfileFunction
>(
1013 ::GetProcAddress(wlan_api_library_
, kWlanDeleteProfile
));
1014 WlanDisconnect_function_
=
1015 reinterpret_cast<WlanDisconnectFunction
>(
1016 ::GetProcAddress(wlan_api_library_
, kWlanDisconnect
));
1017 WlanEnumInterfaces_function_
=
1018 reinterpret_cast<WlanEnumInterfacesFunction
>(
1019 ::GetProcAddress(wlan_api_library_
, kWlanEnumInterfaces
));
1020 WlanFreeMemory_function_
=
1021 reinterpret_cast<WlanFreeMemoryFunction
>(
1022 ::GetProcAddress(wlan_api_library_
, kWlanFreeMemory
));
1023 WlanGetAvailableNetworkList_function_
=
1024 reinterpret_cast<WlanGetAvailableNetworkListFunction
>(
1025 ::GetProcAddress(wlan_api_library_
, kWlanGetAvailableNetworkList
));
1026 WlanGetNetworkBssList_function_
=
1027 reinterpret_cast<WlanGetNetworkBssListFunction
>(
1028 ::GetProcAddress(wlan_api_library_
, kWlanGetNetworkBssList
));
1029 WlanGetProfile_function_
=
1030 reinterpret_cast<WlanGetProfileFunction
>(
1031 ::GetProcAddress(wlan_api_library_
, kWlanGetProfile
));
1032 WlanOpenHandle_function_
=
1033 reinterpret_cast<WlanOpenHandleFunction
>(
1034 ::GetProcAddress(wlan_api_library_
, kWlanOpenHandle
));
1035 WlanQueryInterface_function_
=
1036 reinterpret_cast<WlanQueryInterfaceFunction
>(
1037 ::GetProcAddress(wlan_api_library_
, kWlanQueryInterface
));
1038 WlanRegisterNotification_function_
=
1039 reinterpret_cast<WlanRegisterNotificationFunction
>(
1040 ::GetProcAddress(wlan_api_library_
, kWlanRegisterNotification
));
1041 WlanSaveTemporaryProfile_function_
=
1042 reinterpret_cast<WlanSaveTemporaryProfileFunction
>(
1043 ::GetProcAddress(wlan_api_library_
, kWlanSaveTemporaryProfile
));
1044 WlanScan_function_
=
1045 reinterpret_cast<WlanScanFunction
>(
1046 ::GetProcAddress(wlan_api_library_
, kWlanScan
));
1047 WlanSetProfile_function_
=
1048 reinterpret_cast<WlanSetProfileFunction
>(
1049 ::GetProcAddress(wlan_api_library_
, kWlanSetProfile
));
1051 if (!WlanConnect_function_
||
1052 !WlanCloseHandle_function_
||
1053 !WlanDeleteProfile_function_
||
1054 !WlanDisconnect_function_
||
1055 !WlanEnumInterfaces_function_
||
1056 !WlanFreeMemory_function_
||
1057 !WlanGetAvailableNetworkList_function_
||
1058 !WlanGetProfile_function_
||
1059 !WlanOpenHandle_function_
||
1060 !WlanQueryInterface_function_
||
1061 !WlanRegisterNotification_function_
||
1062 !WlanScan_function_
||
1063 !WlanSetProfile_function_
) {
1064 LOG(ERROR
) << "Unable to find required WlanApi function.";
1065 FreeLibrary(wlan_api_library_
);
1066 wlan_api_library_
= NULL
;
1067 return ERROR_NOT_FOUND
;
1070 // Some WlanApi functions may not be available on XP.
1071 if (!WlanGetNetworkBssList_function_
||
1072 !WlanSaveTemporaryProfile_function_
) {
1073 DVLOG(1) << "WlanApi function is not be available on XP.";
1076 return ERROR_SUCCESS
;
1079 DWORD
WiFiServiceImpl::OpenClientHandle() {
1080 DWORD error
= LoadWlanLibrary();
1081 DWORD service_version
= 0;
1083 if (error
!= ERROR_SUCCESS
)
1086 // Open a handle to the service.
1087 error
= WlanOpenHandle_function_(1, NULL
, &service_version
, &client_
);
1089 PWLAN_INTERFACE_INFO_LIST interface_list
= NULL
;
1090 if (error
== ERROR_SUCCESS
) {
1091 // Enumerate wireless interfaces.
1092 error
= WlanEnumInterfaces_function_(client_
, NULL
, &interface_list
);
1093 if (error
== ERROR_SUCCESS
) {
1094 if (interface_list
!= NULL
&& interface_list
->dwNumberOfItems
!= 0) {
1095 // Remember first interface just in case if none are connected.
1096 interface_guid_
= interface_list
->InterfaceInfo
[0].InterfaceGuid
;
1097 // Try to find a connected interface.
1098 for (DWORD itf
= 0; itf
< interface_list
->dwNumberOfItems
; ++itf
) {
1099 if (interface_list
->InterfaceInfo
[itf
].isState
==
1100 wlan_interface_state_connected
) {
1101 // Found connected interface, remember it!
1102 interface_guid_
= interface_list
->InterfaceInfo
[itf
].InterfaceGuid
;
1107 error
= ERROR_NOINTERFACE
;
1111 if (interface_list
!= NULL
)
1112 WlanFreeMemory_function_(interface_list
);
1117 DWORD
WiFiServiceImpl::ResetDHCP() {
1118 IP_ADAPTER_INDEX_MAP adapter_index_map
= {0};
1119 DWORD error
= FindAdapterIndexMapByGUID(interface_guid_
, &adapter_index_map
);
1120 if (error
!= ERROR_SUCCESS
) {
1121 LOG(ERROR
) << error
;
1124 error
= ::IpReleaseAddress(&adapter_index_map
);
1125 if (error
!= ERROR_SUCCESS
) {
1126 if (error
!= ERROR_ADDRESS_NOT_ASSOCIATED
) {
1127 LOG(ERROR
) << error
;
1130 DVLOG(1) << "Ignoring IpReleaseAddress Error: " << error
;
1132 error
= ::IpRenewAddress(&adapter_index_map
);
1133 if (error
!= ERROR_SUCCESS
)
1134 LOG(ERROR
) << error
;
1138 DWORD
WiFiServiceImpl::FindAdapterIndexMapByGUID(
1139 const GUID
& interface_guid
,
1140 IP_ADAPTER_INDEX_MAP
* adapter_index_map
) {
1141 base::string16 guid_string
;
1142 const int kGUIDSize
= 39;
1144 interface_guid
, WriteInto(&guid_string
, kGUIDSize
), kGUIDSize
);
1146 ULONG buffer_length
= 0;
1147 DWORD error
= ::GetInterfaceInfo(NULL
, &buffer_length
);
1148 if (error
== ERROR_INSUFFICIENT_BUFFER
) {
1149 scoped_ptr
<unsigned char[]> buffer(new unsigned char[buffer_length
]);
1150 IP_INTERFACE_INFO
* interface_info
=
1151 reinterpret_cast<IP_INTERFACE_INFO
*>(buffer
.get());
1152 error
= GetInterfaceInfo(interface_info
, &buffer_length
);
1153 if (error
== ERROR_SUCCESS
) {
1154 for (int adapter
= 0; adapter
< interface_info
->NumAdapters
; ++adapter
) {
1156 interface_info
->Adapter
[adapter
].Name
, guid_string
, false)) {
1157 *adapter_index_map
= interface_info
->Adapter
[adapter
];
1166 DWORD
WiFiServiceImpl::DisableNwCategoryWizard() {
1167 base::win::RegKey nw_category_wizard
;
1168 DWORD error
= nw_category_wizard
.Open(HKEY_CURRENT_USER
,
1169 kNwCategoryWizardRegKey
,
1170 KEY_READ
| KEY_SET_VALUE
);
1171 if (error
== ERROR_SUCCESS
) {
1172 // Save current value if present.
1173 if (nw_category_wizard
.HasValue(kNwCategoryWizardRegValue
)) {
1175 error
= nw_category_wizard
.ReadValueDW(kNwCategoryWizardRegValue
,
1177 if (error
== ERROR_SUCCESS
) {
1178 error
= nw_category_wizard
.WriteValue(kNwCategoryWizardSavedRegValue
,
1182 // Mark that temporary value has to be deleted.
1183 error
= nw_category_wizard
.WriteValue(kNwCategoryWizardDeleteRegValue
,
1187 // Disable network location wizard.
1188 error
= nw_category_wizard
.WriteValue(kNwCategoryWizardRegValue
,
1189 static_cast<DWORD
>(0));
1195 DWORD
WiFiServiceImpl::RestoreNwCategoryWizard() {
1196 base::win::RegKey nw_category_wizard
;
1197 DWORD error
= nw_category_wizard
.Open(HKEY_CURRENT_USER
,
1198 kNwCategoryWizardRegKey
,
1200 if (error
== ERROR_SUCCESS
) {
1201 // Restore saved value if present.
1202 if (nw_category_wizard
.HasValue(kNwCategoryWizardSavedRegValue
)) {
1204 error
= nw_category_wizard
.ReadValueDW(kNwCategoryWizardSavedRegValue
,
1206 if (error
== ERROR_SUCCESS
) {
1207 error
= nw_category_wizard
.WriteValue(kNwCategoryWizardRegValue
,
1209 error
= nw_category_wizard
.DeleteValue(kNwCategoryWizardSavedRegValue
);
1211 } else if (nw_category_wizard
.HasValue(kNwCategoryWizardDeleteRegValue
)) {
1212 error
= nw_category_wizard
.DeleteValue(kNwCategoryWizardRegValue
);
1213 error
= nw_category_wizard
.DeleteValue(kNwCategoryWizardDeleteRegValue
);
1220 DWORD
WiFiServiceImpl::EnsureInitialized() {
1221 if (client_
!= NULL
)
1222 return ERROR_SUCCESS
;
1223 return ERROR_NOINTERFACE
;
1226 DWORD
WiFiServiceImpl::CloseClientHandle() {
1227 DWORD error
= ERROR_SUCCESS
;
1228 if (client_
!= NULL
) {
1229 error
= WlanCloseHandle_function_(client_
, NULL
);
1232 if (wlan_api_library_
!= NULL
) {
1233 WlanConnect_function_
= NULL
;
1234 WlanCloseHandle_function_
= NULL
;
1235 WlanDeleteProfile_function_
= NULL
;
1236 WlanDisconnect_function_
= NULL
;
1237 WlanEnumInterfaces_function_
= NULL
;
1238 WlanFreeMemory_function_
= NULL
;
1239 WlanGetAvailableNetworkList_function_
= NULL
;
1240 WlanGetNetworkBssList_function_
= NULL
;
1241 WlanGetProfile_function_
= NULL
;
1242 WlanOpenHandle_function_
= NULL
;
1243 WlanRegisterNotification_function_
= NULL
;
1244 WlanSaveTemporaryProfile_function_
= NULL
;
1245 WlanScan_function_
= NULL
;
1246 WlanSetProfile_function_
= NULL
;
1247 ::FreeLibrary(wlan_api_library_
);
1248 wlan_api_library_
= NULL
;
1253 DOT11_SSID
WiFiServiceImpl::SSIDFromGUID(
1254 const std::string
& network_guid
) const {
1255 DOT11_SSID ssid
= {0};
1256 if (network_guid
.length() <= DOT11_SSID_MAX_LENGTH
) {
1257 ssid
.uSSIDLength
= static_cast<ULONG
>(network_guid
.length());
1258 strncpy(reinterpret_cast<char*>(ssid
.ucSSID
),
1259 network_guid
.c_str(),
1267 std::string
WiFiServiceImpl::SecurityFromDot11AuthAlg(
1268 DOT11_AUTH_ALGORITHM alg
) const {
1270 case DOT11_AUTH_ALGO_RSNA
:
1271 return onc::wifi::kWPA_EAP
;
1272 case DOT11_AUTH_ALGO_RSNA_PSK
:
1273 return onc::wifi::kWPA_PSK
;
1274 case DOT11_AUTH_ALGO_80211_SHARED_KEY
:
1275 return onc::wifi::kWEP_PSK
;
1276 case DOT11_AUTH_ALGO_80211_OPEN
:
1277 return onc::wifi::kSecurityNone
;
1279 return onc::wifi::kWPA_EAP
;
1283 std::string
WiFiServiceImpl::ConnectionStateFromInterfaceState(
1284 WLAN_INTERFACE_STATE wlan_state
) const {
1285 switch (wlan_state
) {
1286 case wlan_interface_state_connected
:
1287 // TODO(mef): Even if |wlan_state| is connected, the network may still
1288 // not be reachable, and should be resported as |kConnecting|.
1289 return onc::connection_state::kConnected
;
1290 case wlan_interface_state_associating
:
1291 case wlan_interface_state_discovering
:
1292 case wlan_interface_state_authenticating
:
1293 return onc::connection_state::kConnecting
;
1295 return onc::connection_state::kNotConnected
;
1299 void WiFiServiceImpl::NetworkPropertiesFromAvailableNetwork(
1300 const WLAN_AVAILABLE_NETWORK
& wlan
,
1301 NetworkProperties
* properties
) {
1302 // TODO(mef): It would be nice for the connection states in
1303 // getVisibleNetworks and getProperties results to be consistent.
1304 if (wlan
.dwFlags
& WLAN_AVAILABLE_NETWORK_CONNECTED
) {
1305 properties
->connection_state
= onc::connection_state::kConnected
;
1307 properties
->connection_state
= onc::connection_state::kNotConnected
;
1310 properties
->ssid
= SSIDFromWLAN(wlan
);
1311 properties
->name
= properties
->ssid
;
1312 properties
->guid
= GUIDFromWLAN(wlan
);
1313 properties
->type
= onc::network_type::kWiFi
;
1314 properties
->security
=
1315 SecurityFromDot11AuthAlg(wlan
.dot11DefaultAuthAlgorithm
);
1316 properties
->signal_strength
= wlan
.wlanSignalQuality
;
1319 void WiFiServiceImpl::UpdateNetworkPropertiesFromBssList(
1320 const std::string
& network_guid
,
1321 const WLAN_BSS_LIST
& wlan_bss_list
,
1322 NetworkProperties
* properties
) {
1323 if (network_guid
.empty())
1326 DOT11_SSID ssid
= SSIDFromGUID(network_guid
);
1327 for (size_t bss
= 0; bss
< wlan_bss_list
.dwNumberOfItems
; ++bss
) {
1328 const WLAN_BSS_ENTRY
& bss_entry(wlan_bss_list
.wlanBssEntries
[bss
]);
1329 if (bss_entry
.dot11Ssid
.uSSIDLength
== ssid
.uSSIDLength
&&
1330 0 == memcmp(bss_entry
.dot11Ssid
.ucSSID
,
1332 bss_entry
.dot11Ssid
.uSSIDLength
)) {
1333 std::string bssid
= NetworkProperties::MacAddressAsString(
1334 bss_entry
.dot11Bssid
);
1335 Frequency frequency
= GetNormalizedFrequency(
1336 bss_entry
.ulChCenterFrequency
/ 1000);
1337 properties
->frequency_set
.insert(frequency
);
1338 if (properties
->bssid
.empty() || properties
->bssid
== bssid
) {
1339 properties
->frequency
= frequency
;
1340 properties
->bssid
= bssid
;
1346 // Get the list of visible wireless networks
1347 DWORD
WiFiServiceImpl::GetVisibleNetworkList(NetworkList
* network_list
) {
1348 if (client_
== NULL
) {
1350 return ERROR_NOINTERFACE
;
1353 DWORD error
= ERROR_SUCCESS
;
1354 PWLAN_AVAILABLE_NETWORK_LIST available_network_list
= NULL
;
1355 PWLAN_BSS_LIST bss_list
= NULL
;
1357 error
= WlanGetAvailableNetworkList_function_(
1360 WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES
,
1362 &available_network_list
);
1364 std::set
<std::string
> network_guids
;
1366 if (error
== ERROR_SUCCESS
&&
1367 available_network_list
&&
1368 WlanGetNetworkBssList_function_
) {
1369 // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
1370 // needed, then different method of getting BSS (e.g. OID query) will have
1372 error
= WlanGetNetworkBssList_function_(client_
,
1379 if (error
== ERROR_SUCCESS
&& NULL
!= bss_list
) {
1380 for (DWORD i
= 0; i
< available_network_list
->dwNumberOfItems
; ++i
) {
1381 NetworkProperties network_properties
;
1382 NetworkPropertiesFromAvailableNetwork(
1383 available_network_list
->Network
[i
],
1384 &network_properties
);
1385 UpdateNetworkPropertiesFromBssList(network_properties
.guid
,
1387 &network_properties
);
1388 // Check for duplicate network guids.
1389 if (network_guids
.count(network_properties
.guid
)) {
1390 // There should be no difference between properties except for
1391 // |connection_state|, so mark it as |kConnected| if either one is.
1392 if (network_properties
.connection_state
==
1393 onc::connection_state::kConnected
) {
1394 NetworkList::iterator previous_network_properties
=
1395 FindNetwork(*network_list
, network_properties
.guid
);
1396 DCHECK(previous_network_properties
!= network_list
->end());
1397 previous_network_properties
->connection_state
=
1398 network_properties
.connection_state
;
1401 network_list
->push_back(network_properties
);
1403 network_guids
.insert(network_properties
.guid
);
1409 if (available_network_list
!= NULL
) {
1410 WlanFreeMemory_function_(available_network_list
);
1412 if (bss_list
!= NULL
) {
1413 WlanFreeMemory_function_(bss_list
);
1418 DWORD
WiFiServiceImpl::GetCurrentProperties(NetworkProperties
* properties
) {
1419 if (client_
== NULL
) {
1421 return ERROR_NOINTERFACE
;
1424 // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
1425 // needed, then different method of getting BSS (e.g. OID query) will have
1427 if (WlanGetNetworkBssList_function_
== NULL
)
1428 return ERROR_NOINTERFACE
;
1430 DWORD error
= ERROR_SUCCESS
;
1431 DWORD data_size
= 0;
1432 PWLAN_CONNECTION_ATTRIBUTES wlan_connection_attributes
= NULL
;
1433 PWLAN_BSS_LIST bss_list
= NULL
;
1434 error
= WlanQueryInterface_function_(
1437 wlan_intf_opcode_current_connection
,
1440 reinterpret_cast<PVOID
*>(&wlan_connection_attributes
),
1442 if (error
== ERROR_SUCCESS
&&
1443 wlan_connection_attributes
!= NULL
) {
1444 WLAN_ASSOCIATION_ATTRIBUTES
& connected_wlan
=
1445 wlan_connection_attributes
->wlanAssociationAttributes
;
1447 properties
->connection_state
= ConnectionStateFromInterfaceState(
1448 wlan_connection_attributes
->isState
);
1449 properties
->ssid
= GUIDFromSSID(connected_wlan
.dot11Ssid
);
1450 properties
->name
= properties
->ssid
;
1451 properties
->guid
= GUIDFromSSID(connected_wlan
.dot11Ssid
);
1452 properties
->type
= onc::network_type::kWiFi
;
1453 properties
->bssid
= NetworkProperties::MacAddressAsString(
1454 connected_wlan
.dot11Bssid
);
1455 properties
->security
= SecurityFromDot11AuthAlg(
1456 wlan_connection_attributes
->wlanSecurityAttributes
.dot11AuthAlgorithm
);
1457 properties
->signal_strength
= connected_wlan
.wlanSignalQuality
;
1459 error
= WlanGetNetworkBssList_function_(client_
,
1461 &connected_wlan
.dot11Ssid
,
1462 connected_wlan
.dot11BssType
,
1466 if (error
== ERROR_SUCCESS
&& NULL
!= bss_list
) {
1467 UpdateNetworkPropertiesFromBssList(properties
->guid
,
1474 if (wlan_connection_attributes
!= NULL
)
1475 WlanFreeMemory_function_(wlan_connection_attributes
);
1477 if (bss_list
!= NULL
)
1478 WlanFreeMemory_function_(bss_list
);
1484 DWORD
WiFiServiceImpl::GetCurrentSSID(std::string
* ssid
) {
1485 if (client_
== NULL
) {
1487 return ERROR_NOINTERFACE
;
1489 DWORD error
= ERROR_SUCCESS
;
1490 DWORD data_size
= 0;
1491 PWLAN_CONNECTION_ATTRIBUTES wlan_connection_attributes
= NULL
;
1492 error
= WlanQueryInterface_function_(
1495 wlan_intf_opcode_current_connection
,
1498 reinterpret_cast<PVOID
*>(&wlan_connection_attributes
),
1500 if (error
== ERROR_SUCCESS
&&
1501 wlan_connection_attributes
!= NULL
) {
1502 WLAN_ASSOCIATION_ATTRIBUTES
& connected_wlan
=
1503 wlan_connection_attributes
->wlanAssociationAttributes
;
1504 *ssid
= GUIDFromSSID(connected_wlan
.dot11Ssid
);
1508 if (wlan_connection_attributes
!= NULL
)
1509 WlanFreeMemory_function_(wlan_connection_attributes
);
1514 Frequency
WiFiServiceImpl::GetFrequencyToConnect(
1515 const std::string
& network_guid
) const {
1516 // Check whether desired frequency is set in |connect_properties_|.
1517 const base::DictionaryValue
* properties
;
1518 if (connect_properties_
.GetDictionaryWithoutPathExpansion(network_guid
,
1520 const base::DictionaryValue
* wifi
;
1521 if (properties
->GetDictionary(onc::network_type::kWiFi
, &wifi
)) {
1523 if (wifi
->GetInteger(onc::wifi::kFrequency
, &frequency
))
1524 return GetNormalizedFrequency(frequency
);
1527 return kFrequencyAny
;
1530 DWORD
WiFiServiceImpl::GetDesiredBssList(
1532 Frequency frequency
,
1533 scoped_ptr
<DOT11_BSSID_LIST
>* desired_list
) {
1534 if (client_
== NULL
) {
1536 return ERROR_NOINTERFACE
;
1539 desired_list
->reset();
1541 if (frequency
== kFrequencyAny
)
1542 return ERROR_SUCCESS
;
1544 // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
1545 // needed, then different method of getting BSS (e.g. OID query) will have
1547 if (!WlanGetNetworkBssList_function_
)
1548 return ERROR_NOT_SUPPORTED
;
1550 DWORD error
= ERROR_SUCCESS
;
1551 PWLAN_BSS_LIST bss_list
= NULL
;
1553 error
= WlanGetNetworkBssList_function_(client_
,
1556 dot11_BSS_type_infrastructure
,
1560 if (error
== ERROR_SUCCESS
&& NULL
!= bss_list
) {
1561 unsigned int best_quality
= 0u;
1562 size_t best_index
= 0;
1563 Frequency bss_frequency
;
1565 // Go through bss_list and find best quality BSSID with matching frequency.
1566 for (size_t bss
= 0; bss
< bss_list
->dwNumberOfItems
; ++bss
) {
1567 const WLAN_BSS_ENTRY
& bss_entry(bss_list
->wlanBssEntries
[bss
]);
1568 if (bss_entry
.dot11Ssid
.uSSIDLength
!= ssid
.uSSIDLength
||
1569 0 != memcmp(bss_entry
.dot11Ssid
.ucSSID
,
1571 bss_entry
.dot11Ssid
.uSSIDLength
))
1574 bss_frequency
= GetNormalizedFrequency(
1575 bss_entry
.ulChCenterFrequency
/ 1000);
1576 if (bss_frequency
== frequency
&&
1577 bss_entry
.uLinkQuality
> best_quality
) {
1578 best_quality
= bss_entry
.uLinkQuality
;
1583 // If any matching BSS were found, prepare the header.
1584 if (best_quality
> 0) {
1585 const WLAN_BSS_ENTRY
& bss_entry(bss_list
->wlanBssEntries
[best_index
]);
1586 scoped_ptr
<DOT11_BSSID_LIST
> selected_list(new DOT11_BSSID_LIST
);
1588 selected_list
->Header
.Revision
= DOT11_BSSID_LIST_REVISION_1
;
1589 selected_list
->Header
.Size
= sizeof(DOT11_BSSID_LIST
);
1590 selected_list
->Header
.Type
= NDIS_OBJECT_TYPE_DEFAULT
;
1591 selected_list
->uNumOfEntries
= 1;
1592 selected_list
->uTotalNumOfEntries
= 1;
1593 std::copy(bss_entry
.dot11Bssid
,
1594 bss_entry
.dot11Bssid
+sizeof(bss_entry
.dot11Bssid
),
1595 selected_list
->BSSIDs
[0]);
1596 desired_list
->swap(selected_list
);
1597 DVLOG(1) << "Quality: " << best_quality
<< " BSS: "
1598 << NetworkProperties::MacAddressAsString(bss_entry
.dot11Bssid
);
1600 error
= ERROR_NOT_FOUND
;
1605 if (bss_list
!= NULL
) {
1606 WlanFreeMemory_function_(bss_list
);
1611 Frequency
WiFiServiceImpl::GetNormalizedFrequency(int frequency_in_mhz
) const {
1612 if (frequency_in_mhz
== 0)
1613 return kFrequencyAny
;
1614 if (frequency_in_mhz
< 3000)
1615 return kFrequency2400
;
1616 return kFrequency5000
;
1619 DWORD
WiFiServiceImpl::Connect(const std::string
& network_guid
,
1620 Frequency frequency
) {
1621 if (client_
== NULL
) {
1623 return ERROR_NOINTERFACE
;
1626 DWORD error
= ERROR_SUCCESS
;
1627 DOT11_SSID ssid
= SSIDFromGUID(network_guid
);
1628 scoped_ptr
<DOT11_BSSID_LIST
> desired_bss_list
;
1629 error
= GetDesiredBssList(ssid
, frequency
, &desired_bss_list
);
1630 if (error
== ERROR_SUCCESS
) {
1631 if (HaveProfile(network_guid
)) {
1632 base::string16 profile_name
= ProfileNameFromGUID(network_guid
);
1633 WLAN_CONNECTION_PARAMETERS wlan_params
= {
1634 wlan_connection_mode_profile
,
1635 profile_name
.c_str(),
1637 desired_bss_list
.get(),
1640 error
= WlanConnect_function_(
1641 client_
, &interface_guid_
, &wlan_params
, NULL
);
1643 // If network is available, but is not open security, then it cannot be
1644 // connected without profile, so return 'access denied' error.
1645 scoped_ptr
<base::DictionaryValue
> properties (new base::DictionaryValue
);
1646 const base::DictionaryValue
* wifi
;
1647 std::string wifi_security
;
1648 std::string error_string
;
1649 GetProperties(network_guid
, properties
.get(), &error_string
);
1650 if (error_string
.empty() &&
1651 properties
->GetDictionary(onc::network_type::kWiFi
, &wifi
) &&
1652 wifi
->GetString(onc::wifi::kSecurity
, &wifi_security
) &&
1653 wifi_security
!= onc::wifi::kSecurityNone
) {
1654 error
= ERROR_ACCESS_DENIED
;
1655 LOG(ERROR
) << error
;
1658 WLAN_CONNECTION_PARAMETERS wlan_params
= {
1659 wlan_connection_mode_discovery_unsecure
,
1662 desired_bss_list
.get(),
1663 dot11_BSS_type_infrastructure
,
1665 error
= WlanConnect_function_(
1666 client_
, &interface_guid_
, &wlan_params
, NULL
);
1673 DWORD
WiFiServiceImpl::Disconnect() {
1674 if (client_
== NULL
) {
1676 return ERROR_NOINTERFACE
;
1679 DWORD error
= ERROR_SUCCESS
;
1680 error
= WlanDisconnect_function_(client_
, &interface_guid_
, NULL
);
1684 DWORD
WiFiServiceImpl::SaveTempProfile(const std::string
& network_guid
) {
1685 if (client_
== NULL
) {
1687 return ERROR_NOINTERFACE
;
1690 DWORD error
= ERROR_SUCCESS
;
1691 base::string16 profile_name
= ProfileNameFromGUID(network_guid
);
1692 // TODO(mef): WlanSaveTemporaryProfile is not available on XP. If XP support
1693 // is needed, then different method of saving network profile will have to be
1695 if (WlanSaveTemporaryProfile_function_
) {
1696 error
= WlanSaveTemporaryProfile_function_(client_
,
1698 profile_name
.c_str(),
1704 error
= ERROR_NOT_SUPPORTED
;
1709 DWORD
WiFiServiceImpl::GetProfile(const std::string
& network_guid
,
1710 bool get_plaintext_key
,
1711 std::string
* profile_xml
) {
1712 if (client_
== NULL
) {
1714 return ERROR_NOINTERFACE
;
1717 DWORD error
= ERROR_SUCCESS
;
1718 base::string16 profile_name
= ProfileNameFromGUID(network_guid
);
1719 DWORD flags
= get_plaintext_key
? WLAN_PROFILE_GET_PLAINTEXT_KEY
: 0;
1720 LPWSTR str_profile_xml
= NULL
;
1721 error
= WlanGetProfile_function_(client_
,
1723 profile_name
.c_str(),
1729 if (error
== ERROR_SUCCESS
&& str_profile_xml
!= NULL
) {
1730 *profile_xml
= base::UTF16ToUTF8(str_profile_xml
);
1733 if (str_profile_xml
!= NULL
) {
1734 WlanFreeMemory_function_(str_profile_xml
);
1740 DWORD
WiFiServiceImpl::SetProfile(bool shared
,
1741 const std::string
& profile_xml
,
1743 DWORD error_code
= ERROR_SUCCESS
;
1745 base::string16
profile_xml16(base::UTF8ToUTF16(profile_xml
));
1746 DWORD reason_code
= 0u;
1748 error_code
= WlanSetProfile_function_(client_
,
1750 shared
? 0 : WLAN_PROFILE_USER
,
1751 profile_xml16
.c_str(),
1759 bool WiFiServiceImpl::HaveProfile(const std::string
& network_guid
) {
1760 std::string profile_xml
;
1761 return GetProfile(network_guid
, false, &profile_xml
) == ERROR_SUCCESS
;
1765 DWORD
WiFiServiceImpl::DeleteCreatedProfile(const std::string
& network_guid
) {
1766 base::DictionaryValue
* created_profile
= NULL
;
1767 DWORD error_code
= ERROR_SUCCESS
;
1768 // Check, whether this connection is using new created profile, and remove it.
1769 if (created_profiles_
.GetDictionaryWithoutPathExpansion(
1770 network_guid
, &created_profile
)) {
1771 // Connection has failed, so delete it.
1772 base::string16 profile_name
= ProfileNameFromGUID(network_guid
);
1773 error_code
= WlanDeleteProfile_function_(client_
,
1775 profile_name
.c_str(),
1777 created_profiles_
.RemoveWithoutPathExpansion(network_guid
, NULL
);
1782 std::string
WiFiServiceImpl::WpaEncryptionFromEncryptionType(
1783 EncryptionType encryption_type
) const {
1784 if (encryption_type
== kEncryptionTypeTKIP
)
1785 return kEncryptionTKIP
;
1786 return kEncryptionAES
;
1789 bool WiFiServiceImpl::AuthEncryptionFromSecurity(
1790 const std::string
& security
,
1791 EncryptionType encryption_type
,
1792 std::string
* authentication
,
1793 std::string
* encryption
,
1794 std::string
* key_type
) const {
1795 if (security
== onc::wifi::kSecurityNone
) {
1796 *authentication
= kAuthenticationOpen
;
1797 *encryption
= kEncryptionNone
;
1798 } else if (security
== onc::wifi::kWEP_PSK
) {
1799 *authentication
= kAuthenticationOpen
;
1800 *encryption
= kEncryptionWEP
;
1801 *key_type
= kKeyTypeNetwork
;
1802 } else if (security
== onc::wifi::kWPA_PSK
) {
1803 *authentication
= kAuthenticationWpaPsk
;
1804 *encryption
= WpaEncryptionFromEncryptionType(encryption_type
);
1805 *key_type
= kKeyTypePassphrase
;
1806 } else if (security
== onc::wifi::kWPA2_PSK
) {
1807 *authentication
= kAuthenticationWpa2Psk
;
1808 *encryption
= WpaEncryptionFromEncryptionType(encryption_type
);
1809 *key_type
= kKeyTypePassphrase
;
1816 bool WiFiServiceImpl::CreateProfile(
1817 const NetworkProperties
& network_properties
,
1818 EncryptionType encryption_type
,
1819 std::string
* profile_xml
) {
1820 // Get authentication and encryption values from security.
1821 std::string authentication
;
1822 std::string encryption
;
1823 std::string key_type
;
1824 bool valid
= AuthEncryptionFromSecurity(network_properties
.security
,
1832 // Generate profile XML.
1833 XmlWriter xml_writer
;
1834 xml_writer
.StartWriting();
1835 xml_writer
.StartElement("WLANProfile");
1836 xml_writer
.AddAttribute(
1838 "http://www.microsoft.com/networking/WLAN/profile/v1");
1839 xml_writer
.WriteElement("name", network_properties
.guid
);
1840 xml_writer
.StartElement("SSIDConfig");
1841 xml_writer
.StartElement("SSID");
1842 xml_writer
.WriteElement("name", network_properties
.ssid
);
1843 xml_writer
.EndElement(); // Ends "SSID" element.
1844 xml_writer
.EndElement(); // Ends "SSIDConfig" element.
1845 xml_writer
.WriteElement("connectionType", "ESS");
1846 xml_writer
.WriteElement("connectionMode", "manual");
1847 xml_writer
.StartElement("MSM");
1848 xml_writer
.StartElement("security");
1849 xml_writer
.StartElement("authEncryption");
1850 xml_writer
.WriteElement("authentication", authentication
);
1851 xml_writer
.WriteElement("encryption", encryption
);
1852 xml_writer
.WriteElement("useOneX", "false");
1853 xml_writer
.EndElement(); // Ends "authEncryption" element.
1854 if (!key_type
.empty()) {
1855 xml_writer
.StartElement("sharedKey");
1856 xml_writer
.WriteElement("keyType", key_type
);
1857 xml_writer
.WriteElement("protected", "false");
1858 xml_writer
.WriteElement("keyMaterial", network_properties
.password
);
1859 xml_writer
.EndElement(); // Ends "sharedKey" element.
1861 xml_writer
.EndElement(); // Ends "security" element.
1862 xml_writer
.EndElement(); // Ends "MSM" element.
1863 xml_writer
.EndElement(); // Ends "WLANProfile" element.
1864 xml_writer
.StopWriting();
1865 *profile_xml
= xml_writer
.GetWrittenString();
1870 void WiFiServiceImpl::NotifyNetworkListChanged(const NetworkList
& networks
) {
1871 if (network_list_changed_observer_
.is_null())
1874 NetworkGuidList current_networks
;
1875 for (NetworkList::const_iterator it
= networks
.begin();
1876 it
!= networks
.end();
1878 current_networks
.push_back(it
->guid
);
1881 event_task_runner_
->PostTask(
1882 FROM_HERE
, base::Bind(network_list_changed_observer_
, current_networks
));
1885 void WiFiServiceImpl::NotifyNetworkChanged(const std::string
& network_guid
) {
1886 if (enable_notify_network_changed_
&& !networks_changed_observer_
.is_null()) {
1887 DVLOG(1) << "NotifyNetworkChanged: " << network_guid
;
1888 NetworkGuidList
changed_networks(1, network_guid
);
1889 event_task_runner_
->PostTask(
1890 FROM_HERE
, base::Bind(networks_changed_observer_
, changed_networks
));
1894 WiFiService
* WiFiService::Create() { return new WiFiServiceImpl(); }