Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: components/wifi/wifi_service_win.cc

Issue 68503019: Windows-specific implementation of Networking Private API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Make ChromeCast setup work on Windows again. Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « components/wifi/wifi_service_test.cc ('k') | components/wifi/wifi_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "components/wifi/wifi_service.h"
6
7 #include <iphlpapi.h>
8 #include <objbase.h>
9 #include <wlanapi.h>
10
11 #include <set>
12
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
25 namespace {
26 const char kWiFiServiceError[] = "Error.WiFiService";
27 const wchar_t kNwCategoryWizardRegKey[] =
28 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Network\\"
29 L"NwCategoryWizard";
30 const wchar_t kNwCategoryWizardRegValue[] = L"Show";
31 const wchar_t kNwCategoryWizardSavedRegValue[] = L"ShowSaved";
32 const wchar_t kNwCategoryWizardDeleteRegValue[] = L"ShowDelete";
33 const wchar_t kWlanApiDll[] = L"wlanapi.dll";
34
35 // WlanApi function names
36 const char kWlanConnect[] = "WlanConnect";
37 const char kWlanCloseHandle[] = "WlanCloseHandle";
38 const char kWlanDisconnect[] = "WlanDisconnect";
39 const char kWlanEnumInterfaces[] = "WlanEnumInterfaces";
40 const char kWlanFreeMemory[] = "WlanFreeMemory";
41 const char kWlanGetAvailableNetworkList[] = "WlanGetAvailableNetworkList";
42 const char kWlanGetNetworkBssList[] = "WlanGetNetworkBssList";
43 const char kWlanGetProfile[] = "WlanGetProfile";
44 const char kWlanOpenHandle[] = "WlanOpenHandle";
45 const char kWlanRegisterNotification[] = "WlanRegisterNotification";
46 const char kWlanSaveTemporaryProfile[] = "WlanSaveTemporaryProfile";
47 const char kWlanScan[] = "WlanScan";
48
49 // WlanApi function definitions
50 typedef DWORD (WINAPI* WlanConnectFunction)(
51 HANDLE hClientHandle,
52 CONST GUID *pInterfaceGuid,
53 CONST PWLAN_CONNECTION_PARAMETERS pConnectionParameters,
54 PVOID pReserved);
55
56 typedef DWORD (WINAPI* WlanCloseHandleFunction)(
57 HANDLE hClientHandle,
58 PVOID pReserved);
59
60 typedef DWORD (WINAPI* WlanDisconnectFunction)(
61 HANDLE hClientHandle,
62 CONST GUID *pInterfaceGuid,
63 PVOID pReserved);
64
65 typedef DWORD (WINAPI* WlanEnumInterfacesFunction)(
66 HANDLE hClientHandle,
67 PVOID pReserved,
68 PWLAN_INTERFACE_INFO_LIST *ppInterfaceList);
69
70 typedef VOID (WINAPI* WlanFreeMemoryFunction)(
71 _In_ PVOID pMemory);
72
73 typedef DWORD (WINAPI* WlanGetAvailableNetworkListFunction)(
74 HANDLE hClientHandle,
75 CONST GUID *pInterfaceGuid,
76 DWORD dwFlags,
77 PVOID pReserved,
78 PWLAN_AVAILABLE_NETWORK_LIST *ppAvailableNetworkList);
79
80 typedef DWORD (WINAPI* WlanGetNetworkBssListFunction)(
81 HANDLE hClientHandle,
82 const GUID* pInterfaceGuid,
83 const PDOT11_SSID pDot11Ssid,
84 DOT11_BSS_TYPE dot11BssType,
85 BOOL bSecurityEnabled,
86 PVOID pReserved,
87 PWLAN_BSS_LIST* ppWlanBssList);
88
89 typedef DWORD (WINAPI* WlanGetProfileFunction)(
90 HANDLE hClientHandle,
91 CONST GUID *pInterfaceGuid,
92 LPCWSTR strProfileName,
93 PVOID pReserved,
94 LPWSTR *pstrProfileXml,
95 DWORD *pdwFlags,
96 DWORD *pdwGrantedAccess);
97
98 typedef DWORD (WINAPI* WlanOpenHandleFunction)(
99 DWORD dwClientVersion,
100 PVOID pReserved,
101 PDWORD pdwNegotiatedVersion,
102 PHANDLE phClientHandle);
103
104 typedef DWORD (WINAPI* WlanRegisterNotificationFunction)(
105 HANDLE hClientHandle,
106 DWORD dwNotifSource,
107 BOOL bIgnoreDuplicate,
108 WLAN_NOTIFICATION_CALLBACK funcCallback,
109 PVOID pCallbackContext,
110 PVOID pReserved,
111 PDWORD pdwPrevNotifSource);
112
113 typedef DWORD (WINAPI* WlanSaveTemporaryProfileFunction)(
114 HANDLE hClientHandle,
115 CONST GUID* pInterfaceGuid,
116 LPCWSTR strProfileName,
117 LPCWSTR strAllUserProfileSecurity,
118 DWORD dwFlags,
119 BOOL bOverWrite,
120 PVOID pReserved);
121
122 typedef DWORD (WINAPI* WlanScanFunction)(
123 HANDLE hClientHandle,
124 CONST GUID *pInterfaceGuid,
125 CONST PDOT11_SSID pDot11Ssid,
126 CONST PWLAN_RAW_DATA pIeData,
127 PVOID pReserved);
128
129 } // namespace
130
131 namespace wifi {
132
133 // Implementation of WiFiService for Windows.
134 class WiFiServiceImpl : public WiFiService, base::NonThreadSafe {
Jói 2013/11/20 11:08:40 A minor nit on naming; it's inconsistent to use Wi
135 public:
136 WiFiServiceImpl();
137 virtual ~WiFiServiceImpl();
138
139 // WiFiService interface implementation.
140 virtual void Initialize(
141 scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE;
142
143 virtual void UnInitialize() OVERRIDE;
144
145 // Get Properties of network identified by |network_guid|. Populates
146 // |properties| on success, |error| on failure.
147 virtual void GetProperties(const std::string& network_guid,
148 DictionaryValue* properties,
149 std::string* error) OVERRIDE;
150
151 // Set Properties of network identified by |network_guid|. Populates |error|
152 // on failure.
153 virtual void SetProperties(const std::string& network_guid,
154 scoped_ptr<base::DictionaryValue> properties,
155 std::string* error) OVERRIDE;
156
157 // Get list of visible networks. Populates |network_list| on success.
158 virtual void GetVisibleNetworks(ListValue* network_list) OVERRIDE;
159
160 // Request network scan. Send |NetworkListChanged| event on completion.
161 virtual void RequestNetworkScan() OVERRIDE;
162
163 // Start connect to network identified by |network_guid|. Populates |error|
164 // on failure.
165 virtual void StartConnect(const std::string& network_guid,
166 std::string* error) OVERRIDE;
167
168 // Start disconnect from network identified by |network_guid|. Populates
169 // |error| on failure.
170 virtual void StartDisconnect(const std::string& network_guid,
171 std::string* error) OVERRIDE;
172
173 // Set observers to run when |NetworksChanged| and |NetworksListChanged|
174 // events needs to be sent. Notifications are posted on |message_loop_proxy|.
175 virtual void SetEventObservers(
176 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
177 const NetworkGuidListCallback& networks_changed_observer,
178 const NetworkGuidListCallback& network_list_changed_observer) OVERRIDE;
179
180 private:
181 // Static callback for Windows WLAN_NOTIFICATION. Calls OnWlanNotification
182 // on WiFiServiceImpl passed back as |context|.
183 static void __stdcall OnWlanNotificationCallback(
184 PWLAN_NOTIFICATION_DATA wlan_notification_data,
185 PVOID context);
186
187 // Callback for Windows WLAN_NOTIFICATION. Called on random thread from
188 // OnWlanNotificationCallback. Handles network connectivity and scan complete
189 // notification and posts tasks to main thread.
190 void OnWlanNotification(PWLAN_NOTIFICATION_DATA wlan_notification_data);
191
192 // Handles NetworkScanComplete notification on main thread. Sends
193 // |NetworkListChanged| event with new list of visible networks.
194 void OnNetworkScanCompleteOnMainThread();
195
196 // Wait up to |kMaxAttempts| with |kAttemptDelayMs| delay for connection
197 // to network with |network_guid|. Reset DHCP and Notify that |NetworkChanged|
198 // upon success.
199 void WaitForNetworkConnect(const std::string& network_guid, int attempt);
200
201 // Check |error_code| and if is not |ERROR_SUCCESS|, then store |error_name|
202 // into |error|.
203 bool CheckError(DWORD error_code,
204 const std::string& error_name,
205 std::string* error) const;
206
207 // Return |iterator| to network identified by |network_guid| in |networks|
208 // list.
209 NetworkList::iterator FindNetwork(NetworkList& networks,
210 const std::string& network_guid);
211
212 // Save currently connected network profile and return its
213 // |connected_network_guid|, so it can be re-connected later.
214 DWORD SaveCurrentConnectedNetwork(std::string* connected_network_guid);
215
216 // Sort networks, so connected/connecting is up front, then by type:
217 // Ethernet, WiFi, Cellular, VPN
218 static void SortNetworks(NetworkList* networks);
219
220 // Open a WLAN client handle, register for WLAN notifications.
221 DWORD OpenClientHandle();
222
223 // Reset DHCP on wireless network to work around an issue when Windows
224 // takes forever to connect to the network, e.g. after Chromecast
225 // device reset.
226 DWORD ResetDHCP();
227
228 // Find |adapter_index_map| by |interface_guid| for DHCP reset.
229 DWORD FindAdapterIndexMapByGUID(const GUID& interface_guid,
230 IP_ADAPTER_INDEX_MAP* adapter_index_map);
231
232 // Avoid the network location wizard to pop up when network is connected.
233 // Preserve current value in |saved_nw_category_wizard_|.
234 DWORD DisableNwCategoryWizard();
235
236 // Restore network location wizard to value saved by DisableNwCategoryWizard.
237 DWORD RestoreNwCategoryWizard();
238
239 // Ensure that |client_| handle is initialized.
240 DWORD EnsureInitialized();
241
242 // Close |client_| handle if it is open.
243 DWORD CloseClientHandle();
244
245 // Get |profile_name| from unique |network_guid|.
246 base::string16 ProfileNameFromGUID(const std::string& network_guid) const {
247 return base::UTF8ToUTF16(network_guid);
248 }
249
250 // Get |dot11_ssid| from unique |network_guid|.
251 DOT11_SSID SSIDFromGUID(const std::string& network_guid) const;
252
253 // Get unique |network_guid| string based on |dot11_ssid|.
254 std::string GUIDFromSSID(const DOT11_SSID& dot11_ssid) const {
255 return std::string(reinterpret_cast<const char*>(dot11_ssid.ucSSID),
256 dot11_ssid.uSSIDLength);
257 }
258
259 // Get network |ssid| string based on |wlan|.
260 std::string SSIDFromWLAN(const WLAN_AVAILABLE_NETWORK& wlan) const {
261 return GUIDFromSSID(wlan.dot11Ssid);
262 }
263
264 // Get unique |network_guid| string based on |wlan|.
265 std::string GUIDFromWLAN(const WLAN_AVAILABLE_NETWORK& wlan) const {
266 return SSIDFromWLAN(wlan);
267 }
268
269 // Deduce |onc::wifi| security from |alg|.
270 std::string SecurityFromDot11AuthAlg(DOT11_AUTH_ALGORITHM alg) const;
271
272 // Populate |properties| based on |wlan| and its corresponding bss info from
273 // |wlan_bss_list|.
274 void NetworkPropertiesFromAvailableNetwork(const WLAN_AVAILABLE_NETWORK& wlan,
275 const WLAN_BSS_LIST& wlan_bss_list,
276 NetworkProperties* properties);
277
278 // Get the list of visible wireless networks.
279 DWORD GetVisibleNetworkList(NetworkList* network_list);
280
281 // Find currently connected network if any. Populate |connected_network_guid|
282 // on success.
283 DWORD FindConnectedNetwork(std::string* connected_network_guid);
284
285 // Connect to network |network_guid| using previosly stored profile if exists,
286 // or just network sid. If |frequency| is not |kFrequencyUnknown| then
287 // connects only to BSS which uses that frequency and returns
288 // |ERROR_NOT_FOUND| if such BSS cannot be found.
289 DWORD Connect(const std::string& network_guid, Frequency frequency);
290
291 // Disconnect from currently connected network if any.
292 DWORD Disconnect();
293
294 // Get DOT11_BSSID_LIST of desired BSSIDs to connect to |ssid| network on
295 // given |frequency|.
296 DWORD GetDesiredBssList(DOT11_SSID& ssid,
297 Frequency frequency,
298 scoped_ptr<DOT11_BSSID_LIST>* desired_list);
299
300 // Save temporary wireless profile for |network_guid|.
301 DWORD SaveTempProfile(const std::string& network_guid);
302
303 // Get previously stored |profile_xml| for |network_guid|.
304 DWORD GetProfile(const std::string& network_guid, std::string* profile_xml);
305
306 // Return true if there is previously stored profile xml for |network_guid|.
307 bool HaveProfile(const std::string& network_guid);
308
309 // Notify |network_list_changed_observer_| that list of visible networks has
310 // changed to |networks|.
311 void NotifyNetworkListChanged(const NetworkList& networks);
312
313 // Notify |networks_changed_observer_| that network |network_guid| status has
314 // changed.
315 void NotifyNetworkChanged(const std::string& network_guid);
316
317 // Load WlanApi.dll from SystemDirectory and get Api function pointers.
318 DWORD LoadWlanLibrary();
319 // Instance of WlanApi.dll.
320 HINSTANCE wlan_api_library_;
321 // WlanApi function pointers
322 WlanConnectFunction WlanConnect_function_;
323 WlanCloseHandleFunction WlanCloseHandle_function_;
324 WlanDisconnectFunction WlanDisconnect_function_;
325 WlanEnumInterfacesFunction WlanEnumInterfaces_function_;
326 WlanFreeMemoryFunction WlanFreeMemory_function_;
327 WlanGetAvailableNetworkListFunction WlanGetAvailableNetworkList_function_;
328 // WlanGetNetworkBssList function may not be avaiable on Windows XP.
329 WlanGetNetworkBssListFunction WlanGetNetworkBssList_function_;
330 WlanGetProfileFunction WlanGetProfile_function_;
331 WlanOpenHandleFunction WlanOpenHandle_function_;
332 WlanRegisterNotificationFunction WlanRegisterNotification_function_;
333 WlanScanFunction WlanScan_function_;
334 // WlanSaveTemporaryProfile function may not be avaiable on Windows XP.
335 WlanSaveTemporaryProfileFunction WlanSaveTemporaryProfile_function_;
336
337 // WLAN service handle.
338 HANDLE client_;
339 // GUID of the currently connected interface, if any, otherwise the GUID of
340 // one of the WLAN interfaces.
341 GUID interface_guid_;
342 // Preserved WLAN profile xml.
343 std::map<std::string, std::string> saved_profiles_xml_;
344 // Observer to get notified when network(s) have changed (e.g. connect).
345 NetworkGuidListCallback networks_changed_observer_;
346 // Observer to get notified when network list has changed (scan complete).
347 NetworkGuidListCallback network_list_changed_observer_;
348 // Saved value of network location wizard show value.
349 scoped_ptr<DWORD> saved_nw_category_wizard_;
350 // MessageLoopProxy to post events on UI thread.
351 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
352 // Task runner for worker tasks.
353 scoped_refptr<base::SequencedTaskRunner> task_runner_;
354 // If |false|, then |networks_changed_observer_| is not notified.
355 bool enable_notify_network_changed_;
356 // Number of attempts to check that network has connected successfully.
357 static const int kMaxAttempts = 100;
358 // Delay between attempts to check that network has connected successfully.
359 static const int kAttemptDelayMs = 100;
360 DISALLOW_COPY_AND_ASSIGN(WiFiServiceImpl);
361 };
362
363 WiFiServiceImpl::WiFiServiceImpl()
364 : wlan_api_library_(NULL),
365 WlanConnect_function_(NULL),
366 WlanCloseHandle_function_(NULL),
367 WlanDisconnect_function_(NULL),
368 WlanEnumInterfaces_function_(NULL),
369 WlanFreeMemory_function_(NULL),
370 WlanGetAvailableNetworkList_function_(NULL),
371 WlanGetNetworkBssList_function_(NULL),
372 WlanGetProfile_function_(NULL),
373 WlanOpenHandle_function_(NULL),
374 WlanRegisterNotification_function_(NULL),
375 WlanSaveTemporaryProfile_function_(NULL),
376 WlanScan_function_(NULL),
377 client_(NULL),
378 enable_notify_network_changed_(true) {}
379
380 WiFiServiceImpl::~WiFiServiceImpl() { UnInitialize(); }
381
382 void WiFiServiceImpl::Initialize(
383 scoped_refptr<base::SequencedTaskRunner> task_runner) {
384 DCHECK(!client_);
385 task_runner_.swap(task_runner);
386 // Restore NwCategoryWizard in case if we crashed during connect.
387 RestoreNwCategoryWizard();
388 OpenClientHandle();
389 }
390
391 void WiFiServiceImpl::UnInitialize() {
392 CloseClientHandle();
393 }
394
395 void WiFiServiceImpl::GetProperties(const std::string& network_guid,
396 DictionaryValue* properties,
397 std::string* error) {
398 DWORD error_code = EnsureInitialized();
399 if (error_code == ERROR_SUCCESS) {
400 NetworkList network_list;
401 error_code = GetVisibleNetworkList(&network_list);
402 if (error_code == ERROR_SUCCESS && !network_list.empty()) {
403 NetworkList::const_iterator it = FindNetwork(network_list, network_guid);
404 if (it != network_list.end()) {
405 DLOG(INFO) << "Get Properties: " << network_guid << ":"
406 << it->connection_state;
407 properties->Swap(it->ToValue(false).get());
408 return;
409 } else {
410 error_code = ERROR_NOT_FOUND;
411 }
412 }
413 }
414
415 CheckError(error_code, kWiFiServiceError, error);
416 }
417
418 void WiFiServiceImpl::SetProperties(
419 const std::string& network_guid,
420 scoped_ptr<base::DictionaryValue> properties,
421 std::string* error) {
422 // This method is not implemented in first version as it is not used by
423 // Google Cast extension.
424 CheckError(ERROR_CALL_NOT_IMPLEMENTED, kWiFiServiceError, error);
425 }
426
427 void WiFiServiceImpl::GetVisibleNetworks(ListValue* network_list) {
428 DWORD error = EnsureInitialized();
429
430 if (error == ERROR_SUCCESS) {
431 NetworkList networks;
432 error = GetVisibleNetworkList(&networks);
433 if (error == ERROR_SUCCESS && !networks.empty()) {
434 SortNetworks(&networks);
435 for (WiFiService::NetworkList::const_iterator it = networks.begin();
436 it != networks.end();
437 ++it) {
438 scoped_ptr<DictionaryValue> network(it->ToValue(true));
439 network_list->Append(network.release());
440 }
441 }
442 }
443 }
444
445 void WiFiServiceImpl::RequestNetworkScan() {
446 DWORD error = EnsureInitialized();
447 if (error == ERROR_SUCCESS) {
448 WlanScan_function_(client_, &interface_guid_, NULL, NULL, NULL);
449 }
450 }
451
452 void WiFiServiceImpl::StartConnect(const std::string& network_guid,
453 std::string* error) {
454 DLOG(INFO) << "Start Connect: " << network_guid;
455 DWORD error_code = EnsureInitialized();
456 if (error_code == ERROR_SUCCESS) {
457 std::string connected_network_guid;
458 error_code = SaveCurrentConnectedNetwork(&connected_network_guid);
459 if (error_code == ERROR_SUCCESS) {
460 Frequency frequency = kFrequencyAny;
461 // Connect only if network |network_guid| is not connected already.
462 if (network_guid != connected_network_guid)
463 error_code = Connect(network_guid, frequency);
464 if (error_code == ERROR_SUCCESS) {
465 // Notify that previously connected network has changed.
466 NotifyNetworkChanged(connected_network_guid);
467 // Start waiting for network connection state change.
468 if (!networks_changed_observer_.is_null()) {
469 DisableNwCategoryWizard();
470 // Disable automatic network change notifications as they get fired
471 // when network is just connected, but not yet accessible (doesn't
472 // have valid IP address).
473 enable_notify_network_changed_ = false;
474 WaitForNetworkConnect(network_guid, 0);
475 return;
476 }
477 }
478 }
479 }
480 CheckError(error_code, kWiFiServiceError, error);
481 }
482
483 void WiFiServiceImpl::StartDisconnect(const std::string& network_guid,
484 std::string* error) {
485 DLOG(INFO) << "Start Disconnect: " << network_guid;
486 DWORD error_code = EnsureInitialized();
487 if (error_code == ERROR_SUCCESS) {
488 std::string connected_network_guid;
489 error_code = SaveCurrentConnectedNetwork(&connected_network_guid);
490 if (error_code == ERROR_SUCCESS && network_guid == connected_network_guid) {
491 error_code = Disconnect();
492 if (error_code == ERROR_SUCCESS) {
493 NotifyNetworkChanged(network_guid);
494 return;
495 }
496 }
497 }
498 CheckError(error_code, kWiFiServiceError, error);
499 }
500
501 void WiFiServiceImpl::SetEventObservers(
502 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
503 const NetworkGuidListCallback& networks_changed_observer,
504 const NetworkGuidListCallback& network_list_changed_observer) {
505 message_loop_proxy_.swap(message_loop_proxy);
506 networks_changed_observer_ = networks_changed_observer;
507 network_list_changed_observer_ = network_list_changed_observer;
508 }
509
510 void WiFiServiceImpl::OnWlanNotificationCallback(
511 PWLAN_NOTIFICATION_DATA wlan_notification_data,
512 PVOID context) {
513 WiFiServiceImpl* service = reinterpret_cast<WiFiServiceImpl*>(context);
514 service->OnWlanNotification(wlan_notification_data);
515 }
516
517 void WiFiServiceImpl::OnWlanNotification(
518 PWLAN_NOTIFICATION_DATA wlan_notification_data) {
519 if (message_loop_proxy_ == NULL)
520 return;
521 switch (wlan_notification_data->NotificationCode) {
522 case wlan_notification_acm_disconnected:
523 case wlan_notification_acm_connection_complete:
524 case wlan_notification_acm_connection_attempt_fail: {
525 PWLAN_CONNECTION_NOTIFICATION_DATA wlan_connection_data =
526 reinterpret_cast<PWLAN_CONNECTION_NOTIFICATION_DATA>(
527 wlan_notification_data->pData);
528 message_loop_proxy_->PostTask(
529 FROM_HERE,
530 base::Bind(&WiFiServiceImpl::NotifyNetworkChanged,
531 base::Unretained(this),
532 GUIDFromSSID(wlan_connection_data->dot11Ssid)));
533 break;
534 }
535 case wlan_notification_acm_scan_complete:
536 message_loop_proxy_->PostTask(
537 FROM_HERE,
538 base::Bind(&WiFiServiceImpl::OnNetworkScanCompleteOnMainThread,
539 base::Unretained(this)));
540 break;
541 }
542 }
543
544 void WiFiServiceImpl::OnNetworkScanCompleteOnMainThread() {
545 NetworkList networks;
546 // Get current list of visible networks and notify that network list has
547 // changed.
548 DWORD error = GetVisibleNetworkList(&networks);
549 DCHECK(error == ERROR_SUCCESS);
550 if (error == ERROR_SUCCESS)
551 NotifyNetworkListChanged(networks);
552 }
553
554 void WiFiServiceImpl::WaitForNetworkConnect(const std::string& network_guid,
555 int attempt) {
556 // If network didn't get connected in |kMaxAttempts|, then restore automatic
557 // network change notifications and stop waiting.
558 if (attempt > kMaxAttempts) {
559 DLOG(ERROR) << kMaxAttempts << " attempts exceeded waiting for connect to "
560 << network_guid;
561 enable_notify_network_changed_ = true;
562 RestoreNwCategoryWizard();
563 return;
564 }
565 std::string connected_network_guid;
566 DWORD error = FindConnectedNetwork(&connected_network_guid);
567 if (network_guid == connected_network_guid) {
568 DLOG(INFO) << "WiFi Connected, Reset DHCP: " << network_guid;
569 // Even though wireless network is now connected, it may still be unusable,
570 // e.g. after Chromecast device reset. Reset DHCP on wireless network to
571 // work around this issue.
572 error = ResetDHCP();
573 // Restore previously suppressed notifications.
574 enable_notify_network_changed_ = true;
575 RestoreNwCategoryWizard();
576 NotifyNetworkChanged(network_guid);
577 } else {
578 // Continue waiting for network connection state change.
579 task_runner_->PostDelayedTask(
580 FROM_HERE,
581 base::Bind(&WiFiServiceImpl::WaitForNetworkConnect,
582 base::Unretained(this),
583 network_guid,
584 ++attempt),
585 base::TimeDelta::FromMilliseconds(kAttemptDelayMs));
586 }
587 }
588
589 bool WiFiServiceImpl::CheckError(DWORD error_code,
590 const std::string& error_name,
591 std::string* error) const {
592 if (error_code != ERROR_SUCCESS) {
593 DLOG(ERROR) << "WiFiService Error " << error_code << ": " << error_name;
594 *error = error_name;
595 return true;
596 }
597 return false;
598 }
599
600 WiFiService::NetworkList::iterator WiFiServiceImpl::FindNetwork(
601 NetworkList& networks,
602 const std::string& network_guid) {
603 for (NetworkList::iterator it = networks.begin(); it != networks.end();
604 ++it) {
605 if (it->guid == network_guid)
606 return it;
607 }
608 return networks.end();
609 }
610
611 DWORD WiFiServiceImpl::SaveCurrentConnectedNetwork(
612 std::string* connected_network_guid) {
613 // Find currently connected network.
614 DWORD error = FindConnectedNetwork(connected_network_guid);
615 if (error == ERROR_SUCCESS && !connected_network_guid->empty()) {
616 if (error == ERROR_SUCCESS) {
617 SaveTempProfile(*connected_network_guid);
618 std::string profile_xml;
619 error = GetProfile(*connected_network_guid, &profile_xml);
620 if (error == ERROR_SUCCESS) {
621 saved_profiles_xml_[*connected_network_guid] = profile_xml;
622 }
623 }
624 }
625 return error;
626 }
627
628 void WiFiServiceImpl::SortNetworks(NetworkList* networks) {
629 networks->sort(NetworkProperties::OrderByType);
630 }
631
632 DWORD WiFiServiceImpl::LoadWlanLibrary() {
633 // Use an absolute path to load the DLL to avoid DLL preloading attacks.
634 base::FilePath path;
635 if (!PathService::Get(base::DIR_SYSTEM, &path)) {
636 DLOG(ERROR) << "Unable to get system path.";
637 return ERROR_NOT_FOUND;
638 }
639 wlan_api_library_ = ::LoadLibraryEx(path.Append(kWlanApiDll).value().c_str(),
640 NULL,
641 LOAD_WITH_ALTERED_SEARCH_PATH);
642 if (!wlan_api_library_) {
643 DLOG(ERROR) << "Unable to load WlanApi.dll.";
644 return ERROR_NOT_FOUND;
645 }
646
647 // Initialize WlanApi function pointers
648 WlanConnect_function_ =
649 reinterpret_cast<WlanConnectFunction>(
650 ::GetProcAddress(wlan_api_library_, kWlanConnect));
651 WlanCloseHandle_function_ =
652 reinterpret_cast<WlanCloseHandleFunction>(
653 ::GetProcAddress(wlan_api_library_, kWlanCloseHandle));
654 WlanDisconnect_function_ =
655 reinterpret_cast<WlanDisconnectFunction>(
656 ::GetProcAddress(wlan_api_library_, kWlanDisconnect));
657 WlanEnumInterfaces_function_ =
658 reinterpret_cast<WlanEnumInterfacesFunction>(
659 ::GetProcAddress(wlan_api_library_, kWlanEnumInterfaces));
660 WlanFreeMemory_function_ =
661 reinterpret_cast<WlanFreeMemoryFunction>(
662 ::GetProcAddress(wlan_api_library_, kWlanFreeMemory));
663 WlanGetAvailableNetworkList_function_ =
664 reinterpret_cast<WlanGetAvailableNetworkListFunction>(
665 ::GetProcAddress(wlan_api_library_, kWlanGetAvailableNetworkList));
666 WlanGetNetworkBssList_function_ =
667 reinterpret_cast<WlanGetNetworkBssListFunction>(
668 ::GetProcAddress(wlan_api_library_, kWlanGetNetworkBssList));
669 WlanGetProfile_function_ =
670 reinterpret_cast<WlanGetProfileFunction>(
671 ::GetProcAddress(wlan_api_library_, kWlanGetProfile));
672 WlanOpenHandle_function_ =
673 reinterpret_cast<WlanOpenHandleFunction>(
674 ::GetProcAddress(wlan_api_library_, kWlanOpenHandle));
675 WlanRegisterNotification_function_ =
676 reinterpret_cast<WlanRegisterNotificationFunction>(
677 ::GetProcAddress(wlan_api_library_, kWlanRegisterNotification));
678 WlanSaveTemporaryProfile_function_ =
679 reinterpret_cast<WlanSaveTemporaryProfileFunction>(
680 ::GetProcAddress(wlan_api_library_, kWlanSaveTemporaryProfile));
681 WlanScan_function_ =
682 reinterpret_cast<WlanScanFunction>(
683 ::GetProcAddress(wlan_api_library_, kWlanScan));
684
685 if (!WlanConnect_function_ ||
686 !WlanCloseHandle_function_ ||
687 !WlanDisconnect_function_ ||
688 !WlanEnumInterfaces_function_ ||
689 !WlanFreeMemory_function_ ||
690 !WlanGetAvailableNetworkList_function_ ||
691 !WlanGetProfile_function_ ||
692 !WlanOpenHandle_function_ ||
693 !WlanRegisterNotification_function_ ||
694 !WlanScan_function_) {
695 DLOG(ERROR) << "Unable to find required WlanApi function.";
696 FreeLibrary(wlan_api_library_);
697 wlan_api_library_ = NULL;
698 return ERROR_NOT_FOUND;
699 }
700
701 // Some WlanApi functions may not be available on XP.
702 if (!WlanGetNetworkBssList_function_ ||
703 !WlanSaveTemporaryProfile_function_) {
704 DLOG(INFO) << "WlanApi function is not be available on XP.";
705 }
706
707 return ERROR_SUCCESS;
708 }
709
710 DWORD WiFiServiceImpl::OpenClientHandle() {
711 DWORD error = LoadWlanLibrary();
712 DWORD service_version = 0;
713
714 if (error != ERROR_SUCCESS)
715 return error;
716
717 // Open a handle to the service.
718 error = WlanOpenHandle_function_(1, NULL, &service_version, &client_);
719
720 PWLAN_INTERFACE_INFO_LIST interface_list = NULL;
721 if (error == ERROR_SUCCESS) {
722 // Enumerate wireless interfaces.
723 error = WlanEnumInterfaces_function_(client_, NULL, &interface_list);
724 if (error == ERROR_SUCCESS) {
725 if (interface_list != NULL && interface_list->dwNumberOfItems != 0) {
726 // Remember first interface just in case if none are connected.
727 interface_guid_ = interface_list->InterfaceInfo[0].InterfaceGuid;
728 // Try to find a connected interface.
729 for (DWORD itf = 0; itf < interface_list->dwNumberOfItems; ++itf) {
730 if (interface_list->InterfaceInfo[itf].isState ==
731 wlan_interface_state_connected) {
732 // Found connected interface, remember it!
733 interface_guid_ = interface_list->InterfaceInfo[itf].InterfaceGuid;
734 break;
735 }
736 }
737 WlanRegisterNotification_function_(client_,
738 WLAN_NOTIFICATION_SOURCE_ALL,
739 FALSE,
740 OnWlanNotificationCallback,
741 this,
742 NULL,
743 NULL);
744 } else {
745 error = ERROR_NOINTERFACE;
746 }
747 }
748 // Clean up.
749 if (interface_list != NULL)
750 WlanFreeMemory_function_(interface_list);
751 }
752 return error;
753 }
754
755 DWORD WiFiServiceImpl::ResetDHCP() {
756 IP_ADAPTER_INDEX_MAP adapter_index_map = {0};
757 DWORD error = FindAdapterIndexMapByGUID(interface_guid_, &adapter_index_map);
758 if (error == ERROR_SUCCESS) {
759 error = ::IpReleaseAddress(&adapter_index_map);
760 if (error == ERROR_SUCCESS) {
761 error = ::IpRenewAddress(&adapter_index_map);
762 }
763 }
764 return error;
765 }
766
767 DWORD WiFiServiceImpl::FindAdapterIndexMapByGUID(
768 const GUID& interface_guid,
769 IP_ADAPTER_INDEX_MAP* adapter_index_map) {
770 string16 guid_string;
771 const int kGUIDSize = 39;
772 ::StringFromGUID2(
773 interface_guid, WriteInto(&guid_string, kGUIDSize), kGUIDSize);
774
775 ULONG buffer_length = 0;
776 DWORD error = ::GetInterfaceInfo(NULL, &buffer_length);
777 if (error == ERROR_INSUFFICIENT_BUFFER) {
778 scoped_ptr<unsigned char[]> buffer(new unsigned char[buffer_length]);
779 IP_INTERFACE_INFO* interface_info =
780 reinterpret_cast<IP_INTERFACE_INFO*>(buffer.get());
781 error = GetInterfaceInfo(interface_info, &buffer_length);
782 if (error == ERROR_SUCCESS) {
783 for (int adapter = 0; adapter < interface_info->NumAdapters; ++adapter) {
784 if (EndsWith(
785 interface_info->Adapter[adapter].Name, guid_string, false)) {
786 *adapter_index_map = interface_info->Adapter[adapter];
787 break;
788 }
789 }
790 }
791 }
792 return error;
793 }
794
795 DWORD WiFiServiceImpl::DisableNwCategoryWizard() {
796 base::win::RegKey nw_category_wizard;
797 DWORD error = nw_category_wizard.Open(HKEY_CURRENT_USER,
798 kNwCategoryWizardRegKey,
799 KEY_READ | KEY_SET_VALUE);
800 if (error == ERROR_SUCCESS) {
801 // Save current value if present.
802 if (nw_category_wizard.HasValue(kNwCategoryWizardRegValue)) {
803 DWORD saved = 0u;
804 error = nw_category_wizard.ReadValueDW(kNwCategoryWizardRegValue,
805 &saved);
806 if (error == ERROR_SUCCESS) {
807 error = nw_category_wizard.WriteValue(kNwCategoryWizardSavedRegValue,
808 saved);
809 }
810 } else {
811 // Mark that temporary value has to be deleted.
812 error = nw_category_wizard.WriteValue(kNwCategoryWizardDeleteRegValue,
813 1u);
814 }
815
816 // Disable network location wizard.
817 error = nw_category_wizard.WriteValue(kNwCategoryWizardRegValue,
818 static_cast<DWORD>(0));
819 }
820
821 return error;
822 }
823
824 DWORD WiFiServiceImpl::RestoreNwCategoryWizard() {
825 base::win::RegKey nw_category_wizard;
826 DWORD error = nw_category_wizard.Open(HKEY_CURRENT_USER,
827 kNwCategoryWizardRegKey,
828 KEY_SET_VALUE);
829 if (error == ERROR_SUCCESS) {
830 // Restore saved value if present.
831 if (nw_category_wizard.HasValue(kNwCategoryWizardSavedRegValue)) {
832 DWORD saved = 0u;
833 error = nw_category_wizard.ReadValueDW(kNwCategoryWizardSavedRegValue,
834 &saved);
835 if (error == ERROR_SUCCESS) {
836 error = nw_category_wizard.WriteValue(kNwCategoryWizardRegValue,
837 saved);
838 error = nw_category_wizard.DeleteValue(kNwCategoryWizardSavedRegValue);
839 }
840 } else if (nw_category_wizard.HasValue(kNwCategoryWizardDeleteRegValue)) {
841 error = nw_category_wizard.DeleteValue(kNwCategoryWizardRegValue);
842 error = nw_category_wizard.DeleteValue(kNwCategoryWizardDeleteRegValue);
843 }
844 }
845
846 return error;
847 }
848
849 DWORD WiFiServiceImpl::EnsureInitialized() {
850 if (client_ != NULL)
851 return ERROR_SUCCESS;
852 return ERROR_NOINTERFACE;
853 }
854
855 DWORD WiFiServiceImpl::CloseClientHandle() {
856 DWORD error = ERROR_SUCCESS;
857 if (client_ != NULL) {
858 error = WlanCloseHandle_function_(client_, NULL);
859 client_ = NULL;
860 }
861 if (wlan_api_library_ != NULL) {
862 WlanConnect_function_ = NULL;
863 WlanCloseHandle_function_ = NULL;
864 WlanDisconnect_function_ = NULL;
865 WlanEnumInterfaces_function_ = NULL;
866 WlanFreeMemory_function_ = NULL;
867 WlanGetAvailableNetworkList_function_ = NULL;
868 WlanGetNetworkBssList_function_ = NULL;
869 WlanGetProfile_function_ = NULL;
870 WlanOpenHandle_function_ = NULL;
871 WlanRegisterNotification_function_ = NULL;
872 WlanSaveTemporaryProfile_function_ = NULL;
873 WlanScan_function_ = NULL;
874 ::FreeLibrary(wlan_api_library_);
875 wlan_api_library_ = NULL;
876 }
877 return error;
878 }
879
880 DOT11_SSID WiFiServiceImpl::SSIDFromGUID(
881 const std::string& network_guid) const {
882 DOT11_SSID ssid = {0};
883 if (network_guid.length() <= DOT11_SSID_MAX_LENGTH) {
884 ssid.uSSIDLength = network_guid.length();
885 strncpy(reinterpret_cast<char*>(ssid.ucSSID),
886 network_guid.c_str(),
887 ssid.uSSIDLength);
888 } else {
889 NOTREACHED();
890 }
891 return ssid;
892 }
893
894 std::string WiFiServiceImpl::SecurityFromDot11AuthAlg(
895 DOT11_AUTH_ALGORITHM alg) const {
896 switch (alg) {
897 case DOT11_AUTH_ALGO_RSNA:
898 return onc::wifi::kWPA_EAP;
899 case DOT11_AUTH_ALGO_RSNA_PSK:
900 return onc::wifi::kWPA_PSK;
901 case DOT11_AUTH_ALGO_80211_SHARED_KEY:
902 return onc::wifi::kWEP_PSK;
903 case DOT11_AUTH_ALGO_80211_OPEN:
904 return onc::wifi::kNone;
905 default:
906 return onc::wifi::kWPA_EAP;
907 }
908 }
909
910 void WiFiServiceImpl::NetworkPropertiesFromAvailableNetwork(
911 const WLAN_AVAILABLE_NETWORK& wlan,
912 const WLAN_BSS_LIST& wlan_bss_list,
913 NetworkProperties* properties) {
914 if (wlan.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) {
915 properties->connection_state = onc::connection_state::kConnected;
916 } else {
917 properties->connection_state = onc::connection_state::kNotConnected;
918 }
919
920 properties->ssid = SSIDFromWLAN(wlan);
921 properties->name = properties->ssid;
922 properties->guid = GUIDFromWLAN(wlan);
923 properties->type = onc::network_type::kWiFi;
924
925 for (size_t bss = 0; bss < wlan_bss_list.dwNumberOfItems; ++bss) {
926 const WLAN_BSS_ENTRY& bss_entry(wlan_bss_list.wlanBssEntries[bss]);
927 if (bss_entry.dot11Ssid.uSSIDLength == wlan.dot11Ssid.uSSIDLength &&
928 0 == memcmp(bss_entry.dot11Ssid.ucSSID,
929 wlan.dot11Ssid.ucSSID,
930 bss_entry.dot11Ssid.uSSIDLength)) {
931 if (bss_entry.ulChCenterFrequency < 3000000)
932 properties->frequency = kFrequency2400;
933 else
934 properties->frequency = kFrequency5000;
935 properties->frequency_list.push_back(properties->frequency);
936 properties->bssid = NetworkProperties::MacAddressAsString(
937 bss_entry.dot11Bssid);
938 }
939 }
940 properties->frequency_list.sort();
941 properties->frequency_list.unique();
942 properties->security =
943 SecurityFromDot11AuthAlg(wlan.dot11DefaultAuthAlgorithm);
944 properties->signal_strength = wlan.wlanSignalQuality;
945 }
946
947 // Get the list of visible wireless networks
948 DWORD WiFiServiceImpl::GetVisibleNetworkList(NetworkList* network_list) {
949 if (client_ == NULL) {
950 NOTREACHED();
951 return ERROR_NOINTERFACE;
952 }
953
954 DWORD error = ERROR_SUCCESS;
955 PWLAN_AVAILABLE_NETWORK_LIST available_network_list = NULL;
956 PWLAN_BSS_LIST bss_list = NULL;
957
958 error = WlanGetAvailableNetworkList_function_(
959 client_,
960 &interface_guid_,
961 WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES,
962 NULL,
963 &available_network_list);
964
965 std::set<std::string> network_guids;
966
967 if (error == ERROR_SUCCESS &&
968 available_network_list &&
969 WlanGetNetworkBssList_function_) {
970 // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
971 // needed, then different method of getting BSS (e.g. OID query) will have
972 // to be used.
973 error = WlanGetNetworkBssList_function_(client_,
974 &interface_guid_,
975 NULL,
976 dot11_BSS_type_any,
977 FALSE,
978 NULL,
979 &bss_list);
980 if (error == ERROR_SUCCESS && NULL != bss_list) {
981 for (DWORD i = 0; i < available_network_list->dwNumberOfItems; ++i) {
982 NetworkProperties network_properties;
983 NetworkPropertiesFromAvailableNetwork(
984 available_network_list->Network[i],
985 *bss_list,
986 &network_properties);
987 // Check for duplicate network guids.
988 if (network_guids.count(network_properties.guid)) {
989 // There should be no difference between properties except for
990 // |connection_state|, so mark it as |kConnected| if either one is.
991 if (network_properties.connection_state ==
992 onc::connection_state::kConnected) {
993 NetworkList::iterator previous_network_properties =
994 FindNetwork(*network_list, network_properties.guid);
995 DCHECK(previous_network_properties != network_list->end());
996 previous_network_properties->connection_state =
997 network_properties.connection_state;
998 }
999 } else {
1000 network_list->push_back(network_properties);
1001 }
1002 network_guids.insert(network_properties.guid);
1003 }
1004 }
1005 }
1006
1007 // clean up
1008 if (available_network_list != NULL) {
1009 WlanFreeMemory_function_(available_network_list);
1010 }
1011 if (bss_list != NULL) {
1012 WlanFreeMemory_function_(bss_list);
1013 }
1014 return error;
1015 }
1016
1017 // Find currently connected network.
1018 DWORD WiFiServiceImpl::FindConnectedNetwork(
1019 std::string* connected_network_guid) {
1020 if (client_ == NULL) {
1021 NOTREACHED();
1022 return ERROR_NOINTERFACE;
1023 }
1024
1025 DWORD error = ERROR_SUCCESS;
1026 PWLAN_AVAILABLE_NETWORK_LIST available_network_list = NULL;
1027 error = WlanGetAvailableNetworkList_function_(
1028 client_, &interface_guid_, 0, NULL, &available_network_list);
1029
1030 if (error == ERROR_SUCCESS && NULL != available_network_list) {
1031 for (DWORD i = 0; i < available_network_list->dwNumberOfItems; ++i) {
1032 const WLAN_AVAILABLE_NETWORK& wlan = available_network_list->Network[i];
1033 if (wlan.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) {
1034 *connected_network_guid = GUIDFromWLAN(wlan);
1035 break;
1036 }
1037 }
1038 }
1039
1040 // clean up
1041 if (available_network_list != NULL) {
1042 WlanFreeMemory_function_(available_network_list);
1043 }
1044
1045 return error;
1046 }
1047
1048 DWORD WiFiServiceImpl::GetDesiredBssList(
1049 DOT11_SSID& ssid,
1050 Frequency frequency,
1051 scoped_ptr<DOT11_BSSID_LIST>* desired_list) {
1052 if (client_ == NULL) {
1053 NOTREACHED();
1054 return ERROR_NOINTERFACE;
1055 }
1056
1057 desired_list->reset();
1058
1059 if (frequency == kFrequencyAny)
1060 return ERROR_SUCCESS;
1061
1062 // TODO(mef): WlanGetNetworkBssList is not available on XP. If XP support is
1063 // needed, then different method of getting BSS (e.g. OID query) will have
1064 // to be used.
1065 if (!WlanGetNetworkBssList_function_)
1066 return ERROR_NOT_SUPPORTED;
1067
1068 DWORD error = ERROR_SUCCESS;
1069 PWLAN_BSS_LIST bss_list = NULL;
1070
1071 error = WlanGetNetworkBssList_function_(client_,
1072 &interface_guid_,
1073 NULL,
1074 dot11_BSS_type_any,
1075 FALSE,
1076 NULL,
1077 &bss_list);
1078 if (error == ERROR_SUCCESS && NULL != bss_list) {
1079 unsigned int best_quality = 0u;
1080 size_t best_index = 0;
1081 Frequency bss_frequency;
1082
1083 // Go through bss_list and find best quality BSSID with matching frequency.
1084 for (size_t bss = 0; bss < bss_list->dwNumberOfItems; ++bss) {
1085 const WLAN_BSS_ENTRY& bss_entry(bss_list->wlanBssEntries[bss]);
1086 if (bss_entry.dot11Ssid.uSSIDLength != ssid.uSSIDLength ||
1087 0 != memcmp(bss_entry.dot11Ssid.ucSSID,
1088 ssid.ucSSID,
1089 bss_entry.dot11Ssid.uSSIDLength))
1090 continue;
1091
1092 if (bss_entry.ulChCenterFrequency < 3000000)
1093 bss_frequency = kFrequency2400;
1094 else
1095 bss_frequency = kFrequency5000;
1096
1097 if (bss_frequency == frequency &&
1098 bss_entry.uLinkQuality > best_quality) {
1099 best_quality = bss_entry.uLinkQuality;
1100 best_index = bss;
1101 }
1102 }
1103
1104 // If any matching BSS were found, prepare the header.
1105 if (best_quality > 0) {
1106 const WLAN_BSS_ENTRY& bss_entry(bss_list->wlanBssEntries[best_index]);
1107 scoped_ptr<DOT11_BSSID_LIST> selected_list(new DOT11_BSSID_LIST);
1108
1109 selected_list->Header.Revision = DOT11_BSSID_LIST_REVISION_1;
1110 selected_list->Header.Size = sizeof(DOT11_BSSID_LIST);
1111 selected_list->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
1112 selected_list->uNumOfEntries = 1;
1113 selected_list->uTotalNumOfEntries = 1;
1114 std::copy(bss_entry.dot11Bssid,
1115 bss_entry.dot11Bssid+sizeof(bss_entry.dot11Bssid),
1116 selected_list->BSSIDs[0]);
1117 desired_list->swap(selected_list);
1118 DLOG(INFO) << "Quality: " << best_quality << " BSS: "
1119 << NetworkProperties::MacAddressAsString(bss_entry.dot11Bssid);
1120 } else {
1121 error = ERROR_NOT_FOUND;
1122 }
1123 }
1124
1125 // clean up
1126 if (bss_list != NULL) {
1127 WlanFreeMemory_function_(bss_list);
1128 }
1129 return error;
1130 }
1131
1132
1133 DWORD WiFiServiceImpl::Connect(const std::string& network_guid,
1134 Frequency frequency) {
1135 if (client_ == NULL) {
1136 NOTREACHED();
1137 return ERROR_NOINTERFACE;
1138 }
1139
1140 DWORD error = ERROR_SUCCESS;
1141 DOT11_SSID ssid = SSIDFromGUID(network_guid);
1142 scoped_ptr<DOT11_BSSID_LIST> desired_bss_list;
1143 error = GetDesiredBssList(ssid, frequency, &desired_bss_list);
1144 if (error == ERROR_SUCCESS) {
1145 if (HaveProfile(network_guid)) {
1146 base::string16 profile_name = ProfileNameFromGUID(network_guid);
1147 WLAN_CONNECTION_PARAMETERS wlan_params = {
1148 wlan_connection_mode_profile,
1149 profile_name.c_str(),
1150 NULL,
1151 desired_bss_list.get(),
1152 dot11_BSS_type_any,
1153 0};
1154 error = WlanConnect_function_(
1155 client_, &interface_guid_, &wlan_params, NULL);
1156 } else {
1157 // TODO(mef): wlan_connection_mode_discovery_unsecure is not available on
1158 // XP. If XP support is needed, then temporary profile will have to be
1159 // created.
1160 WLAN_CONNECTION_PARAMETERS wlan_params = {
1161 wlan_connection_mode_discovery_unsecure,
1162 NULL,
1163 &ssid,
1164 desired_bss_list.get(),
1165 dot11_BSS_type_infrastructure,
1166 0};
1167 error = WlanConnect_function_(
1168 client_, &interface_guid_, &wlan_params, NULL);
1169 }
1170 }
1171
1172 return error;
1173 }
1174
1175 DWORD WiFiServiceImpl::Disconnect() {
1176 if (client_ == NULL) {
1177 NOTREACHED();
1178 return ERROR_NOINTERFACE;
1179 }
1180
1181 DWORD error = ERROR_SUCCESS;
1182 error = WlanDisconnect_function_(client_, &interface_guid_, NULL);
1183 return error;
1184 }
1185
1186 DWORD WiFiServiceImpl::SaveTempProfile(const std::string& network_guid) {
1187 if (client_ == NULL) {
1188 NOTREACHED();
1189 return ERROR_NOINTERFACE;
1190 }
1191
1192 DWORD error = ERROR_SUCCESS;
1193 base::string16 profile_name = ProfileNameFromGUID(network_guid);
1194 // TODO(mef): WlanSaveTemporaryProfile is not available on XP. If XP support
1195 // is needed, then different method of saving network profile will have to be
1196 // used.
1197 if (WlanSaveTemporaryProfile_function_) {
1198 error = WlanSaveTemporaryProfile_function_(client_,
1199 &interface_guid_,
1200 profile_name.c_str(),
1201 NULL,
1202 WLAN_PROFILE_USER,
1203 true,
1204 NULL);
1205 } else {
1206 error = ERROR_NOT_SUPPORTED;
1207 }
1208 return error;
1209 }
1210
1211 DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid,
1212 std::string* profile_xml) {
1213 if (client_ == NULL) {
1214 NOTREACHED();
1215 return ERROR_NOINTERFACE;
1216 }
1217
1218 DWORD error = ERROR_SUCCESS;
1219 base::string16 profile_name = ProfileNameFromGUID(network_guid);
1220 LPWSTR str_profile_xml = NULL;
1221 error = WlanGetProfile_function_(client_,
1222 &interface_guid_,
1223 profile_name.c_str(),
1224 NULL,
1225 &str_profile_xml,
1226 NULL,
1227 NULL);
1228
1229 if (error == ERROR_SUCCESS && str_profile_xml != NULL) {
1230 *profile_xml = base::UTF16ToUTF8(str_profile_xml);
1231 }
1232 // clean up
1233 if (str_profile_xml != NULL) {
1234 WlanFreeMemory_function_(str_profile_xml);
1235 }
1236
1237 return error;
1238 }
1239
1240 bool WiFiServiceImpl::HaveProfile(const std::string& network_guid) {
1241 DWORD error = ERROR_SUCCESS;
1242 std::string profile_xml;
1243 return GetProfile(network_guid, &profile_xml) == ERROR_SUCCESS;
1244 }
1245
1246 void WiFiServiceImpl::NotifyNetworkListChanged(const NetworkList& networks) {
1247 if (network_list_changed_observer_.is_null())
1248 return;
1249
1250 NetworkGuidList current_networks;
1251 for (NetworkList::const_iterator it = networks.begin();
1252 it != networks.end();
1253 ++it) {
1254 current_networks.push_back(it->guid);
1255 }
1256
1257 message_loop_proxy_->PostTask(
1258 FROM_HERE,
1259 base::Bind(network_list_changed_observer_, current_networks));
1260 }
1261
1262 void WiFiServiceImpl::NotifyNetworkChanged(const std::string& network_guid) {
1263 if (enable_notify_network_changed_ && !networks_changed_observer_.is_null()) {
1264 DLOG(INFO) << "NotifyNetworkChanged: " << network_guid;
1265 NetworkGuidList changed_networks(1, network_guid);
1266 message_loop_proxy_->PostTask(
1267 FROM_HERE,
1268 base::Bind(networks_changed_observer_, changed_networks));
1269 }
1270 }
1271
1272 WiFiService* WiFiService::Create() { return new WiFiServiceImpl(); }
1273
1274 } // namespace wifi
OLDNEW
« no previous file with comments | « components/wifi/wifi_service_test.cc ('k') | components/wifi/wifi_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698