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

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: Added NetworkChangeDetector that listens to NetworkChangeNotifier. 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 2014 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 #import <netinet/in.h>
8 #import <CoreWLAN/CoreWLAN.h>
9 #import <SystemConfiguration/SystemConfiguration.h>
10
11 #include "base/bind.h"
12 #include "base/mac/scoped_cftyperef.h"
13 #include "base/mac/scoped_nsobject.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/strings/sys_string_conversions.h"
16 #include "components/onc/onc_constants.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "net/base/network_change_notifier.h"
19
20 #if !defined(MAC_OS_X_VERSION_10_7) || \
21 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
22
23 // Local definitions of API added in Mac OS X 10.7
24
25 @interface CWInterface (LionAPI)
26 - (BOOL)associateToNetwork:(CWNetwork*)network
27 password:(NSString*)password
28 error:(NSError**)error;
29 - (NSSet*)scanForNetworksWithName:(NSString*)networkName
30 error:(NSError**)error;
31 @end
32
33 enum CWChannelBand {
34 kCWChannelBandUnknown = 0,
35 kCWChannelBand2GHz = 1,
36 kCWChannelBand5GHz = 2,
37 };
38
39 @interface CWChannel : NSObject
40 @property(readonly) CWChannelBand channelBand;
41 @end
42
43 @interface CWNetwork (LionAPI)
44 @property(readonly) CWChannel* wlanChannel;
45 @end
46
47 #endif // 10.7
48
49 namespace wifi {
50
51 const char kErrorAssociateToNetwork[] = "Error.AssociateToNetwork";
52 const char kErrorInvalidData[] = "Error.InvalidData";
53 const char kErrorNotConnected[] = "Error.NotConnected";
54 const char kErrorNotFound[] = "Error.NotFound";
55 const char kErrorNotImplemented[] = "Error.NotImplemented";
56 const char kErrorScanForNetworksWithName[] = "Error.ScanForNetworksWithName";
57
58 // Implementation of WiFiService for Mac OS X.
59 class WiFiServiceMac : public WiFiService {
60
61 // Detect network changes by subscribing NetworkChangeNotifier notifications
62 // on IO thread. Posts |on_network_changed_| to worker pool using
63 // |task_runner_|.
64 class NetworkChangeDetector
65 : public base::RefCountedThreadSafe<
66 NetworkChangeDetector, content::BrowserThread::DeleteOnIOThread>,
67 net::NetworkChangeNotifier::NetworkChangeObserver {
68 public:
69 NetworkChangeDetector(const base::Closure& on_network_changed,
70 scoped_refptr<base::SequencedTaskRunner> task_runner)
71 : on_network_changed_(on_network_changed), task_runner_(task_runner) {
72 }
73
74 void StartOnIOThread() {
75 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
76 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
77 }
78
79 void StopOnIOThread() {
80 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
81 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
tbarzic 2014/01/27 20:17:24 is it ok if this doesn't get called (which is poss
mef 2014/01/27 23:08:27 Good question, it seems that it may leak. Any sugg
82 }
83
84 private:
85 friend struct content::BrowserThread::DeleteOnThread<
tbarzic 2014/01/27 20:17:24 As long as you always call StopOnIOThread, you sho
mef 2014/01/27 23:08:27 Without this I get compiler errors about inaccessi
86 content::BrowserThread::IO>;
87 friend class base::DeleteHelper<NetworkChangeDetector>;
88
89 virtual ~NetworkChangeDetector() {
90 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
91 }
92
93 // Handle NetworkChanged notification and post it to worker pool.
94 virtual void OnNetworkChanged(
95 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE {
96 if (!on_network_changed_.is_null()) {
97 task_runner_->PostTask(FROM_HERE, on_network_changed_);
98 }
99 }
100
101 // Task to post on worker pool when notification is received.
102 const base::Closure on_network_changed_;
103 // Task runner for worker tasks.
104 scoped_refptr<base::SequencedTaskRunner> task_runner_;
105 };
106
107 public:
108 WiFiServiceMac();
109 virtual ~WiFiServiceMac();
110
111 // WiFiService interface implementation.
112 virtual void Initialize(
113 scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE;
114
115 virtual void UnInitialize() OVERRIDE;
116
117 virtual void GetProperties(const std::string& network_guid,
118 base::DictionaryValue* properties,
119 std::string* error) OVERRIDE;
120
121 virtual void GetManagedProperties(const std::string& network_guid,
122 base::DictionaryValue* managed_properties,
123 std::string* error) OVERRIDE;
124
125 virtual void GetState(const std::string& network_guid,
126 base::DictionaryValue* properties,
127 std::string* error) OVERRIDE;
128
129 virtual void SetProperties(const std::string& network_guid,
130 scoped_ptr<base::DictionaryValue> properties,
131 std::string* error) OVERRIDE;
132
133 virtual void CreateNetwork(bool shared,
134 scoped_ptr<base::DictionaryValue> properties,
135 std::string* network_guid,
136 std::string* error) OVERRIDE;
137
138 virtual void GetVisibleNetworks(const std::string& network_type,
139 base::ListValue* network_list) OVERRIDE;
140
141 virtual void RequestNetworkScan() OVERRIDE;
142
143 virtual void StartConnect(const std::string& network_guid,
144 std::string* error) OVERRIDE;
145
146 virtual void StartDisconnect(const std::string& network_guid,
147 std::string* error) OVERRIDE;
148
149 virtual void SetEventObservers(
150 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
151 const NetworkGuidListCallback& networks_changed_observer,
152 const NetworkGuidListCallback& network_list_changed_observer) OVERRIDE;
153
154 private:
155 // Checks |ns_error| and if is not |nil|, then stores |error_name|
156 // into |error|.
157 bool CheckError(NSError* ns_error,
158 const char* error_name,
159 std::string* error) const;
160
161 // Gets |ssid| from unique |network_guid|.
162 NSString* SSIDFromGUID(const std::string& network_guid) const {
163 return base::SysUTF8ToNSString(network_guid);
164 }
165
166 // Gets unique |network_guid| string based on |ssid|.
167 std::string GUIDFromSSID(NSString* ssid) const {
168 return base::SysNSStringToUTF8(ssid);
169 }
170
171 // Populates |properties| from |network|.
172 void NetworkPropertiesFromCWNetwork(const CWNetwork* network,
173 NetworkProperties* properties) const;
174
175 // Convert s|CWSecurityMode| into onc::wifi::k{WPA|WEP}* security constant.
176 std::string SecurityFromCWSecurityMode(CWSecurityMode security) const;
177
178 // Waits up to |kMaxAttempts| with |kAttemptDelayMs| delay for connection to
179 // network with |network_guid|. Notifies that |NetworkChanged| upon success.
180 void WaitForNetworkConnect(const std::string& network_guid, int attempt);
181
182 // Gets current |onc::connection_state| for given |network_guid|.
183 std::string GetNetworkConnectionState(const std::string& network_guid) const;
184
185 // Updates |networks_| with the list of visible wireless networks.
186 void UpdateNetworks();
187
188 // Find network by |network_guid| and return iterator to its entry in
189 // |networks_|.
190 NetworkList::iterator FindNetwork(const std::string& network_guid);
191
192 // Handles notification from |wlan_observer_|.
193 void OnWlanObserverNotification();
194
195 // Notifies |network_list_changed_observer_| that list of visible networks has
196 // changed to |networks|.
197 void NotifyNetworkListChanged(const NetworkList& networks);
198
199 // Notifies |networks_changed_observer_| that network |network_guid|
200 // connection state has changed.
201 void NotifyNetworkChanged(const std::string& network_guid);
202
203 // Default interface.
204 base::scoped_nsobject<CWInterface> interface_;
205 // WLAN Notifications observer. |this| doesn't own this reference.
206 id wlan_observer_;
207 // Detects Network Changes. Registered, notified and deleted on IO thread.
208 scoped_refptr<NetworkChangeDetector> network_change_detector_;
209
210 // Observer to get notified when network(s) have changed (e.g. connect).
211 NetworkGuidListCallback networks_changed_observer_;
212 // Observer to get notified when network list has changed (scan complete).
213 NetworkGuidListCallback network_list_changed_observer_;
214 // MessageLoopProxy to post events on UI thread.
215 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
216 // Task runner for worker tasks.
217 scoped_refptr<base::SequencedTaskRunner> task_runner_;
218 // Cache of network list collected by GetVisibleNetworks.
219 NetworkList networks_;
220 // Temporary storage of network properties indexed by |network_guid|.
221 base::DictionaryValue network_properties_;
222 // Use WeakPtrs for callbacks from |network_change_detector_|.
223 base::WeakPtrFactory<WiFiServiceMac> weak_factory_;
224 // Number of attempts to check that network has connected successfully.
225 static const int kConnectionCheckMaxAttempts = 200;
226 // Delay between attempts to check that network has connected successfully.
227 static const int kConnectionCheckAttemptDelayMs = 100;
228 };
229
230 WiFiServiceMac::WiFiServiceMac() : wlan_observer_(nil), weak_factory_(this) {
231 }
232
233 WiFiServiceMac::~WiFiServiceMac() {
234 }
235
236 void WiFiServiceMac::Initialize(
237 scoped_refptr<base::SequencedTaskRunner> task_runner) {
238 task_runner_.swap(task_runner);
239 interface_.reset([[CWInterface interface] retain]);
240 if (!interface_) {
241 DVLOG(1) << "Failed to initialize default interface.";
242 return;
243 }
244
245 if (![interface_
246 respondsToSelector:@selector(associateToNetwork:password:error:)]) {
247 DVLOG(1) << "CWInterface does not support associateToNetwork.";
248 interface_.reset();
249 return;
250 }
251
252 // Subscribe to NetworkChange notifications.
253 if (!network_change_detector_) {
254 network_change_detector_ = new NetworkChangeDetector(
255 base::Bind(&WiFiServiceMac::OnWlanObserverNotification,
256 weak_factory_.GetWeakPtr()),
257 task_runner_);
258 content::BrowserThread::PostTask(
259 content::BrowserThread::IO,
tbarzic 2014/01/27 20:17:24 if you wish, you could get rid of dependency on co
mef 2014/01/27 23:08:27 Hmm, I'm wondering whether I should subscribe to n
260 FROM_HERE,
261 base::Bind(&NetworkChangeDetector::StartOnIOThread,
262 network_change_detector_));
263 }
264 }
265
266 void WiFiServiceMac::UnInitialize() {
267 if (wlan_observer_)
268 [[NSNotificationCenter defaultCenter] removeObserver:wlan_observer_];
269 interface_.reset();
270 // Unsubscribe from NetworkChange notifications.
271 if (network_change_detector_) {
272 content::BrowserThread::PostTask(
273 content::BrowserThread::IO,
274 FROM_HERE,
275 base::Bind(&NetworkChangeDetector::StopOnIOThread,
276 network_change_detector_));
277 network_change_detector_ = NULL;
278 }
279 }
280
281 void WiFiServiceMac::GetProperties(const std::string& network_guid,
282 base::DictionaryValue* properties,
283 std::string* error) {
284 NetworkList::iterator it = FindNetwork(network_guid);
285 if (it == networks_.end()) {
286 DVLOG(1) << "Network not found:" << network_guid;
287 *error = kErrorNotFound;
288 return;
289 }
290
291 it->connection_state = GetNetworkConnectionState(network_guid);
292 scoped_ptr<base::DictionaryValue> network(it->ToValue(false));
293 properties->Swap(network.get());
294 DVLOG(1) << *properties;
295 }
296
297 void WiFiServiceMac::GetManagedProperties(
298 const std::string& network_guid,
299 base::DictionaryValue* managed_properties,
300 std::string* error) {
301 *error = kErrorNotImplemented;
302 }
303
304 void WiFiServiceMac::GetState(const std::string& network_guid,
305 base::DictionaryValue* properties,
306 std::string* error) {
307 *error = kErrorNotImplemented;
308 }
309
310 void WiFiServiceMac::SetProperties(
311 const std::string& network_guid,
312 scoped_ptr<base::DictionaryValue> properties,
313 std::string* error) {
314 network_properties_.SetWithoutPathExpansion(network_guid,
315 properties.release());
316 }
317
318 void WiFiServiceMac::CreateNetwork(
319 bool shared,
320 scoped_ptr<base::DictionaryValue> properties,
321 std::string* network_guid,
322 std::string* error) {
323 WiFiService::NetworkProperties network_properties;
324 if (!network_properties.UpdateFromValue(*properties)) {
325 *error = kErrorInvalidData;
326 return;
327 }
328
329 std::string guid = network_properties.ssid;
330 if (FindNetwork(guid) != networks_.end()) {
331 *error = kErrorInvalidData;
332 return;
333 }
334 network_properties_.SetWithoutPathExpansion(guid,
335 properties.release());
336 *network_guid = guid;
337 }
338
339 void WiFiServiceMac::GetVisibleNetworks(const std::string& network_type,
340 base::ListValue* network_list) {
341 if (!network_type.empty() &&
342 network_type != onc::network_type::kAllTypes &&
343 network_type != onc::network_type::kWiFi) {
344 return;
345 }
346
347 if (networks_.empty())
348 UpdateNetworks();
349
350 for (WiFiService::NetworkList::const_iterator it = networks_.begin();
351 it != networks_.end();
352 ++it) {
353 scoped_ptr<base::DictionaryValue> network(it->ToValue(true));
354 network_list->Append(network.release());
355 }
356 }
357
358 void WiFiServiceMac::RequestNetworkScan() {
359 UpdateNetworks();
360 }
361
362 void WiFiServiceMac::StartConnect(const std::string& network_guid,
363 std::string* error) {
364 NSError* ns_error = nil;
365
366 DVLOG(1) << "*** StartConnect: " << network_guid;
367 // Remember previously connected network.
368 std::string connected_network_guid = GUIDFromSSID([interface_ ssid]);
369 // Check whether desired network is already connected.
370 if (network_guid == connected_network_guid) {
371 NotifyNetworkChanged(connected_network_guid);
372 return;
373 }
374
375 NSSet* networks = [interface_
376 scanForNetworksWithName:SSIDFromGUID(network_guid)
377 error:&ns_error];
378
379 if (CheckError(ns_error, kErrorScanForNetworksWithName, error))
380 return;
381
382 CWNetwork* network = [networks anyObject];
383 if (network == nil) {
384 // System can't find the network, remove it from the |networks_| and notify
385 // observers.
386 NetworkList::iterator it = FindNetwork(connected_network_guid);
387 if (it != networks_.end()) {
388 networks_.erase(it);
389 // Notify observers that list has changed.
390 NotifyNetworkListChanged(networks_);
391 }
392
393 *error = kErrorNotFound;
394 return;
395 }
396
397 // Check whether WiFi Password is set in |network_properties_|.
398 base::DictionaryValue* properties;
399 base::DictionaryValue* wifi;
400 std::string passphrase;
401 NSString* ns_password = nil;
402 if (network_properties_.GetDictionaryWithoutPathExpansion(network_guid,
403 &properties) &&
404 properties->GetDictionary(onc::network_type::kWiFi, &wifi) &&
405 wifi->GetString(onc::wifi::kPassphrase, &passphrase)) {
406 ns_password = base::SysUTF8ToNSString(passphrase);
407 }
408
409 // Number of attempts to associate to network.
410 static const int kMaxAssociationAttempts = 3;
411 // Try to associate to network several times if timeout or PMK error occurs.
412 for (int i = 0; i < kMaxAssociationAttempts; ++i) {
413 // Nil out the PMK to prevent stale data from causing invalid PMK error
414 // (CoreWLANTypes -3924).
415 [interface_ setPairwiseMasterKey:nil error:&ns_error];
416 if (![interface_ associateToNetwork:network
417 password:ns_password
418 error:&ns_error]) {
419 NSInteger error_code = [ns_error code];
420 if (error_code != kCWTimeoutErr && error_code != kCWInvalidPMKErr) {
421 break;
422 }
423 }
424 }
425 CheckError(ns_error, kErrorAssociateToNetwork, error);
426 }
427
428 void WiFiServiceMac::StartDisconnect(const std::string& network_guid,
429 std::string* error) {
430 DVLOG(1) << "*** StartDisconnect: " << network_guid;
431
432 if (network_guid == GUIDFromSSID([interface_ ssid])) {
433 // Power-cycle the interface to disconnect from current network and connect
434 // to default network.
435 NSError* ns_error = nil;
436 [interface_ setPower:NO error:&ns_error];
437 CheckError(ns_error, kErrorAssociateToNetwork, error);
438 [interface_ setPower:YES error:&ns_error];
439 CheckError(ns_error, kErrorAssociateToNetwork, error);
440 } else {
441 *error = kErrorNotConnected;
442 }
443 }
444
445 void WiFiServiceMac::SetEventObservers(
446 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
447 const NetworkGuidListCallback& networks_changed_observer,
448 const NetworkGuidListCallback& network_list_changed_observer) {
449 message_loop_proxy_.swap(message_loop_proxy);
450 networks_changed_observer_ = networks_changed_observer;
451 network_list_changed_observer_ = network_list_changed_observer;
452
453 // Remove previous OS notifications observer.
454 if (wlan_observer_) {
455 [[NSNotificationCenter defaultCenter] removeObserver:wlan_observer_];
456 wlan_observer_ = nil;
457 }
458
459 // Subscribe to OS notifications.
460 if (!networks_changed_observer_.is_null()) {
461 void (^ns_observer) (NSNotification* notification) =
462 ^(NSNotification* notification) {
463 task_runner_->PostTask(
464 FROM_HERE,
465 base::Bind(&WiFiServiceMac::OnWlanObserverNotification,
466 base::Unretained(this)));
467 };
468
469 wlan_observer_ = [[NSNotificationCenter defaultCenter]
470 addObserverForName:CWSSIDDidChangeNotification
471 object:nil
472 queue:nil
473 usingBlock:ns_observer];
474 }
475
tbarzic 2014/01/27 20:17:24 nuke the line
mef 2014/01/27 23:08:27 Done.
476 }
477
478 void WiFiServiceMac::WaitForNetworkConnect(const std::string& network_guid,
479 int attempt) {
480 return;
481 // If network didn't get connected in |kMaxAttempts|, then stop waiting.
482 if (attempt > kConnectionCheckMaxAttempts) {
483 DLOG(ERROR) << kConnectionCheckMaxAttempts
484 << " attempts exceeded waiting for connect to "
485 << network_guid;
486 return;
487 }
488
489 if (GetNetworkConnectionState(network_guid) ==
490 onc::connection_state::kConnected) {
491 DVLOG(1) << "WiFi Connected, Reachable: " << network_guid;
492 NotifyNetworkChanged(network_guid);
493 } else {
494 // Continue waiting for network connection state change.
495 task_runner_->PostDelayedTask(
496 FROM_HERE,
497 base::Bind(&WiFiServiceMac::WaitForNetworkConnect,
498 base::Unretained(this),
499 network_guid,
500 ++attempt),
501 base::TimeDelta::FromMilliseconds(kConnectionCheckAttemptDelayMs));
502 }
503 }
504
505 std::string WiFiServiceMac::GetNetworkConnectionState(
506 const std::string& network_guid) const {
507 if (network_guid != GUIDFromSSID([interface_ ssid]))
508 return onc::connection_state::kNotConnected;
509
510 // Check whether WiFi network is reachable.
511 struct sockaddr_in local_wifi_address;
512 bzero(&local_wifi_address, sizeof(local_wifi_address));
513 local_wifi_address.sin_len = sizeof(local_wifi_address);
514 local_wifi_address.sin_family = AF_INET;
515 local_wifi_address.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
516 base::ScopedCFTypeRef<SCNetworkReachabilityRef> reachability(
517 SCNetworkReachabilityCreateWithAddress(
518 kCFAllocatorDefault,
519 reinterpret_cast<const struct sockaddr*>(&local_wifi_address)));
520 SCNetworkReachabilityFlags flags = 0u;
521 if (SCNetworkReachabilityGetFlags(reachability, &flags) &&
522 (flags & kSCNetworkReachabilityFlagsReachable) &&
523 (flags & kSCNetworkReachabilityFlagsIsDirect)) {
524 // Network is reachable, report is as |kConnected|.
525 return onc::connection_state::kConnected;
526 }
527 // Network is not reachable yet, so it must be |kConnecting|.
528 return onc::connection_state::kConnecting;
529 }
530
531 void WiFiServiceMac::UpdateNetworks() {
532 NSError* ns_error = nil;
533 NSSet* cw_networks = [interface_ scanForNetworksWithName:nil
534 error:&ns_error];
535
536 if (ns_error != nil)
537 return;
538
539 std::map<std::string, NetworkProperties*> network_properties_map;
540 networks_.clear();
541
542 // There is one |cw_network| per BSS in |cw_networks|, so go through the set
543 // and combine them, paying attention to supported frequencies.
544 for (CWNetwork* cw_network in cw_networks) {
545 NetworkProperties network_properties;
546 NetworkPropertiesFromCWNetwork(cw_network, &network_properties);
547
548 if (network_properties_map.find(network_properties.guid) ==
549 network_properties_map.end()) {
550 networks_.push_back(network_properties);
551 network_properties_map[network_properties.guid] = &networks_.back();
552 } else {
553 NetworkProperties* existing = network_properties_map.at(
554 network_properties.guid);
555 existing->frequency_set.insert(*network_properties.frequency_set.begin());
556 }
557 }
558 // Sort networks, so connected/connecting is up front.
559 networks_.sort(NetworkProperties::OrderByType);
560 // Notify observers that list has changed.
561 NotifyNetworkListChanged(networks_);
562 }
563
564 bool WiFiServiceMac::CheckError(NSError* ns_error,
565 const char* error_name,
566 std::string* error) const {
567 if (ns_error != nil) {
568 DLOG(ERROR) << "*** Error:" << error_name << ":" << [ns_error code];
569 *error = error_name;
570 return true;
571 }
572 return false;
573 }
574
575 void WiFiServiceMac::NetworkPropertiesFromCWNetwork(
576 const CWNetwork* network,
577 NetworkProperties* properties) const {
578 std::string network_guid = GUIDFromSSID([network ssid]);
579
580 properties->connection_state = GetNetworkConnectionState(network_guid);
581 properties->ssid = base::SysNSStringToUTF8([network ssid]);
582 properties->name = properties->ssid;
583 properties->guid = network_guid;
584 properties->type = onc::network_type::kWiFi;
585
586 properties->bssid = base::SysNSStringToUTF8([network bssid]);
587 if ([[network wlanChannel] channelBand] == kCWChannelBand2GHz)
588 properties->frequency = kFrequency2400;
589 else
590 properties->frequency = kFrequency5000;
591 properties->frequency_set.insert(properties->frequency);
592 properties->security = SecurityFromCWSecurityMode(
593 static_cast<CWSecurityMode>([[network securityMode] intValue]));
594
595 properties->signal_strength = [[network rssi] intValue];
596 }
597
598 std::string WiFiServiceMac::SecurityFromCWSecurityMode(
599 CWSecurityMode security) const {
600 switch (security) {
601 case kCWSecurityModeWPA_Enterprise:
602 case kCWSecurityModeWPA2_Enterprise:
603 return onc::wifi::kWPA_EAP;
604 case kCWSecurityModeWPA_PSK:
605 case kCWSecurityModeWPA2_PSK:
606 return onc::wifi::kWPA_PSK;
607 case kCWSecurityModeWEP:
608 return onc::wifi::kWEP_PSK;
609 case kCWSecurityModeOpen:
610 return onc::wifi::kNone;
611 // TODO(mef): Figure out correct mapping.
612 case kCWSecurityModeWPS:
613 case kCWSecurityModeDynamicWEP:
614 return onc::wifi::kWPA_EAP;
615 }
616 return onc::wifi::kWPA_EAP;
617 }
618
619 WiFiService::NetworkList::iterator WiFiServiceMac::FindNetwork(
620 const std::string& network_guid) {
621 for (NetworkList::iterator it = networks_.begin();
622 it != networks_.end();
623 ++it) {
624 if (it->guid == network_guid)
625 return it;
626 }
627 return networks_.end();
628 }
629
630 void WiFiServiceMac::OnWlanObserverNotification() {
631 std::string connected_network_guid = GUIDFromSSID([interface_ ssid]);
632 DVLOG(1) << " *** Got Notification: " << connected_network_guid;
633 // There are 2 notifications for every network switch:
634 // 1. When old WLAN is disconnected, |connected_network_guid| is empty.
635 // 2. When new WLAN is connected, |connected_network_guid| is new network
636 // guid.
637 if (connected_network_guid.empty()) {
638 // Find previously connected network and notify that it is disconnected.
639 for (WiFiService::NetworkList::iterator it = networks_.begin();
640 it != networks_.end();
641 ++it) {
642 if (it->connection_state == onc::connection_state::kConnected) {
643 it->connection_state = onc::connection_state::kNotConnected;
644 NotifyNetworkChanged(it->guid);
645 }
646 }
647 } else {
648 // Update connection_state of newly connected network.
649 NetworkList::iterator it = FindNetwork(connected_network_guid);
650 if (it != networks_.end()) {
651 it->connection_state = GetNetworkConnectionState(connected_network_guid);
652 } else {
653 // Can't find |connected_network_guid| in |networks_|, try to update it.
654 UpdateNetworks();
655 }
656 // Notify that network is connecting.
657 NotifyNetworkChanged(connected_network_guid);
658 // Start waiting for network connection to complete.
659 // Don't wait as network change notification should be sent by detector.
660 //if (!networks_changed_observer_.is_null())
661 // WaitForNetworkConnect(connected_network_guid, 0);
662 }
663 }
664
665 void WiFiServiceMac::NotifyNetworkListChanged(const NetworkList& networks) {
666 if (network_list_changed_observer_.is_null())
667 return;
668
669 NetworkGuidList current_networks;
670 for (NetworkList::const_iterator it = networks.begin();
671 it != networks.end();
672 ++it) {
673 current_networks.push_back(it->guid);
674 }
675
676 message_loop_proxy_->PostTask(
677 FROM_HERE,
678 base::Bind(network_list_changed_observer_, current_networks));
679 }
680
681 void WiFiServiceMac::NotifyNetworkChanged(const std::string& network_guid) {
682 if (networks_changed_observer_.is_null())
683 return;
684
685 DVLOG(1) << "NotifyNetworkChanged: " << network_guid;
686 NetworkGuidList changed_networks(1, network_guid);
687 message_loop_proxy_->PostTask(
688 FROM_HERE,
689 base::Bind(networks_changed_observer_, changed_networks));
690 }
691
692 // static
693 WiFiService* WiFiService::Create() { return new WiFiServiceMac(); }
694
695 } // 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