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

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 codereview comments. Created 6 years, 10 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 // Detect network changes by subscribing NetworkChangeNotifier notifications
61 // on IO thread. Posts |on_network_changed_| to worker pool using
62 // |task_runner_|.
63 class NetworkChangeDetector
64 : public base::RefCountedThreadSafe<
65 NetworkChangeDetector, content::BrowserThread::DeleteOnIOThread>,
66 net::NetworkChangeNotifier::NetworkChangeObserver {
67 public:
68 NetworkChangeDetector(const base::Closure& on_network_changed,
69 scoped_refptr<base::SequencedTaskRunner> task_runner)
70 : on_network_changed_(on_network_changed), task_runner_(task_runner) {
71 }
72
73 void StartOnIOThread() {
74 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
75 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
tbarzic 2014/01/27 20:17:24 maybe trigger OnNetworkChange (to initialize conne
mef 2014/01/27 23:08:27 Done.
76 }
77
78 void StopOnIOThread() {
79 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
80 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
81 }
82
83 private:
84 friend struct content::BrowserThread::DeleteOnThread<
85 content::BrowserThread::IO>;
86 friend class base::DeleteHelper<NetworkChangeDetector>;
87
88 virtual ~NetworkChangeDetector() {
89 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
90 }
91
92 // Handle NetworkChanged notification and post it to worker pool.
93 virtual void OnNetworkChanged(
94 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE {
95 DVLOG(1) << "Received OnNetworkChanged Notification";
96 if (!on_network_changed_.is_null()) {
tbarzic 2014/01/27 20:17:24 I'd consider making this CHECK If you keep it like
mef 2014/01/27 23:08:27 Done.
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 // Converts |CWSecurityMode| into onc::wifi::k{WPA|WEP}* security constant.
176 std::string SecurityFromCWSecurityMode(CWSecurityMode security) const;
177
178 // Gets current |onc::connection_state| for given |network_guid|.
179 std::string GetNetworkConnectionState(const std::string& network_guid) const;
180
181 // Updates |networks_| with the list of visible wireless networks.
182 void UpdateNetworks();
183
184 // Find network by |network_guid| and return iterator to its entry in
185 // |networks_|.
186 NetworkList::iterator FindNetwork(const std::string& network_guid);
187
188 // Handles notification from |wlan_observer_|.
189 void OnWlanObserverNotification();
190
191 // Notifies |network_list_changed_observer_| that list of visible networks has
192 // changed to |networks|.
193 void NotifyNetworkListChanged(const NetworkList& networks);
194
195 // Notifies |networks_changed_observer_| that network |network_guid|
196 // connection state has changed.
197 void NotifyNetworkChanged(const std::string& network_guid);
198
199 // Default interface.
200 base::scoped_nsobject<CWInterface> interface_;
201 // WLAN Notifications observer. |this| doesn't own this reference.
202 id wlan_observer_;
203 // Detects Network Changes. Registered, notified and deleted on IO thread.
204 scoped_refptr<NetworkChangeDetector> network_change_detector_;
205
206 // Observer to get notified when network(s) have changed (e.g. connect).
207 NetworkGuidListCallback networks_changed_observer_;
208 // Observer to get notified when network list has changed (scan complete).
209 NetworkGuidListCallback network_list_changed_observer_;
210 // MessageLoopProxy to post events on UI thread.
211 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
212 // Task runner for worker tasks.
213 scoped_refptr<base::SequencedTaskRunner> task_runner_;
214 // Cache of network list collected by GetVisibleNetworks.
215 NetworkList networks_;
216 // Guid of last known connected network.
217 std::string connected_network_guid_;
218 // Temporary storage of network properties indexed by |network_guid|.
219 base::DictionaryValue network_properties_;
220 // Use WeakPtrs for callbacks from |network_change_detector_|.
221 base::WeakPtrFactory<WiFiServiceMac> weak_factory_;
222 };
223
224 WiFiServiceMac::WiFiServiceMac() : wlan_observer_(nil), weak_factory_(this) {
225 }
226
227 WiFiServiceMac::~WiFiServiceMac() {
228 }
229
230 void WiFiServiceMac::Initialize(
231 scoped_refptr<base::SequencedTaskRunner> task_runner) {
232 task_runner_.swap(task_runner);
233 interface_.reset([[CWInterface interface] retain]);
234 if (!interface_) {
235 DVLOG(1) << "Failed to initialize default interface.";
236 return;
237 }
238
239 if (![interface_
240 respondsToSelector:@selector(associateToNetwork:password:error:)]) {
241 DVLOG(1) << "CWInterface does not support associateToNetwork.";
242 interface_.reset();
243 return;
244 }
245
246 // Subscribe to NetworkChange notifications.
247 if (!network_change_detector_) {
248 network_change_detector_ = new NetworkChangeDetector(
249 base::Bind(&WiFiServiceMac::OnWlanObserverNotification,
250 weak_factory_.GetWeakPtr()),
251 task_runner_);
252 content::BrowserThread::PostTask(
253 content::BrowserThread::IO,
254 FROM_HERE,
255 base::Bind(&NetworkChangeDetector::StartOnIOThread,
256 network_change_detector_));
257 }
258 }
259
260 void WiFiServiceMac::UnInitialize() {
261 if (wlan_observer_)
262 [[NSNotificationCenter defaultCenter] removeObserver:wlan_observer_];
263 interface_.reset();
264 // Unsubscribe from NetworkChange notifications.
265 if (network_change_detector_) {
266 content::BrowserThread::PostTask(
267 content::BrowserThread::IO,
268 FROM_HERE,
269 base::Bind(&NetworkChangeDetector::StopOnIOThread,
270 network_change_detector_));
271 network_change_detector_ = NULL;
272 }
273 }
274
275 void WiFiServiceMac::GetProperties(const std::string& network_guid,
276 base::DictionaryValue* properties,
277 std::string* error) {
278 NetworkList::iterator it = FindNetwork(network_guid);
279 if (it == networks_.end()) {
280 DVLOG(1) << "Network not found:" << network_guid;
281 *error = kErrorNotFound;
282 return;
283 }
284
285 it->connection_state = GetNetworkConnectionState(network_guid);
286 scoped_ptr<base::DictionaryValue> network(it->ToValue(false));
287 properties->Swap(network.get());
288 DVLOG(1) << *properties;
289 }
290
291 void WiFiServiceMac::GetManagedProperties(
292 const std::string& network_guid,
293 base::DictionaryValue* managed_properties,
294 std::string* error) {
295 *error = kErrorNotImplemented;
296 }
297
298 void WiFiServiceMac::GetState(const std::string& network_guid,
299 base::DictionaryValue* properties,
300 std::string* error) {
301 *error = kErrorNotImplemented;
302 }
303
304 void WiFiServiceMac::SetProperties(
305 const std::string& network_guid,
306 scoped_ptr<base::DictionaryValue> properties,
307 std::string* error) {
308 network_properties_.SetWithoutPathExpansion(network_guid,
309 properties.release());
310 }
311
312 void WiFiServiceMac::CreateNetwork(
313 bool shared,
314 scoped_ptr<base::DictionaryValue> properties,
315 std::string* network_guid,
316 std::string* error) {
317 WiFiService::NetworkProperties network_properties;
318 if (!network_properties.UpdateFromValue(*properties)) {
319 *error = kErrorInvalidData;
320 return;
321 }
322
323 std::string guid = network_properties.ssid;
324 if (FindNetwork(guid) != networks_.end()) {
325 *error = kErrorInvalidData;
326 return;
327 }
328 network_properties_.SetWithoutPathExpansion(guid,
329 properties.release());
330 *network_guid = guid;
331 }
332
333 void WiFiServiceMac::GetVisibleNetworks(const std::string& network_type,
334 base::ListValue* network_list) {
335 if (!network_type.empty() &&
336 network_type != onc::network_type::kAllTypes &&
337 network_type != onc::network_type::kWiFi) {
338 return;
339 }
340
341 if (networks_.empty())
342 UpdateNetworks();
343
344 for (WiFiService::NetworkList::const_iterator it = networks_.begin();
345 it != networks_.end();
346 ++it) {
347 scoped_ptr<base::DictionaryValue> network(it->ToValue(true));
348 network_list->Append(network.release());
349 }
350 }
351
352 void WiFiServiceMac::RequestNetworkScan() {
353 DVLOG(1) << "*** RequestNetworkScan";
354 UpdateNetworks();
355 }
356
357 void WiFiServiceMac::StartConnect(const std::string& network_guid,
358 std::string* error) {
359 NSError* ns_error = nil;
360
361 DVLOG(1) << "*** StartConnect: " << network_guid;
362 // Remember previously connected network.
363 std::string connected_network_guid = GUIDFromSSID([interface_ ssid]);
364 // Check whether desired network is already connected.
365 if (network_guid == connected_network_guid) {
366 NotifyNetworkChanged(connected_network_guid);
367 return;
368 }
369
370 NSSet* networks = [interface_
371 scanForNetworksWithName:SSIDFromGUID(network_guid)
372 error:&ns_error];
373
374 if (CheckError(ns_error, kErrorScanForNetworksWithName, error))
375 return;
376
377 CWNetwork* network = [networks anyObject];
378 if (network == nil) {
379 // System can't find the network, remove it from the |networks_| and notify
380 // observers.
381 NetworkList::iterator it = FindNetwork(connected_network_guid);
382 if (it != networks_.end()) {
383 networks_.erase(it);
384 // Notify observers that list has changed.
385 NotifyNetworkListChanged(networks_);
386 }
387
388 *error = kErrorNotFound;
389 return;
390 }
391
392 // Check whether WiFi Password is set in |network_properties_|.
393 base::DictionaryValue* properties;
394 base::DictionaryValue* wifi;
395 std::string passphrase;
396 NSString* ns_password = nil;
397 if (network_properties_.GetDictionaryWithoutPathExpansion(network_guid,
398 &properties) &&
399 properties->GetDictionary(onc::network_type::kWiFi, &wifi) &&
400 wifi->GetString(onc::wifi::kPassphrase, &passphrase)) {
401 ns_password = base::SysUTF8ToNSString(passphrase);
402 }
403
404 // Number of attempts to associate to network.
405 static const int kMaxAssociationAttempts = 3;
406 // Try to associate to network several times if timeout or PMK error occurs.
407 for (int i = 0; i < kMaxAssociationAttempts; ++i) {
408 // Nil out the PMK to prevent stale data from causing invalid PMK error
409 // (CoreWLANTypes -3924).
410 [interface_ setPairwiseMasterKey:nil error:&ns_error];
411 if (![interface_ associateToNetwork:network
412 password:ns_password
413 error:&ns_error]) {
414 NSInteger error_code = [ns_error code];
415 if (error_code != kCWTimeoutErr && error_code != kCWInvalidPMKErr) {
416 break;
417 }
418 }
419 }
420 CheckError(ns_error, kErrorAssociateToNetwork, error);
421 }
422
423 void WiFiServiceMac::StartDisconnect(const std::string& network_guid,
424 std::string* error) {
425 DVLOG(1) << "*** StartDisconnect: " << network_guid;
426
427 if (network_guid == GUIDFromSSID([interface_ ssid])) {
428 // Power-cycle the interface to disconnect from current network and connect
429 // to default network.
430 NSError* ns_error = nil;
431 [interface_ setPower:NO error:&ns_error];
432 CheckError(ns_error, kErrorAssociateToNetwork, error);
433 [interface_ setPower:YES error:&ns_error];
434 CheckError(ns_error, kErrorAssociateToNetwork, error);
435 } else {
436 *error = kErrorNotConnected;
437 }
438 }
439
440 void WiFiServiceMac::SetEventObservers(
441 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
442 const NetworkGuidListCallback& networks_changed_observer,
443 const NetworkGuidListCallback& network_list_changed_observer) {
444 message_loop_proxy_.swap(message_loop_proxy);
445 networks_changed_observer_ = networks_changed_observer;
446 network_list_changed_observer_ = network_list_changed_observer;
447
448 // Remove previous OS notifications observer.
449 if (wlan_observer_) {
450 [[NSNotificationCenter defaultCenter] removeObserver:wlan_observer_];
451 wlan_observer_ = nil;
452 }
453
454 // Subscribe to OS notifications.
455 if (!networks_changed_observer_.is_null()) {
456 void (^ns_observer) (NSNotification* notification) =
457 ^(NSNotification* notification) {
458 DVLOG(1) << "Received CWSSIDDidChangeNotification";
459 task_runner_->PostTask(
460 FROM_HERE,
461 base::Bind(&WiFiServiceMac::OnWlanObserverNotification,
462 base::Unretained(this)));
463 };
464
465 wlan_observer_ = [[NSNotificationCenter defaultCenter]
466 addObserverForName:CWSSIDDidChangeNotification
467 object:nil
468 queue:nil
469 usingBlock:ns_observer];
470 }
471 }
472
473 std::string WiFiServiceMac::GetNetworkConnectionState(
474 const std::string& network_guid) const {
475 if (network_guid != GUIDFromSSID([interface_ ssid]))
476 return onc::connection_state::kNotConnected;
477
478 // Check whether WiFi network is reachable.
479 struct sockaddr_in local_wifi_address;
480 bzero(&local_wifi_address, sizeof(local_wifi_address));
481 local_wifi_address.sin_len = sizeof(local_wifi_address);
482 local_wifi_address.sin_family = AF_INET;
483 local_wifi_address.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
484 base::ScopedCFTypeRef<SCNetworkReachabilityRef> reachability(
485 SCNetworkReachabilityCreateWithAddress(
486 kCFAllocatorDefault,
487 reinterpret_cast<const struct sockaddr*>(&local_wifi_address)));
488 SCNetworkReachabilityFlags flags = 0u;
489 if (SCNetworkReachabilityGetFlags(reachability, &flags) &&
490 (flags & kSCNetworkReachabilityFlagsReachable) &&
491 (flags & kSCNetworkReachabilityFlagsIsDirect)) {
492 // Network is reachable, report is as |kConnected|.
493 return onc::connection_state::kConnected;
494 }
495 // Network is not reachable yet, so it must be |kConnecting|.
496 return onc::connection_state::kConnecting;
497 }
498
499 void WiFiServiceMac::UpdateNetworks() {
500 NSError* ns_error = nil;
501 NSSet* cw_networks = [interface_ scanForNetworksWithName:nil
502 error:&ns_error];
503
504 if (ns_error != nil)
505 return;
506
507 std::map<std::string, NetworkProperties*> network_properties_map;
508 networks_.clear();
509
510 // There is one |cw_network| per BSS in |cw_networks|, so go through the set
511 // and combine them, paying attention to supported frequencies.
512 for (CWNetwork* cw_network in cw_networks) {
513 NetworkProperties network_properties;
514 NetworkPropertiesFromCWNetwork(cw_network, &network_properties);
515
516 if (network_properties_map.find(network_properties.guid) ==
517 network_properties_map.end()) {
518 networks_.push_back(network_properties);
519 network_properties_map[network_properties.guid] = &networks_.back();
520 } else {
521 NetworkProperties* existing = network_properties_map.at(
522 network_properties.guid);
523 existing->frequency_set.insert(*network_properties.frequency_set.begin());
524 }
525 }
526 // Sort networks, so connected/connecting is up front.
527 networks_.sort(NetworkProperties::OrderByType);
528 // Notify observers that list has changed.
529 NotifyNetworkListChanged(networks_);
530 }
531
532 bool WiFiServiceMac::CheckError(NSError* ns_error,
533 const char* error_name,
534 std::string* error) const {
535 if (ns_error != nil) {
536 DLOG(ERROR) << "*** Error:" << error_name << ":" << [ns_error code];
537 *error = error_name;
538 return true;
539 }
540 return false;
541 }
542
543 void WiFiServiceMac::NetworkPropertiesFromCWNetwork(
544 const CWNetwork* network,
545 NetworkProperties* properties) const {
546 std::string network_guid = GUIDFromSSID([network ssid]);
547
548 properties->connection_state = GetNetworkConnectionState(network_guid);
549 properties->ssid = base::SysNSStringToUTF8([network ssid]);
550 properties->name = properties->ssid;
551 properties->guid = network_guid;
552 properties->type = onc::network_type::kWiFi;
553
554 properties->bssid = base::SysNSStringToUTF8([network bssid]);
555 if ([[network wlanChannel] channelBand] == kCWChannelBand2GHz)
556 properties->frequency = kFrequency2400;
557 else
558 properties->frequency = kFrequency5000;
559 properties->frequency_set.insert(properties->frequency);
560 properties->security = SecurityFromCWSecurityMode(
561 static_cast<CWSecurityMode>([[network securityMode] intValue]));
562
563 properties->signal_strength = [[network rssi] intValue];
564 }
565
566 std::string WiFiServiceMac::SecurityFromCWSecurityMode(
567 CWSecurityMode security) const {
568 switch (security) {
569 case kCWSecurityModeWPA_Enterprise:
570 case kCWSecurityModeWPA2_Enterprise:
571 return onc::wifi::kWPA_EAP;
572 case kCWSecurityModeWPA_PSK:
573 case kCWSecurityModeWPA2_PSK:
574 return onc::wifi::kWPA_PSK;
575 case kCWSecurityModeWEP:
576 return onc::wifi::kWEP_PSK;
577 case kCWSecurityModeOpen:
578 return onc::wifi::kNone;
579 // TODO(mef): Figure out correct mapping.
580 case kCWSecurityModeWPS:
581 case kCWSecurityModeDynamicWEP:
582 return onc::wifi::kWPA_EAP;
583 }
584 return onc::wifi::kWPA_EAP;
585 }
586
587 WiFiService::NetworkList::iterator WiFiServiceMac::FindNetwork(
588 const std::string& network_guid) {
589 for (NetworkList::iterator it = networks_.begin();
590 it != networks_.end();
591 ++it) {
592 if (it->guid == network_guid)
593 return it;
594 }
595 return networks_.end();
596 }
597
598 void WiFiServiceMac::OnWlanObserverNotification() {
599 std::string connected_network_guid = GUIDFromSSID([interface_ ssid]);
600 DVLOG(1) << " *** Got Notification: " << connected_network_guid;
601 // There are 2 notifications for every network switch:
602 // 1. When old WLAN is disconnected, |connected_network_guid| is empty.
603 // 2. When new WLAN is connected, |connected_network_guid| is new network
604 // guid.
605 // Connected network has changed, mark previous one disconnected.
606 if (connected_network_guid != connected_network_guid_) {
607 // Update connection_state of newly connected network.
608 NetworkList::iterator it = FindNetwork(connected_network_guid_);
609 if (it != networks_.end()) {
610 it->connection_state = onc::connection_state::kNotConnected;
611 }
612 NotifyNetworkChanged(connected_network_guid_);
613 connected_network_guid_ = connected_network_guid;
614 }
615
616 if (!connected_network_guid.empty()) {
617 // Update connection_state of newly connected network.
618 NetworkList::iterator it = FindNetwork(connected_network_guid);
619 if (it != networks_.end()) {
620 it->connection_state = GetNetworkConnectionState(connected_network_guid);
621 } else {
622 // Can't find |connected_network_guid| in |networks_|, try to update it.
623 UpdateNetworks();
624 }
625 // Notify that network is connecting.
626 NotifyNetworkChanged(connected_network_guid);
627 // Further network change notification will be sent by detector.
628 }
629 }
630
631 void WiFiServiceMac::NotifyNetworkListChanged(const NetworkList& networks) {
632 if (network_list_changed_observer_.is_null())
633 return;
634
635 NetworkGuidList current_networks;
636 for (NetworkList::const_iterator it = networks.begin();
637 it != networks.end();
638 ++it) {
639 current_networks.push_back(it->guid);
640 }
641
642 message_loop_proxy_->PostTask(
643 FROM_HERE,
644 base::Bind(network_list_changed_observer_, current_networks));
645 }
646
647 void WiFiServiceMac::NotifyNetworkChanged(const std::string& network_guid) {
648 if (networks_changed_observer_.is_null())
649 return;
650
651 DVLOG(1) << "NotifyNetworkChanged: " << network_guid;
652 NetworkGuidList changed_networks(1, network_guid);
653 message_loop_proxy_->PostTask(
654 FROM_HERE,
655 base::Bind(networks_changed_observer_, changed_networks));
656 }
657
658 // static
659 WiFiService* WiFiService::Create() { return new WiFiServiceMac(); }
660
661 } // 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