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

Side by Side Diff: chrome/utility/wifi/wifi_service_win.cc

Issue 27722003: Windows-specific implementation of Networking Private API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Specify wlanapi.lib in chrome.gyp instead of #pragma comment. Created 7 years, 2 months 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
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 "chrome/utility/wifi/wifi_service.h"
6
7 #include <iphlpapi.h>
8 #include <objbase.h>
9 #include <wlanapi.h>
10
11 #include "base/bind.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/strings/string16.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "components/onc/onc_constants.h"
18
19 namespace wifi {
Jói 2013/10/19 21:14:45 I believe in the src/chrome folder we're mostly ge
mef 2013/10/21 15:37:16 Interesting. I'll check the component idea. Per di
Jói 2013/10/21 16:44:03 If there are no plans to use it other than for ext
mef 2013/10/21 19:42:00 Done. If you don't have strong objections I'd keep
20
21 // Implementation of WiFiService for Windows.
22 class WiFiServiceImpl : public WiFiService, base::NonThreadSafe {
23 public:
24 WiFiServiceImpl();
25 virtual ~WiFiServiceImpl();
26
27 // WiFiService interface implementation.
28
29 virtual void GetProperties(const std::string& network_guid,
30 const NetworkPropertiesCallback& callback,
31 const ErrorCallback& error_callback) OVERRIDE;
32
33 virtual void GetState(const std::string& network_guid,
34 const NetworkPropertiesCallback& callback,
35 const ErrorCallback& error_callback) OVERRIDE;
36
37 virtual void GetManagedProperties(
38 const std::string& network_guid,
39 const DictionaryResultCallback& callback,
40 const ErrorCallback& error_callback) OVERRIDE;
41
42 virtual void SetProperties(const std::string& network_guid,
43 const base::DictionaryValue& properties,
44 const StringResultCallback& callback,
45 const ErrorCallback& error_callback) OVERRIDE;
46
47 virtual void GetVisibleNetworks(const NetworkListCallback& callback,
48 const ErrorCallback& error_callback) OVERRIDE;
49
50 virtual void RequestNetworkScan() OVERRIDE;
51
52 virtual void StartConnect(const std::string& network_guid,
53 const StringResultCallback& callback,
54 const ErrorCallback& error_callback) OVERRIDE;
55
56 virtual void StartDisconnect(const std::string& network_guid,
57 const StringResultCallback& callback,
58 const ErrorCallback& error_callback) OVERRIDE;
59
60 virtual void SetNetworksChangedObserver(
61 const NetworkGuidListCallback& observer) OVERRIDE;
62
63 virtual void SetNetworkListChangedObserver(
64 const NetworkGuidListCallback& observer) OVERRIDE;
65
66 private:
67 // Static callback for Windows WLAN_NOTIFICATION. Calls OnWlanNotification
68 // on WiFiServiceImpl passed back as |context|.
69 static void __stdcall OnWlanNotificationCallback(
70 PWLAN_NOTIFICATION_DATA wlan_notification_data,
71 PVOID context);
72
73 // Callback for Windows WLAN_NOTIFICATION. Called on random thread from
74 // OnWlanNotificationCallback. Handles network connectivity and scan complete
75 // notification and posts tasks to main thread.
76 void OnWlanNotification(PWLAN_NOTIFICATION_DATA wlan_notification_data);
77
78 // Handles NetworkScanComplete notification on main thread. Sends
79 // |NetworkListChanged| event with new list of visible networks.
80 void OnNetworkScanCompleteOnMainThread();
81
82 // Wait up to |kMaxAttempts| with |kAttemptDelayMs| delay for connection
83 // to network with |network_guid|. Reset DHCP and Notify that |NetworkChanged|
84 // upon success.
85 void WaitForNetworkConnect(const std::string& network_guid, int attempt);
86
87 // Check |error_code| and if is not |ERROR_SUCCESS|, then run |error_callback|
88 // with |error_name|.
89 bool CheckError(const ErrorCallback& error_callback,
90 const std::string& error_name,
91 DWORD error_code) const;
92
93 // Return |iterator| to network identified by |network_guid| in |networks|
94 // list.
95 NetworkList::const_iterator FindNetwork(
96 const NetworkList& networks,
97 const std::string& network_guid) const;
98
99 // Save currently connected network profile and return its
100 // |connected_network_guid|, so it can be re-connected later.
101 DWORD SaveCurrentConnectedNetwork(std::string* connected_network_guid);
102
103 // Sort networks, so connected/connecting is up front, then by type:
104 // Ethernet, WiFi, Cellular, VPN
105 static void SortNetworks(NetworkList* networks);
106
107 // Open a WLAN client handle, register for WLAN notifications.
108 DWORD OpenClientHandle();
109
110 // Reset DHCP on wireless adapter to speed up reconnect after chromecast
Jói 2013/10/19 21:14:45 Is this code specific to Chromecast? If not, sugge
mef 2013/10/21 15:37:16 Done.
111 // device reset
112 DWORD ResetDHCP();
Jói 2013/10/19 21:14:45 Here you upper-case DHCP; in OnWlanNotification an
mef 2013/10/21 15:37:16 Done. I've chosen upper-case.
113
114 // Find |adapter_index_map| by |interface_guid| for DHCP reset.
115 DWORD FindAdapterIndexMapByGuid(const GUID& interface_guid,
116 IP_ADAPTER_INDEX_MAP* adapter_index_map);
117
118 // Ensure that |client_| handle is initialized.
119 DWORD EnsureInitialized();
120
121 // Close |client_| handle if it is open.
122 DWORD CloseClientHandle();
123
124 // Get |profile_name| from unique |network_guid|.
125 base::string16 ProfileNameFromGuid(const std::string& network_guid) const {
126 return base::UTF8ToUTF16(network_guid);
127 }
128
129 // Get |dot11Ssid| from unique |network_guid|.
130 DOT11_SSID SsidFromGuid(const std::string& network_guid) const;
131
132 // Get unique |network_guid| string based on |dot11Ssid|.
133 std::string GuidFromSsid(const DOT11_SSID& dot11Ssid) const {
afontan 2013/10/21 16:55:23 dot11Ssid is not a GUID and it is not unique. You
mef 2013/10/21 19:42:00 I could make it an interface-ssid-bssid combinatio
afontan 2013/10/21 20:51:02 Correct. The 5GHz/2.4GHz with same SSID is the sce
mef 2013/10/24 23:44:47 Done. Per discussion with tbarzic@ we'll keep the
134 return std::string(reinterpret_cast<const char*>(dot11Ssid.ucSSID),
135 dot11Ssid.uSSIDLength);
136 }
137
138 // Get network |ssid| string based on |wlan|.
139 std::string SsidFromWlan(const WLAN_AVAILABLE_NETWORK& wlan) const {
140 return GuidFromSsid(wlan.dot11Ssid);
141 }
142
143 // Get unique |network_guid| string based on |wlan|.
144 std::string GuidFromWlan(const WLAN_AVAILABLE_NETWORK& wlan) const {
afontan 2013/10/21 16:55:23 ditto.
mef 2013/10/24 23:44:47 Done. Same as GUIDFromSSID().
145 return SsidFromWlan(wlan);
146 }
147
148 // Deduce |onc::wifi| security from |alg|.
149 std::string SecurityFromDot11AuthAlg(DOT11_AUTH_ALGORITHM alg) const;
150
151 // Populate |properties| based on |wlan| and its corresponding bss info from
152 // |wlan_bss_list|.
153 void NetworkPropertiesFromAvailableNetwork(const WLAN_AVAILABLE_NETWORK& wlan,
154 const WLAN_BSS_LIST& wlan_bss_list,
155 NetworkProperties* properties);
156 // Get the list of visible wireless networks.
157 DWORD GetVisibleNetworkList(NetworkList* network_list);
158
159 // Find currently connected network if any. Populate |connected_network_guid|
160 // on success.
161 DWORD FindConnectedNetwork(std::string* connected_network_guid);
162
163 // Connect to network |network_guid| using previosly stored profile if exists,
164 // or just network sid.
165 DWORD Connect(const std::string& network_guid);
166
167 // Disconnect from currently connected network if any.
168 DWORD Disconnect();
169
170 // Save temporary wireless profile for |network_guid|.
171 DWORD SaveTempProfile(const std::string& network_guid);
172
173 // Get previously stored |profile_xml| for |network_guid|.
174 DWORD GetProfile(const std::string& network_guid, std::string* profile_xml);
175
176 // Return true if there is previously stored profile xml for |network_guid|.
177 bool HaveProfile(const std::string& network_guid);
178
179 // Notify |network_list_changed_observer_| that list of visible networks has
180 // changed to |networks|.
181 void NotifyNetworkListChanged(const NetworkList& networks);
182
183 // Notify |networks_changed_observer_| that network |network_guid| status has
184 // changed.
185 void NotifyNetworkChanged(const std::string& network_guid);
186
187 // Wlan Service Handle.
Jói 2013/10/19 21:14:45 Title case seems unnecessary, here and next couple
mef 2013/10/21 15:37:16 Done.
188 HANDLE client_;
189 // Wlan Interface Guid.
Jói 2013/10/19 21:14:45 A better comment might be "GUID of the currently c
mef 2013/10/21 15:37:16 Done.
190 GUID interface_guid_;
191 // Preserved Wlan Profile Xml.
192 std::map<std::string, std::string> saved_profiles_xml_;
193 // Observer to get notified when network(s) have changed (e.g. connect).
194 NetworkGuidListCallback networks_changed_observer_;
195 // Observer to get notified when network list has changed (scan complete).
196 NetworkGuidListCallback network_list_changed_observer_;
197 // Task runner to post tasks on main thread.
198 scoped_refptr<base::TaskRunner> task_runner_;
199 // If |false|, then |networks_changed_observer_| is not notified.
200 bool enable_notify_network_changed_;
201 // Number of attempts to check that network has connected successfully.
202 static const int kMaxAttempts = 100;
203 // Delay between attempts to check that network has connected successfully.
204 static const int kAttemptDelayMs = 100;
205 // Delay after DHCP Renew to allow IP address to be acquired.
206 static const int kDhcpRenewDelayMs = 5000;
207
208 DISALLOW_COPY_AND_ASSIGN(WiFiServiceImpl);
209 };
210
211 WiFiServiceImpl::WiFiServiceImpl()
212 : client_(NULL), enable_notify_network_changed_(true) {}
213
214 WiFiServiceImpl::~WiFiServiceImpl() { CloseClientHandle(); }
215
216 void WiFiServiceImpl::GetProperties(const std::string& network_guid,
217 const NetworkPropertiesCallback& callback,
Jói 2013/10/19 21:14:45 I'm assuming the interface here and other places i
mef 2013/10/21 15:37:16 Yes, AFAIR Mac OS X WiFiFoundation uses callbacks
Jói 2013/10/21 16:44:03 OK, fine by me, just checking.
218 const ErrorCallback& error_callback) {
219 DWORD error = EnsureInitialized();
220 if (error == ERROR_SUCCESS) {
221 NetworkList network_list;
222 error = GetVisibleNetworkList(&network_list);
223 if (error == ERROR_SUCCESS && !network_list.empty()) {
224 NetworkList::const_iterator it = FindNetwork(network_list, network_guid);
225 if (it != network_list.end()) {
226 DLOG(INFO) << "Get Properties: " << network_guid << ":"
227 << it->connection_state;
228 callback.Run(network_guid, *it);
Jói 2013/10/19 21:14:45 Could return right after this, no need to CheckErr
mef 2013/10/21 15:37:16 Done.
229 } else {
230 error = ERROR_NOT_FOUND;
231 }
232 }
233 }
234
235 CheckError(error_callback, "Error.DBusFailed", error);
236 }
237
238 void WiFiServiceImpl::GetState(const std::string& network_guid,
239 const NetworkPropertiesCallback& callback,
240 const ErrorCallback& error_callback) {}
Jói 2013/10/19 21:14:45 Might want to comment here and GetManagedPropertie
mef 2013/10/21 15:37:16 Done.
241
242 void WiFiServiceImpl::GetManagedProperties(
243 const std::string& network_guid,
244 const DictionaryResultCallback& callback,
245 const ErrorCallback& error_callback) {}
246
247 void WiFiServiceImpl::SetProperties(const std::string& network_guid,
248 const base::DictionaryValue& properties,
249 const StringResultCallback& callback,
250 const ErrorCallback& error_callback) {}
251
252 void WiFiServiceImpl::GetVisibleNetworks(const NetworkListCallback& callback,
253 const ErrorCallback& error_callback) {
254 DWORD error = EnsureInitialized();
255
256 if (error == ERROR_SUCCESS) {
257 NetworkList network_list;
258 error = GetVisibleNetworkList(&network_list);
259 if (error == ERROR_SUCCESS && !network_list.empty()) {
260 SortNetworks(&network_list);
afontan 2013/10/21 16:55:23 I would have expected the API to retrieve the netw
mef 2013/10/21 19:42:00 Is it something that could block for considerable
261 callback.Run(network_list);
Jói 2013/10/19 21:14:45 Could return here, no need to CheckError. This pr
mef 2013/10/21 15:37:16 Done.
262 }
263 }
264
265 CheckError(error_callback, "Error.DBusFailed", error);
266 }
267
268 void WiFiServiceImpl::RequestNetworkScan() {
269 DWORD error = EnsureInitialized();
270 if (error == ERROR_SUCCESS) {
271 WlanScan(client_, &interface_guid_, NULL, NULL, NULL);
272 }
273 }
274
275 void WiFiServiceImpl::StartConnect(const std::string& network_guid,
276 const StringResultCallback& callback,
277 const ErrorCallback& error_callback) {
278 DLOG(INFO) << "Start Connect: " << network_guid;
279 DWORD error = EnsureInitialized();
280 if (error == ERROR_SUCCESS) {
281 std::string connected_network_guid;
282 error = SaveCurrentConnectedNetwork(&connected_network_guid);
283 if (error == ERROR_SUCCESS) {
284 // Connect only if network |network_guid| is not connected already.
285 if (network_guid != connected_network_guid)
286 error = Connect(network_guid);
afontan 2013/10/21 16:55:23 One thing we were asked is to avoid the network lo
mef 2013/10/21 19:42:00 Cool, Will do.
mef 2013/10/22 20:06:01 Done.
287 if (error == ERROR_SUCCESS) {
288 callback.Run(network_guid);
Jói 2013/10/19 21:14:45 Just checking: Are you sure you want to run this b
mef 2013/10/21 15:37:16 I think so. Logically caller is start the Connect,
Jói 2013/10/21 16:44:03 OK.
289 // Notify that previously connected network has changed.
290 NotifyNetworkChanged(connected_network_guid);
291 // Start waiting for network connection state change.
292 if (!networks_changed_observer_.is_null()) {
293 // Disable automatic network change notifications.
294 enable_notify_network_changed_ = false;
295 WaitForNetworkConnect(network_guid, 0);
296 }
297 }
298 }
299 }
300 CheckError(error_callback, "Error.DBusFailed", error);
301 }
302
303 void WiFiServiceImpl::StartDisconnect(const std::string& network_guid,
304 const StringResultCallback& callback,
305 const ErrorCallback& error_callback) {
306 DLOG(INFO) << "Start Disconnect: " << network_guid;
307 DWORD error = EnsureInitialized();
308 if (error == ERROR_SUCCESS) {
309 std::string connected_network_guid;
310 error = SaveCurrentConnectedNetwork(&connected_network_guid);
311 if (error == ERROR_SUCCESS && network_guid == connected_network_guid) {
312 error = Disconnect();
313 if (error == ERROR_SUCCESS) {
314 NotifyNetworkChanged(network_guid);
315 callback.Run(network_guid);
316 }
317 }
318 }
319 CheckError(error_callback, "Error.DBusFailed", error);
Jói 2013/10/19 21:14:45 Error.DBusFailed is a bit of a weird error for Win
mef 2013/10/21 15:37:16 Done. Yes, it was a ChromeOS legacy, but it doesn'
320 }
321
322 void WiFiServiceImpl::SetNetworksChangedObserver(
323 const NetworkGuidListCallback& observer) {
324 networks_changed_observer_ = observer;
325 }
326
327 void WiFiServiceImpl::SetNetworkListChangedObserver(
328 const NetworkGuidListCallback& observer) {
329 network_list_changed_observer_ = observer;
330 }
331
332 void WiFiServiceImpl::OnWlanNotificationCallback(
333 PWLAN_NOTIFICATION_DATA wlan_notification_data,
334 PVOID context) {
335 WiFiServiceImpl* service = reinterpret_cast<WiFiServiceImpl*>(context);
336 service->OnWlanNotification(wlan_notification_data);
337 }
338
339 void WiFiServiceImpl::OnWlanNotification(
340 PWLAN_NOTIFICATION_DATA wlan_notification_data) {
341 PWLAN_CONNECTION_NOTIFICATION_DATA wlan_connection_data =
342 reinterpret_cast<PWLAN_CONNECTION_NOTIFICATION_DATA>(
343 wlan_notification_data->pData);
344
345 switch (wlan_notification_data->NotificationCode) {
346 case wlan_notification_acm_disconnected:
347 case wlan_notification_acm_connection_complete:
348 case wlan_notification_acm_connection_attempt_fail:
349 task_runner_->PostTask(
350 FROM_HERE,
351 base::Bind(&WiFiServiceImpl::NotifyNetworkChanged,
352 base::Unretained(this),
353 GuidFromSsid(wlan_connection_data->dot11Ssid)));
354 break;
355 case wlan_notification_acm_scan_complete:
356 task_runner_->PostTask(
357 FROM_HERE,
358 base::Bind(&WiFiServiceImpl::OnNetworkScanCompleteOnMainThread,
359 base::Unretained(this)));
360 break;
361 }
Jói 2013/10/19 21:14:45 I would add a default: case that DCHECKs.
mef 2013/10/21 15:37:16 I can't, there are more notification types that we
Jói 2013/10/21 16:44:03 If you get one of the other notifications, then yo
mef 2013/10/21 19:42:00 Done.
362 }
363
364 void WiFiServiceImpl::OnNetworkScanCompleteOnMainThread() {
365 NetworkList networks;
366 DWORD error = GetVisibleNetworkList(&networks);
Jói 2013/10/19 21:14:45 Why do you need to do this before notifying that t
mef 2013/10/21 15:37:16 Done. Added a comment. Not sure what would a good
Jói 2013/10/21 16:44:03 DCHECK seems right if you expect this to always su
mef 2013/10/21 19:42:00 Done.
367 if (error == ERROR_SUCCESS)
368 NotifyNetworkListChanged(networks);
369 }
370
371 void WiFiServiceImpl::WaitForNetworkConnect(const std::string& network_guid,
372 int attempt) {
373 if (attempt > kMaxAttempts) {
374 enable_notify_network_changed_ = true;
Jói 2013/10/19 21:14:45 Why is this is set to true when max attempts have
mef 2013/10/21 15:37:16 At this point we don't expect this network to get
375 return;
376 }
377 std::string connected_network_guid;
378 DWORD error = FindConnectedNetwork(&connected_network_guid);
379 if (network_guid == connected_network_guid) {
380 DLOG(INFO) << "WiFi Connected, Reset DHCP: " << network_guid;
381 enable_notify_network_changed_ = true;
382 // Reset DHCP to speed up the connection after Chromekey factory reset.
Jói 2013/10/19 21:14:45 Same question on whether code is specific to Chrom
mef 2013/10/21 15:37:16 Done. Added better comment.
383 error = ResetDHCP();
384 if (error == ERROR_SUCCESS) {
385 base::MessageLoop::current()->PostDelayedTask(
Jói 2013/10/19 21:14:45 Why is this delayed if resetting DHCP was successf
mef 2013/10/21 15:37:16 I've added comment, but would love to change it to
Jói 2013/10/21 16:44:03 I'm not aware of a notification you could subscrib
mef 2013/10/21 19:42:00 Sounds good, I'll try to find appropriate API.
mef 2013/10/22 20:06:01 Done. Upon further testing it turned that IP Addre
386 FROM_HERE,
387 base::Bind(&WiFiServiceImpl::NotifyNetworkChanged,
388 base::Unretained(this),
389 network_guid),
390 base::TimeDelta::FromMilliseconds(kDhcpRenewDelayMs));
391 } else {
392 NotifyNetworkChanged(network_guid);
393 }
394 } else {
395 // Continue waiting for network connection state change.
396 base::MessageLoop::current()->PostDelayedTask(
397 FROM_HERE,
398 base::Bind(&WiFiServiceImpl::WaitForNetworkConnect,
399 base::Unretained(this),
400 network_guid,
401 ++attempt),
402 base::TimeDelta::FromMilliseconds(kAttemptDelayMs));
403 }
404 }
405
406 bool WiFiServiceImpl::CheckError(const ErrorCallback& error_callback,
407 const std::string& error_name,
408 DWORD error_code) const {
409 if (error_code != ERROR_SUCCESS) {
410 DLOG(ERROR) << "WiFiService Error " << error_code << ": " << error_name;
411 scoped_ptr<base::DictionaryValue> error_data(new base::DictionaryValue);
412 error_data->SetInteger("Win32ErrorCode", error_code);
413 error_callback.Run(error_name, error_data.Pass());
414 return true;
415 }
416 return false;
417 }
418
419 WiFiService::NetworkList::const_iterator WiFiServiceImpl::FindNetwork(
420 const WiFiService::NetworkList& networks,
421 const std::string& network_guid) const {
422 for (NetworkList::const_iterator it = networks.begin(); it != networks.end();
423 ++it) {
424 if (it->guid == network_guid)
425 return it;
426 }
427 return networks.end();
428 }
429
430 DWORD WiFiServiceImpl::SaveCurrentConnectedNetwork(
431 std::string* connected_network_guid) {
432 // Find currently connected network.
433 DWORD error = FindConnectedNetwork(connected_network_guid);
434 if (error == ERROR_SUCCESS && !connected_network_guid->empty()) {
435 if (error == ERROR_SUCCESS) {
436 SaveTempProfile(*connected_network_guid);
437 std::string profile_xml;
438 error = GetProfile(*connected_network_guid, &profile_xml);
439 if (error == ERROR_SUCCESS) {
440 saved_profiles_xml_[*connected_network_guid] = profile_xml;
441 }
442 }
443 }
444 return error;
445 }
446
447 void WiFiServiceImpl::SortNetworks(NetworkList* networks) {
448 networks->sort(WiFiService::NetworkProperties::OrderByType);
449 }
450
451 DWORD WiFiServiceImpl::OpenClientHandle() {
452 CloseClientHandle();
453
454 DWORD error = ERROR_SUCCESS;
455 DWORD service_version = 0;
456
457 // Open a handle to the service.
458 error = WlanOpenHandle(WLAN_API_VERSION, NULL, &service_version, &client_);
459
afontan 2013/10/21 16:55:23 I assume using WLAN_API_VERSION is fine (given tha
mef 2013/10/21 19:42:00 Could you elaborate on suggested change? Also, I'v
afontan 2013/10/21 20:51:02 Correct. Today we only support win 7/8. For vista
mef 2013/10/22 20:06:01 Done.
460 PWLAN_INTERFACE_INFO_LIST pIntfList = NULL;
Jói 2013/10/19 21:14:45 pIntfList is non-compliant naming; interface_list,
mef 2013/10/21 15:37:16 Done.
461 if (error == ERROR_SUCCESS) {
462 // Enumerate wireless interfaces.
463 error = WlanEnumInterfaces(client_, NULL, &pIntfList);
464 if (error == ERROR_SUCCESS) {
465 if (pIntfList != NULL && pIntfList->dwNumberOfItems != 0) {
466 // Remember first interface.
Jói 2013/10/19 21:14:45 What is special about the first interface, is this
mef 2013/10/21 15:37:16 Yes.
467 interface_guid_ = pIntfList->InterfaceInfo[0].InterfaceGuid;
468 // Try to find connected interface.
Jói 2013/10/19 21:14:45 nit: find connected -> find a connected
mef 2013/10/21 15:37:16 Done.
469 for (DWORD itf = 0; itf < pIntfList->dwNumberOfItems; ++itf) {
470 if (pIntfList->InterfaceInfo[itf].isState ==
471 wlan_interface_state_connected) {
472 // Found connected interface, remember it!
473 interface_guid_ = pIntfList->InterfaceInfo[itf].InterfaceGuid;
afontan 2013/10/21 16:55:23 What if we want to setup with other wifi interface
mef 2013/10/21 19:42:00 Interesting. I suppose this loop could potentially
afontan 2013/10/21 20:51:02 The issue is that we decided to try to setup first
474 break;
475 }
476 }
477 WlanRegisterNotification(client_,
478 WLAN_NOTIFICATION_SOURCE_ALL,
479 FALSE,
480 OnWlanNotificationCallback,
481 this,
482 NULL,
483 NULL);
484 } else {
485 error = ERROR_NOINTERFACE;
486 }
487 }
488 // Clean up.
489 if (pIntfList != NULL)
490 WlanFreeMemory(pIntfList);
491 }
492 return error;
493 }
494
495 DWORD WiFiServiceImpl::ResetDHCP() {
496 IP_ADAPTER_INDEX_MAP adapter_index_map = {0};
497 DWORD error = FindAdapterIndexMapByGuid(interface_guid_, &adapter_index_map);
498 if (error == ERROR_SUCCESS) {
499 error = IpReleaseAddress(&adapter_index_map);
500 if (error == ERROR_SUCCESS) {
501 error = IpRenewAddress(&adapter_index_map);
502 }
503 }
504 return error;
505 }
506
507 DWORD WiFiServiceImpl::FindAdapterIndexMapByGuid(
508 const GUID& interface_guid,
509 IP_ADAPTER_INDEX_MAP* adapter_index_map) {
510 string16 guid_string;
511 const int kGUIDSize = 39;
Jói 2013/10/19 21:14:45 GUID vs. Guid -> be consistent through your code.
mef 2013/10/21 15:37:16 Done.
512 ::StringFromGUID2(
513 interface_guid, WriteInto(&guid_string, kGUIDSize), kGUIDSize);
514
515 ULONG buffer_length = 0;
516 DWORD error = GetInterfaceInfo(NULL, &buffer_length);
517 if (error == ERROR_INSUFFICIENT_BUFFER) {
518 scoped_ptr<unsigned char[]> buffer(new unsigned char[buffer_length]);
519 IP_INTERFACE_INFO* interface_info =
520 reinterpret_cast<IP_INTERFACE_INFO*>(buffer.get());
521 error = GetInterfaceInfo(interface_info, &buffer_length);
522 if (error == ERROR_SUCCESS) {
523 for (int adapter = 0; adapter < interface_info->NumAdapters; ++adapter) {
524 if (EndsWith(
525 interface_info->Adapter[adapter].Name, guid_string, false)) {
526 *adapter_index_map = interface_info->Adapter[adapter];
527 break;
528 }
529 }
530 }
531 }
532 return error;
533 }
534
535 DWORD WiFiServiceImpl::EnsureInitialized() {
536 DCHECK(CalledOnValidThread());
537 if (task_runner_.get() == NULL)
538 task_runner_ = base::MessageLoopProxy::current();
539
540 if (client_ != NULL)
Jói 2013/10/19 21:14:45 Suggest leading with this (right after the DCHECK)
mef 2013/10/21 15:37:16 Done.
541 return ERROR_SUCCESS;
542 return OpenClientHandle();
543 }
544
545 DWORD WiFiServiceImpl::CloseClientHandle() {
546 DWORD error = ERROR_SUCCESS;
547 if (client_ != NULL) {
548 WlanCloseHandle(client_, NULL);
Jói 2013/10/19 21:14:45 should be: error = WlanCloseHandle(client_, NULL)
mef 2013/10/21 15:37:16 Done.
549 client_ = NULL;
550 }
551 return error;
552 }
553
554 DOT11_SSID WiFiServiceImpl::SsidFromGuid(
555 const std::string& network_guid) const {
556 DOT11_SSID ssid = {0};
557 if (network_guid.length() <= DOT11_SSID_MAX_LENGTH) {
Jói 2013/10/19 21:14:45 Should there be e.g. a DCHECK in case the length i
mef 2013/10/21 15:37:16 Done.
558 ssid.uSSIDLength = network_guid.length();
559 strncpy(reinterpret_cast<char*>(ssid.ucSSID),
560 network_guid.c_str(),
561 ssid.uSSIDLength);
562 }
563 return ssid;
564 }
565
566 std::string WiFiServiceImpl::SecurityFromDot11AuthAlg(
567 DOT11_AUTH_ALGORITHM alg) const {
568 // TODO(mef): Figure out correct mapping.
569 switch (alg) {
570 case DOT11_AUTH_ALGO_RSNA:
571 return onc::wifi::kWPA_EAP;
572 case DOT11_AUTH_ALGO_RSNA_PSK:
573 return onc::wifi::kWPA_PSK;
574 case DOT11_AUTH_ALGO_80211_SHARED_KEY:
575 return onc::wifi::kWEP_PSK;
576 case DOT11_AUTH_ALGO_80211_OPEN:
577 return onc::wifi::kNone;
578 default:
579 return onc::wifi::kWPA_EAP;
580 }
581 return onc::wifi::kWPA_EAP;
Jói 2013/10/19 21:14:45 This line is not needed, since you already have a
mef 2013/10/21 15:37:16 Done.
582 }
583
584 void WiFiServiceImpl::NetworkPropertiesFromAvailableNetwork(
585 const WLAN_AVAILABLE_NETWORK& wlan,
586 const WLAN_BSS_LIST& wlan_bss_list,
587 NetworkProperties* properties) {
588 if (wlan.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) {
589 properties->connection_state = onc::connection_state::kConnected;
590 } else {
591 properties->connection_state = onc::connection_state::kNotConnected;
592 }
593
594 properties->ssid = SsidFromWlan(wlan);
595 properties->name = properties->ssid;
596 properties->guid = GuidFromWlan(wlan);
597 properties->type = onc::network_type::kWiFi;
598
599 for (size_t bss = 0; bss < wlan_bss_list.dwNumberOfItems; ++bss) {
600 const WLAN_BSS_ENTRY& bss_entry(wlan_bss_list.wlanBssEntries[bss]);
601 if (bss_entry.dot11Ssid.uSSIDLength == wlan.dot11Ssid.uSSIDLength &&
602 0 == memcmp(bss_entry.dot11Ssid.ucSSID,
603 wlan.dot11Ssid.ucSSID,
604 bss_entry.dot11Ssid.uSSIDLength)) {
605 if (bss_entry.ulChCenterFrequency < 3000000)
606 properties->frequency = kFrequency2400;
607 else
608 properties->frequency = kFrequency5000;
609 properties->frequency_list.push_back(properties->frequency);
610 properties->bssid = WiFiService::NetworkProperties::MacAddressAsString(
Jói 2013/10/19 21:14:45 Is the WiFiService:: prefix needed here?
mef 2013/10/21 15:37:16 Done.
611 bss_entry.dot11Bssid);
612 }
613 }
614 properties->frequency_list.sort();
615 properties->frequency_list.unique();
616 properties->security =
617 SecurityFromDot11AuthAlg(wlan.dot11DefaultAuthAlgorithm);
618 properties->signal_strength = wlan.wlanSignalQuality;
619 }
620
621 // Get the list of visible wireless networks
622 DWORD WiFiServiceImpl::GetVisibleNetworkList(NetworkList* network_list) {
623 DWORD error = ERROR_SUCCESS;
624
625 if (client_ == NULL) {
Jói 2013/10/19 21:14:45 Should there be a NOTREACHED() here to help you ca
mef 2013/10/21 15:37:16 Done.
Jói 2013/10/21 16:44:03 You still need a NOTREACHED() in EnsureInitialized
mef 2013/10/21 19:42:00 Should I add explicit 'Initialize()' method as cur
626 return ERROR_NOINTERFACE;
627 }
628
629 PWLAN_AVAILABLE_NETWORK_LIST pVList = NULL;
Jói 2013/10/19 21:14:45 pVList -> network_list (for example)
mef 2013/10/21 15:37:16 Done.
630 PWLAN_BSS_LIST pWlanBssList = NULL;
Jói 2013/10/19 21:14:45 pWlanBssList -> bss_list (for example)
mef 2013/10/21 15:37:16 Done.
631
632 error =
Jói 2013/10/19 21:14:45 nit: I think it would be more common to break afte
mef 2013/10/21 15:37:16 Done.
633 WlanGetAvailableNetworkList(client_, &interface_guid_, 0, NULL, &pVList);
634
635 if (error == ERROR_SUCCESS && NULL != pVList) {
636 error = WlanGetNetworkBssList(client_,
637 &interface_guid_,
638 NULL,
639 dot11_BSS_type_any,
640 FALSE,
641 NULL,
642 &pWlanBssList);
643 if (error == ERROR_SUCCESS && NULL != pWlanBssList) {
644 for (DWORD i = 0; i < pVList->dwNumberOfItems; ++i) {
645 network_list->push_back(NetworkProperties());
646 NetworkPropertiesFromAvailableNetwork(
647 pVList->Network[i], *pWlanBssList, &network_list->back());
648 }
649 }
650 }
651
652 // clean up
653 if (pVList != NULL) {
654 WlanFreeMemory(pVList);
655 }
656 if (pWlanBssList != NULL) {
657 WlanFreeMemory(pWlanBssList);
658 }
659 return error;
660 }
661
662 // Find currently connected network.
663 DWORD WiFiServiceImpl::FindConnectedNetwork(
664 std::string* connected_network_guid) {
665 DWORD error = ERROR_SUCCESS;
666
667 if (client_ == NULL) {
668 return ERROR_NOINTERFACE;
Jói 2013/10/19 21:14:45 NOTREACHED() ?
mef 2013/10/21 15:37:16 Done.
669 }
670
671 PWLAN_AVAILABLE_NETWORK_LIST pVList = NULL;
Jói 2013/10/19 21:14:45 pVList -> network_list (for example)
mef 2013/10/21 15:37:16 Done.
672
673 error =
674 WlanGetAvailableNetworkList(client_, &interface_guid_, 0, NULL, &pVList);
Jói 2013/10/19 21:14:45 same nit re indenting; more common to indent right
mef 2013/10/21 15:37:16 Done.
afontan 2013/10/21 16:55:23 Flags is currently 0 but you should include hidden
mef 2013/10/21 19:42:00 Done. But why?
afontan 2013/10/21 20:51:02 Because the user may have configured a hidden nerw
675
676 if (error == ERROR_SUCCESS && NULL != pVList) {
677 for (DWORD i = 0; i < pVList->dwNumberOfItems; ++i) {
678 const WLAN_AVAILABLE_NETWORK& wlan = pVList->Network[i];
679 if (wlan.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) {
680 *connected_network_guid = GuidFromWlan(wlan);
681 break;
682 }
683 }
684 }
685
686 // clean up
687 if (pVList != NULL) {
688 WlanFreeMemory(pVList);
689 }
690
691 return error;
692 }
693
694 DWORD WiFiServiceImpl::Connect(const std::string& network_guid) {
afontan 2013/10/21 16:55:23 One scenario we had to cover based on dogfooding w
mef 2013/10/21 19:42:00 Interesting. Could you elaborate on this? Currentl
tbarzic 2013/10/21 20:13:29 On ChromeOs we can't connect to a specific profile
afontan 2013/10/21 20:51:02 We get a list of band filtered Bss entries that co
mef 2013/10/24 23:44:47 Done. On separate CL.
695 DWORD error = ERROR_SUCCESS;
696
697 if (client_ == NULL) {
698 return ERROR_NOINTERFACE;
Jói 2013/10/19 21:14:45 NOTREACHED() ? Here and all remaining "return ERR
mef 2013/10/21 15:37:16 Done.
699 }
700
701 base::string16 profile_name = ProfileNameFromGuid(network_guid);
702
703 if (HaveProfile(network_guid)) {
704 WLAN_CONNECTION_PARAMETERS wlan_params = {
705 wlan_connection_mode_profile, profile_name.c_str(), NULL,
Jói 2013/10/19 21:14:45 Suggest one per line.
mef 2013/10/21 15:37:16 Done.
706 NULL, dot11_BSS_type_any, 0};
707 error = ::WlanConnect(client_, &interface_guid_, &wlan_params, NULL);
708 } else {
709 DOT11_SSID ssid = SsidFromGuid(network_guid);
710 WLAN_CONNECTION_PARAMETERS wlan_params = {
711 wlan_connection_mode_discovery_unsecure, NULL, &ssid, NULL,
Jói 2013/10/19 21:14:45 Suggest one per line.
mef 2013/10/21 15:37:16 Done.
712 dot11_BSS_type_infrastructure, 0};
713 error = ::WlanConnect(client_, &interface_guid_, &wlan_params, NULL);
Jói 2013/10/19 21:14:45 Note that per http://msdn.microsoft.com/en-us/libr
mef 2013/10/21 15:37:16 Yes. This and unsupported WlanGetNetworkBssList fu
Jói 2013/10/21 16:44:03 This needs to be fixed before check-in. According
mef 2013/10/21 19:42:00 Sounds good to be on the safe side, although from
714 }
715
716 return error;
717 }
718
719 DWORD WiFiServiceImpl::Disconnect() {
720 DWORD error = ERROR_SUCCESS;
721
722 if (client_ == NULL) {
723 return ERROR_NOINTERFACE;
724 }
725
726 error = ::WlanDisconnect(client_, &interface_guid_, NULL);
727 return error;
728 }
729
730 DWORD WiFiServiceImpl::SaveTempProfile(const std::string& network_guid) {
731 DWORD error = ERROR_SUCCESS;
732
733 if (client_ == NULL) {
734 return ERROR_NOINTERFACE;
735 }
736
737 base::string16 profile_name = ProfileNameFromGuid(network_guid);
738
739 error = ::WlanSaveTemporaryProfile(
740 client_, &interface_guid_, profile_name.c_str(), NULL, 0, true, NULL);
Jói 2013/10/19 21:14:45 Should the profile perhaps be saved per-user? See
mef 2013/10/21 15:37:16 Done.
afontan 2013/10/21 16:55:23 In the current Chromecast implementation we save i
mef 2013/10/21 19:42:00 Done.
741 return error;
742 }
743
744 DWORD WiFiServiceImpl::GetProfile(const std::string& network_guid,
745 std::string* profile_xml) {
746 DWORD error = ERROR_SUCCESS;
747
748 if (client_ == NULL) {
749 return ERROR_NOINTERFACE;
750 }
751
752 base::string16 profile_name = ProfileNameFromGuid(network_guid);
753 LPWSTR str_profile_xml = NULL;
754 error = ::WlanGetProfile(client_,
Jói 2013/10/19 21:14:45 Suggest using :: in front of all the Win32 APIs yo
mef 2013/10/21 15:37:16 Done.
755 &interface_guid_,
756 profile_name.c_str(),
757 NULL,
758 &str_profile_xml,
759 NULL,
760 NULL);
761
762 if (error == ERROR_SUCCESS && str_profile_xml != NULL) {
763 *profile_xml = base::UTF16ToUTF8(str_profile_xml);
764 }
765 // clean up
766 if (str_profile_xml != NULL) {
767 WlanFreeMemory(str_profile_xml);
768 }
769
770 return error;
771 }
772
773 bool WiFiServiceImpl::HaveProfile(const std::string& network_guid) {
774 DWORD error = ERROR_SUCCESS;
775 std::string profile_xml;
776 return GetProfile(network_guid, &profile_xml) == ERROR_SUCCESS;
777 }
778
779 void WiFiServiceImpl::NotifyNetworkListChanged(const NetworkList& networks) {
780 if (network_list_changed_observer_.is_null())
781 return;
782
783 WiFiService::NetworkGuidList current_networks;
784 for (WiFiService::NetworkList::const_iterator it = networks.begin();
785 it != networks.end();
786 ++it) {
787 current_networks.push_back(it->guid);
788 }
789 network_list_changed_observer_.Run(current_networks);
790 }
791
792 void WiFiServiceImpl::NotifyNetworkChanged(const std::string& network_guid) {
793 if (enable_notify_network_changed_ && !networks_changed_observer_.is_null()) {
794 DLOG(INFO) << "NotifyNetworkChanged: " << network_guid;
795 WiFiService::NetworkGuidList changed_networks(1, network_guid);
Jói 2013/10/19 21:14:45 Is the WiFiService:: prefix needed here?
mef 2013/10/21 15:37:16 Done.
796 networks_changed_observer_.Run(changed_networks);
797 }
798 }
799
800 WiFiService* WiFiService::CreateService() { return new WiFiServiceImpl(); }
801
802 } // namespace wifi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698