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

Side by Side Diff: components/wifi/wifi_service_mac.mm

Issue 64683014: Mac OS X-specific implementation of Networking Private API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address stevenjb's comment. Created 6 years, 11 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
« no previous file with comments | « components/wifi/wifi_service.cc ('k') | components/wifi/wifi_service_win.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 "base/bind.h"
8 #include "base/mac/scoped_nsautorelease_pool.h"
9 #include "base/mac/scoped_nsobject.h"
10 #include "base/message_loop/message_loop.h"
11 #include "components/onc/onc_constants.h"
12
13 #import <netinet/in.h>
Robert Sesek 2014/01/07 16:19:05 These headers come below the .h for the .mm and be
mef 2014/01/08 21:00:03 Done.
14 #import <CoreWLAN/CoreWLAN.h>
15 #import <SystemConfiguration/SystemConfiguration.h>
16
17 namespace {
18 // Declare notification names from the 10.7 SDK.
19 const char* kCWSSIDDidChangeNotification_chrome =
Robert Sesek 2014/01/07 16:19:05 kCWSSIDDidChangeNotification is marked as availabl
mef 2014/01/08 21:00:03 Is it ok to link to CoreWLAN.framework, or should
Robert Sesek 2014/01/09 23:12:45 I think it's fine to link it directly in the link_
mef 2014/01/10 17:01:52 Done.
20 "com.apple.coreWLAN.notification.ssid";
21 } // namespace
22
23 #if !defined(MAC_OS_X_VERSION_10_7) || \
24 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
25
26 // Local definitions of API added in Mac OS X 10.7
27
28 @interface CWInterface (LionAPI)
29 - (BOOL)associateToNetwork:(CWNetwork *)network
Robert Sesek 2014/01/07 16:19:05 nit: here and throughout, there's no space between
mef 2014/01/08 21:00:03 Done.
30 password:(NSString *)password
31 error:(NSError **)error;
32 - (NSSet*)scanForNetworksWithName:(NSString *)networkName
33 error:(NSError **)error;
34 @end
35
36 enum CWChannelBand {
37 kCWChannelBandUnknown = 0,
Robert Sesek 2014/01/07 16:19:05 nit: only indent 2 spaces
mef 2014/01/08 21:00:03 Done.
38 kCWChannelBand2GHz = 1,
39 kCWChannelBand5GHz = 2,
40 };
41
42 @interface CWChannel : NSObject
43 @property(readonly) CWChannelBand channelBand;
44 @end
45
46 @interface CWNetwork (LionAPI)
47 @property(readonly) CWChannel *wlanChannel;
48 @end
49
50 #endif // 10.7
51
52 // Observe CoreWLAN notifications and call |WiFiServiceImpl| on worker thread.
tbarzic 2014/01/07 20:05:33 This seems to observe only "connected network ssid
mef 2014/01/08 21:00:03 Done.
53 @interface WLANNotificationObserver : NSObject {
54 // Task runner for worker tasks.
55 scoped_refptr<base::SequencedTaskRunner> task_runner_;
56 // Notification handler.
57 base::Closure notification_handler_;
58 }
59 @end
60
61 @implementation WLANNotificationObserver
62
63 // Upon receiving |notification| post |notification_handler_| to |task_runner_|.
64 - (void)handleInterfaceNotification:(NSNotification*)notification {
65 DCHECK(task_runner_);
66 DCHECK(!notification_handler_.is_null());
67 task_runner_->PostTask(FROM_HERE, notification_handler_);
68 }
69
70 // Start listening for WLAN notifications.
71 - (void)startListen:(base::Closure) notification_handler
72 usingTaskRunner:(scoped_refptr<base::SequencedTaskRunner>) task_runner {
73 notification_handler_ = notification_handler;
74 task_runner_ = task_runner;
75 [[NSNotificationCenter defaultCenter]
Robert Sesek 2014/01/07 16:19:05 You can remove this entire ObjC class if you use t
mef 2014/01/08 21:00:03 Done.
76 addObserver:self
77 selector:@selector(handleInterfaceNotification:)
78 name:[NSString stringWithUTF8String:kCWSSIDDidChangeNotification_chrome]
79 object:nil];
80 }
81
82 // Stop listening for WLAN notifications.
83 - (void)stopListen
84 {
85 [[NSNotificationCenter defaultCenter] removeObserver:self];
86 }
87
88 @end
89
90 namespace wifi {
91
92 // Implementation of WiFiService for Mac OS X.
93 class WiFiServiceImpl : public WiFiService {
Robert Sesek 2014/01/07 16:19:05 Why not call this WiFiServiceMac ?
mef 2014/01/08 21:00:03 Done.
94 public:
95 WiFiServiceImpl();
96 virtual ~WiFiServiceImpl();
97
98 // WiFiService interface implementation.
99 virtual void Initialize(
100 scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE;
101
102 virtual void UnInitialize() OVERRIDE;
103
104 virtual void GetProperties(const std::string& network_guid,
105 base::DictionaryValue* properties,
106 std::string* error) OVERRIDE;
107
108 virtual void GetManagedProperties(const std::string& network_guid,
109 base::DictionaryValue* managed_properties,
110 std::string* error) OVERRIDE;
111
112 virtual void GetState(const std::string& network_guid,
113 base::DictionaryValue* properties,
114 std::string* error) OVERRIDE;
115
116 virtual void SetProperties(const std::string& network_guid,
117 scoped_ptr<base::DictionaryValue> properties,
118 std::string* error) OVERRIDE;
119
120 virtual void CreateNetwork(bool shared,
121 scoped_ptr<base::DictionaryValue> properties,
122 std::string* network_guid,
123 std::string* error) OVERRIDE;
124
125 virtual void GetVisibleNetworks(const std::string& network_type,
126 base::ListValue* network_list) OVERRIDE;
127
128 virtual void RequestNetworkScan() OVERRIDE;
129
130 virtual void StartConnect(const std::string& network_guid,
131 std::string* error) OVERRIDE;
132
133 virtual void StartDisconnect(const std::string& network_guid,
134 std::string* error) OVERRIDE;
135
136 virtual void SetEventObservers(
137 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
138 const NetworkGuidListCallback& networks_changed_observer,
139 const NetworkGuidListCallback& network_list_changed_observer) OVERRIDE;
140
141 private:
142 // Check |nsError| and if is not |nil|, then store |error_name|
143 // into |error|.
144 bool CheckError(NSError* nsError,
Robert Sesek 2014/01/07 16:19:05 naming: In C++, variables do not use camelCase.
mef 2014/01/08 21:00:03 Done.
145 const char* error_name,
146 std::string* error) const;
147
148 // Get |ssid| from unique |network_guid|.
149 NSString* SSIDFromGUID(const std::string& network_guid) const {
Robert Sesek 2014/01/07 16:19:05 I think you can remove this and the method below e
mef 2014/01/08 21:00:03 I'd like to have explicit SSID / GUID convertors i
150 return [NSString stringWithUTF8String:network_guid.c_str()];
151 }
152
153 // Get unique |network_guid| string based on |ssid|.
154 std::string GUIDFromSSID(NSString* ssid) const {
155 if (ssid == nil)
156 return std::string();
157 return std::string([ssid UTF8String]);
158 }
159
160 // Populate |properties| from |network|.
161 void NetworkPropertiesFromCWNetwork(const CWNetwork* network,
162 NetworkProperties* properties) const;
163
164 // Convert |CWSecurityMode| into onc::wifi::k{WPA|WEP}* security constant.
165 std::string SecurityFromCWSecurityMode(CWSecurityMode security) const;
166
167 // Wait up to |kMaxAttempts| with |kAttemptDelayMs| delay for connection
168 // to network with |network_guid|. Notify that |NetworkChanged| upon success.
169 void WaitForNetworkConnect(const std::string& network_guid, int attempt);
170
171 // Get the list of visible wireless networks. If |network_guid| is not empty,
172 // then only return that network.
173 NSError* GetVisibleNetworkList(const std::string& network_guid,
174 NetworkList* network_list);
175
176 // Sort networks, so connected/connecting is up front, then by type:
177 // Ethernet, WiFi, Cellular, VPN
tbarzic 2014/01/07 20:05:33 missing . at the end of the comment
mef 2014/01/08 21:00:03 Done.
178 static void SortNetworks(NetworkList* networks);
179
180 // Handle notification from |WLANListener|;
tbarzic 2014/01/07 20:05:33 Hm, I can't see anything named |WLANListener| here
mef 2014/01/08 21:00:03 Done.
181 void OnListenerNotification();
182
183 // Notify |network_list_changed_observer_| that list of visible networks has
184 // changed to |networks|.
185 void NotifyNetworkListChanged(const NetworkList& networks);
186
187 // Notify |networks_changed_observer_| that network |network_guid| status has
188 // changed.
189 void NotifyNetworkChanged(const std::string& network_guid);
190
191 // CoreWLAN.Framework bundle.
192 base::scoped_nsobject<NSBundle> bundle_;
193 // Default interface.
194 base::scoped_nsobject<CWInterface> interface_;
195 // WLAN Notifications observer.
196 base::scoped_nsobject<WLANNotificationObserver> wlan_observer_;
197
198 // Observer to get notified when network(s) have changed (e.g. connect).
199 NetworkGuidListCallback networks_changed_observer_;
200 // Observer to get notified when network list has changed (scan complete).
201 NetworkGuidListCallback network_list_changed_observer_;
202 // MessageLoopProxy to post events on UI thread.
203 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
204 // Task runner for worker tasks.
205 scoped_refptr<base::SequencedTaskRunner> task_runner_;
206 // Cache of network list collected by GetVisibleNetworks.
207 NetworkList networks_;
208 // Temporary storage of network properties indexed by |network_guid|.
209 base::DictionaryValue network_properties_;
210 // If |false|, then |networks_changed_observer_| is not notified.
211 bool enable_notify_network_changed_;
212 // Number of attempts to check that network has connected successfully.
213 static const int kMaxAttempts = 200;
tbarzic 2014/01/07 20:05:33 the name could be more descriptive (e.g. kMaxConne
mef 2014/01/08 21:00:03 Done.
214 // Delay between attempts to check that network has connected successfully.
215 static const int kAttemptDelayMs = 100;
216 };
217
218 WiFiServiceImpl::WiFiServiceImpl() : enable_notify_network_changed_(true) {
219 }
220
221 WiFiServiceImpl::~WiFiServiceImpl() {
222 }
223
224 void WiFiServiceImpl::Initialize(
225 scoped_refptr<base::SequencedTaskRunner> task_runner) {
226 // As the WLAN api binding runs on its own thread, we need to provide our own
Robert Sesek 2014/01/07 16:19:05 I don't understand this. What's backing this Seque
mef 2014/01/08 21:00:03 I'm not sure I understand the question, could you
Robert Sesek 2014/01/09 23:12:45 I don't think you need to supply your own autorele
mef 2014/01/10 17:01:52 FYI: WiFiService calls are posted from UI thread t
Robert Sesek 2014/01/10 18:59:51 As I wrote above, it is not necessary. Worker thre
mef 2014/01/10 20:26:16 Done.
227 // auto release pool. It's simplest to do this as an automatic variable in
228 // each method that needs it, to ensure the scoping is correct and does not
229 // interfere with any other code using autorelease pools on the thread.
230 base::mac::ScopedNSAutoreleasePool auto_pool;
231
232 task_runner_.swap(task_runner);
233
234 bundle_.reset([[NSBundle alloc]
235 initWithPath:@"/System/Library/Frameworks/CoreWLAN.framework"]);
Robert Sesek 2014/01/07 16:19:05 Why do you dynamically load CoreWLAN?
mef 2014/01/08 21:00:03 To mimic geolocation code, but I guess we can actu
Robert Sesek 2014/01/09 23:12:45 Yes. I think so.
mef 2014/01/10 17:01:52 Done.
236 if (!bundle_) {
237 DVLOG(1) << "Failed to load the CoreWLAN framework bundle";
238 return;
239 }
240
241 Class cw_interface_class = [bundle_ classNamed:@"CWInterface"];
242 interface_.reset([[cw_interface_class interface] retain]);
243 if (!bundle_) {
244 DVLOG(1) << "Failed to initialize default interface";
245 return;
246 }
247
248 WLANNotificationObserver* observer = [[WLANNotificationObserver alloc] init];
Robert Sesek 2014/01/07 16:19:05 Put this in the scoper to start with, rather than
mef 2014/01/08 21:00:03 Done.
249 [observer startListen:base::Bind(&WiFiServiceImpl::OnListenerNotification,
250 base::Unretained(this))
251 usingTaskRunner:task_runner_];
252 wlan_observer_.reset(observer);
253 }
254
255 void WiFiServiceImpl::UnInitialize() {
256 [wlan_observer_ stopListen];
257 }
258
259 void WiFiServiceImpl::GetProperties(const std::string& network_guid,
260 base::DictionaryValue* properties,
261 std::string* error) {
262 base::mac::ScopedNSAutoreleasePool auto_pool;
263
264 if (networks_.empty()) {
265 DVLOG(1) << "GetProperties";
266 NSError* nsError = GetVisibleNetworkList(std::string(), &networks_);
Robert Sesek 2014/01/07 16:19:05 naming: nsError
mef 2014/01/08 21:00:03 Done.
267 if (CheckError(nsError, "Error.GetProperties", error))
268 return;
269 }
270
271 for (WiFiService::NetworkList::iterator it = networks_.begin();
272 it != networks_.end();
273 ++it) {
274 if (it->guid == network_guid) {
275 bool is_connected = network_guid == GUIDFromSSID([interface_ ssid]);
276 it->connection_state =
277 is_connected ? onc::connection_state::kConnected :
278 onc::connection_state::kNotConnected;
279 scoped_ptr<base::DictionaryValue> network(it->ToValue(false));
280 properties->Swap(network.get());
281 DVLOG(1) << *properties;
282 return;
283 }
284 }
285
286 *error = "Error.NotFound";
287 }
288
289 void WiFiServiceImpl::GetManagedProperties(
290 const std::string& network_guid,
291 base::DictionaryValue* managed_properties,
292 std::string* error) {
293 *error = "Error.NotImplemented";
Robert Sesek 2014/01/07 16:19:05 Are these going to be implemented?
mef 2014/01/08 21:00:03 At some point, not in current release.
294 }
295
296 void WiFiServiceImpl::GetState(const std::string& network_guid,
297 base::DictionaryValue* properties,
298 std::string* error) {
299 *error = "Error.NotImplemented";
300 }
301
302 void WiFiServiceImpl::SetProperties(
303 const std::string& network_guid,
304 scoped_ptr<base::DictionaryValue> properties,
305 std::string* error) {
306 base::mac::ScopedNSAutoreleasePool auto_pool;
307 network_properties_.SetWithoutPathExpansion(network_guid,
308 properties.release());
309 }
310
311 void WiFiServiceImpl::CreateNetwork(
312 bool shared,
313 scoped_ptr<base::DictionaryValue> properties,
314 std::string* network_guid,
315 std::string* error) {
316 *error = "Error.NotImplemented";
317 }
318
319 void WiFiServiceImpl::GetVisibleNetworks(const std::string& network_type,
320 base::ListValue* network_list) {
321 if (!network_type.empty() &&
322 network_type != onc::network_type::kAllTypes &&
323 network_type != onc::network_type::kWiFi) {
324 return;
325 }
326
327 DVLOG(1) << __FUNCTION__;
Robert Sesek 2014/01/07 16:19:05 Remove unnecessary logging; here and throughout.
mef 2014/01/08 21:00:03 Why?
Robert Sesek 2014/01/09 23:12:45 It needlessly clutters the code.
328
329 base::mac::ScopedNSAutoreleasePool auto_pool;
330
331 GetVisibleNetworkList(std::string(), &networks_);
332
333 SortNetworks(&networks_);
334 for (WiFiService::NetworkList::const_iterator it = networks_.begin();
335 it != networks_.end();
336 ++it) {
337 scoped_ptr<base::DictionaryValue> network(it->ToValue(true));
338 network_list->Append(network.release());
339 }
340 }
341
342 void WiFiServiceImpl::RequestNetworkScan() {
343 base::mac::ScopedNSAutoreleasePool auto_pool;
344 NetworkList networks;
345 DVLOG(1) << __FUNCTION__;
346
347 NSError* nsError = GetVisibleNetworkList(std::string(), &networks);
Robert Sesek 2014/01/07 16:19:05 naming: nsError. Here and throughout.
mef 2014/01/08 21:00:03 Done.
348 if (nsError == nil && !networks.empty()) {
349 NotifyNetworkListChanged(networks);
350 }
351 }
352
353 void WiFiServiceImpl::StartConnect(const std::string& network_guid,
354 std::string* error) {
355 base::mac::ScopedNSAutoreleasePool auto_pool;
356 NSError* nsError = nil;
357
358 DVLOG(1) << "*** StartConnect: " << network_guid;
359 NSSet* networks = [interface_
360 scanForNetworksWithName:SSIDFromGUID(network_guid)
361 error:&nsError];
362
363 if (CheckError(nsError, "Error.scanForNetworksWithName", error))
Robert Sesek 2014/01/07 16:19:05 Should these errors be made into constants?
mef 2014/01/08 21:00:03 Done.
364 return;
365
366 CWNetwork* network = [networks anyObject];
367 if (network == nil) {
368 *error = "Error.NotFound";
369 return;
370 }
371 // Remember previously connected network.
372 std::string connected_network_guid = GUIDFromSSID([interface_ ssid]);
373 // Check, whether desired network is already connected.
374 if (network_guid == connected_network_guid) {
375 NotifyNetworkChanged(connected_network_guid);
376 return;
377 }
378 // Check whether WiFi Password is set in |network_properties_|
379 base::DictionaryValue* properties;
380 base::DictionaryValue* wifi;
381 std::string passphrase;
382 NSString* nsPassword = nil;
Robert Sesek 2014/01/07 16:19:05 naming
mef 2014/01/08 21:00:03 Done.
383 if (network_properties_.GetDictionaryWithoutPathExpansion(network_guid,
384 &properties) &&
385 properties->GetDictionary(onc::network_type::kWiFi, &wifi) &&
386 wifi->GetString(onc::wifi::kPassphrase, &passphrase)) {
387 nsPassword = [NSString stringWithUTF8String:passphrase.c_str()];
Robert Sesek 2014/01/07 16:19:05 base/strings/sys_string_conversions.h
mef 2014/01/08 21:00:03 Done.
388 }
389
390 // Disable automatic network change notifications as they get fired
391 // when network is just connected, but not yet accessible (doesn't
392 // have valid IP address).
tbarzic 2014/01/07 20:05:33 This seems wrong.. what if another network gets co
mef 2014/01/08 21:00:03 I think I should change 'GetProperties' to check r
tbarzic 2014/01/08 23:06:23 sounds good
mef 2014/01/10 20:26:16 Done.
393 enable_notify_network_changed_ = false;
394 // Number of attempts to associate to network.
395 static const int kMaxAssociationAttempts = 3;
396 // Try to associate to network several times if timeout or PMK error occurs.
397 for (int i = 0; i < kMaxAssociationAttempts; ++i) {
398 // Nil out the PMK to prevent stale data from causing invalid PMK error
399 // (CoreWLANTypes -3924).
400 [interface_ setPairwiseMasterKey:nil error:&nsError];
401 if ([interface_ associateToNetwork:network
Robert Sesek 2014/01/07 16:19:05 What if this is running on 10.6? This method is on
mef 2014/01/08 21:00:03 Couple of followup questions: - What is suggested
Robert Sesek 2014/01/09 23:12:45 This is the first time I've ever seen Apple actual
mef 2014/01/10 17:01:52 Done.
402 password:nsPassword
403 error:&nsError]) {
404 // Notify that previously connected network has changed.
405 NotifyNetworkChanged(connected_network_guid);
406
407 // Start waiting for network connection state change.
tbarzic 2014/01/07 20:05:33 Add a comment that WaiForNetworkConnect is async a
mef 2014/01/08 21:00:03 Done.
408 if (!networks_changed_observer_.is_null()) {
409 WaitForNetworkConnect(network_guid, 0);
410 return;
411 }
412 } else {
413 long error_code = [nsError code];
Robert Sesek 2014/01/07 16:19:05 long -> NSInteger
mef 2014/01/08 21:00:03 Done.
414 if (error_code != kCWTimeoutErr && error_code != kCWInvalidPMKErr) {
415 break;
416 }
417 }
418 }
419 enable_notify_network_changed_ = true;
420 CheckError(nsError, "Error.associateToNetwork", error);
421 }
422
423 void WiFiServiceImpl::StartDisconnect(const std::string& network_guid,
424 std::string* error) {
425 base::mac::ScopedNSAutoreleasePool auto_pool;
426 DVLOG(1) << "*** StartDisconnect: " << network_guid;
427
428 if (network_guid == GUIDFromSSID([interface_ ssid])) {
429 [interface_ disassociate];
430 NotifyNetworkChanged(network_guid);
tbarzic 2014/01/07 20:05:33 Shouldn't this be reported from |OnListenerNotific
mef 2014/01/08 21:00:03 Done.
431 } else {
432 *error = "not-connected";
Robert Sesek 2014/01/07 16:19:05 Why doesn't this error start with |Error.|?
mef 2014/01/08 21:00:03 Done.
433 }
434 }
435
436 void WiFiServiceImpl::SetEventObservers(
437 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
438 const NetworkGuidListCallback& networks_changed_observer,
439 const NetworkGuidListCallback& network_list_changed_observer) {
440 base::mac::ScopedNSAutoreleasePool auto_pool;
441 message_loop_proxy_.swap(message_loop_proxy);
442 networks_changed_observer_ = networks_changed_observer;
443 network_list_changed_observer_ = network_list_changed_observer;
444 }
445
446 void WiFiServiceImpl::WaitForNetworkConnect(const std::string& network_guid,
447 int attempt) {
448 // If network didn't get connected in |kMaxAttempts|, then restore automatic
449 // network change notifications and stop waiting.
450 if (attempt > kMaxAttempts) {
451 DLOG(ERROR) << kMaxAttempts << " attempts exceeded waiting for connect to "
452 << network_guid;
453 // Restore previously suppressed notifications.
454 enable_notify_network_changed_ = true;
455 return;
456 }
457
458 // Check whether WiFi network is reachable.
459 struct sockaddr_in localWiFiAddress;
Robert Sesek 2014/01/07 16:19:05 naming
mef 2014/01/08 21:00:03 Done.
460 bzero(&localWiFiAddress, sizeof(localWiFiAddress));
461 localWiFiAddress.sin_len = sizeof(localWiFiAddress);
462 localWiFiAddress.sin_family = AF_INET;
463 localWiFiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
464
465 SCNetworkReachabilityRef reachability =
Robert Sesek 2014/01/07 16:19:05 Use a ScopedCFTypeRef.
mef 2014/01/08 21:00:03 Done.
466 SCNetworkReachabilityCreateWithAddress(
467 kCFAllocatorDefault,
468 (const struct sockaddr*)&localWiFiAddress);
Robert Sesek 2014/01/07 16:19:05 C-style casts are banned.
mef 2014/01/08 21:00:03 Done.
469 SCNetworkReachabilityFlags flags = 0u;
470 if (SCNetworkReachabilityGetFlags(reachability, &flags) &&
471 (flags & kSCNetworkReachabilityFlagsReachable) &&
472 (flags & kSCNetworkReachabilityFlagsIsDirect)) {
473 DVLOG(1) << "WiFi Connected, Reachable: " << network_guid;
474 // Restore previously suppressed notifications.
475 enable_notify_network_changed_ = true;
476 NotifyNetworkChanged(network_guid);
477 } else {
478 DVLOG(1) << "Attempt:" << attempt << ", reachability:" << flags;
479 // Continue waiting for network connection state change.
480 task_runner_->PostDelayedTask(
481 FROM_HERE,
482 base::Bind(&WiFiServiceImpl::WaitForNetworkConnect,
483 base::Unretained(this),
484 network_guid,
485 ++attempt),
486 base::TimeDelta::FromMilliseconds(kAttemptDelayMs));
487 }
488
489 if (reachability)
490 CFRelease(reachability);
491 }
492
493
494 NSError* WiFiServiceImpl::GetVisibleNetworkList(const std::string& network_guid,
495 NetworkList* network_list) {
496
497 NSError* nsError = nil;
498 NSString* networkName = nil;
Robert Sesek 2014/01/07 16:19:05 naming
mef 2014/01/08 21:00:03 Done.
499
500 DVLOG(1) << "<<< GetVisibleNetworkList: " << network_guid;
501
502 if (!network_guid.empty())
503 networkName = SSIDFromGUID(network_guid);
504
505 NSSet* networks = [interface_ scanForNetworksWithName:networkName
506 error:&nsError];
507 if (nsError != nil)
508 return nsError;
509
510 std::map<std::string, NetworkProperties*> network_properties_map;
511
512 CWNetwork* network;
513 // There is one |network| per BSS in |networks|, so go through the set and
514 // combine them, paying attention to supported frequencies.
515 for(network in networks) {
Robert Sesek 2014/01/07 16:19:05 nit: space before (
mef 2014/01/08 21:00:03 Done.
516 NetworkProperties network_properties;
517 NetworkPropertiesFromCWNetwork(network, &network_properties);
518
519 if (network_properties_map.find(network_properties.guid) ==
520 network_properties_map.end()) {
521 network_list->push_back(network_properties);
522 network_properties_map[network_properties.guid] = &network_list->back();
523 } else {
524 NetworkProperties* existing = network_properties_map.at(
525 network_properties.guid);
526 existing->frequency_set.insert(*network_properties.frequency_set.begin());
527 }
528 }
529 DVLOG(1) << ">>> GetVisibleNetworkList: " << network_guid;
530
531 return nil;
532 }
533
534 bool WiFiServiceImpl::CheckError(NSError* nsError,
535 const char* error_name,
536 std::string* error) const {
537 if (nsError != nil) {
538 DLOG(ERROR) << "*** Error:" << error_name << ":" << [nsError code];
539 *error = error_name;
540 return true;
541 }
542 return false;
543 }
544
545 void WiFiServiceImpl::NetworkPropertiesFromCWNetwork(
546 const CWNetwork* network,
547 NetworkProperties* properties) const {
548
549 if (NSOrderedSame == [[network ssid] compare:[interface_ ssid]])
Robert Sesek 2014/01/07 16:19:05 Preference is for |expr == NSOrderedSame| http://
mef 2014/01/08 21:00:03 Done.
550 properties->connection_state = onc::connection_state::kConnected;
551 else
552 properties->connection_state = onc::connection_state::kNotConnected;
553
554 properties->ssid = [[network ssid] UTF8String];
Robert Sesek 2014/01/07 16:19:05 sys_string_conversions.h. This looks like you're a
mef 2014/01/08 21:00:03 |ssid| and other properties are std::string.
Robert Sesek 2014/01/09 23:12:45 Yes, but I had to look that up. It looks like you'
mef 2014/01/10 17:01:52 Any suggestions on making it more apparent?
Robert Sesek 2014/01/10 18:59:51 Yes, the string conversion function to make it exp
mef 2014/01/10 20:26:16 Done. Use SysNSStringToUTF8.
555 properties->name = properties->ssid;
556 properties->guid = GUIDFromSSID([network ssid]);
557 properties->type = onc::network_type::kWiFi;
558
559 properties->bssid = [[network bssid] UTF8String];
560 if ([[network wlanChannel] channelBand] == kCWChannelBand2GHz)
Robert Sesek 2014/01/07 16:19:05 Again, what if this is running on a 10.6 machine?
mef 2014/01/08 21:00:03 Is there some other way to get this info on 10.6 m
Robert Sesek 2014/01/09 23:12:45 That I do not know, unfortunately :|.
mef 2014/01/10 17:01:52 It seems that native ChromeCast App only supports
Robert Sesek 2014/01/10 18:59:51 Chrome needs to run on 10.6. If you call this as i
mef 2014/01/10 20:26:16 Done. Added respondsToSelector:@selector(associate
561 properties->frequency = kFrequency2400;
562 else
563 properties->frequency = kFrequency5000;
564 properties->frequency_set.insert(properties->frequency);
565 properties->security = SecurityFromCWSecurityMode(
566 static_cast<CWSecurityMode>([[network securityMode] intValue]));
567
568 properties->signal_strength = [[network rssi] intValue];
569 }
570
571 std::string WiFiServiceImpl::SecurityFromCWSecurityMode(
572 CWSecurityMode security) const {
573 switch (security) {
574 case kCWSecurityModeWPA_Enterprise:
575 case kCWSecurityModeWPA2_Enterprise:
576 return onc::wifi::kWPA_EAP;
577 case kCWSecurityModeWPA_PSK:
578 case kCWSecurityModeWPA2_PSK:
579 return onc::wifi::kWPA_PSK;
580 case kCWSecurityModeWEP:
581 return onc::wifi::kWEP_PSK;
582 case kCWSecurityModeOpen:
583 return onc::wifi::kNone;
584 // TODO(mef): Figure out correct mapping.
585 case kCWSecurityModeWPS:
586 case kCWSecurityModeDynamicWEP:
587 return onc::wifi::kWPA_EAP;
588 }
589 return onc::wifi::kWPA_EAP;
590 }
591
592 void WiFiServiceImpl::SortNetworks(NetworkList* networks) {
Robert Sesek 2014/01/07 16:19:05 This is called exactly once. Why does it need its
mef 2014/01/08 21:00:03 Done.
593 networks->sort(NetworkProperties::OrderByType);
594 }
595
596
Robert Sesek 2014/01/07 16:19:05 nit: double blank line
mef 2014/01/08 21:00:03 Done.
597 void WiFiServiceImpl::OnListenerNotification() {
598 std::string connected_network_guid = GUIDFromSSID([interface_ ssid]);
599 DVLOG(1) << " *** Got Notification: " << connected_network_guid;
600 if (connected_network_guid.empty()) {
601 // Find previously connected network and notify that it is disconnected.
tbarzic 2014/01/07 20:05:33 When a connected network changes from A to B, will
mef 2014/01/08 21:00:03 In my testing it appears to always get notificatio
tbarzic 2014/01/08 23:06:23 You don't seem too sure about this :) Can you add
mef 2014/01/10 17:01:52 Done.
602 for (WiFiService::NetworkList::iterator it = networks_.begin();
603 it != networks_.end();
604 ++it) {
605 if (it->connection_state == onc::connection_state::kConnected) {
606 it->connection_state = onc::connection_state::kNotConnected;
607 NotifyNetworkChanged(it->guid);
608 }
609 }
610 } else {
611 NotifyNetworkChanged(connected_network_guid);
612 }
613 }
614
615 void WiFiServiceImpl::NotifyNetworkListChanged(const NetworkList& networks) {
616 if (network_list_changed_observer_.is_null())
Robert Sesek 2014/01/07 16:19:05 Why listen for network change events if nothing is
mef 2014/01/08 21:00:03 Because caller could've done |RequestNetworkScan|
tbarzic 2014/01/08 23:06:23 I agree that there is no real need to observe netw
mef 2014/01/10 20:26:16 Done.
617 return;
618
619 NetworkGuidList current_networks;
620 for (NetworkList::const_iterator it = networks.begin();
621 it != networks.end();
622 ++it) {
623 current_networks.push_back(it->guid);
624 }
625
626 message_loop_proxy_->PostTask(
627 FROM_HERE,
628 base::Bind(network_list_changed_observer_, current_networks));
629 }
630
631 void WiFiServiceImpl::NotifyNetworkChanged(const std::string& network_guid) {
632 if (!enable_notify_network_changed_ || networks_changed_observer_.is_null())
Robert Sesek 2014/01/07 16:19:05 Same question.
mef 2014/01/08 21:00:03 Done. I've moved 'NSNotificationCenter addObserver
633 return;
634
635 DVLOG(1) << "NotifyNetworkChanged: " << network_guid;
636 NetworkGuidList changed_networks(1, network_guid);
637 message_loop_proxy_->PostTask(
638 FROM_HERE,
639 base::Bind(networks_changed_observer_, changed_networks));
640 }
641
Robert Sesek 2014/01/07 16:19:05 "// static"
mef 2014/01/08 21:00:03 Done.
642 WiFiService* WiFiService::Create() { return new WiFiServiceImpl(); }
643
644 } // namespace wifi
OLDNEW
« no previous file with comments | « components/wifi/wifi_service.cc ('k') | components/wifi/wifi_service_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698