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

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: Better comments. 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
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>
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 =
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
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,
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.
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]
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 {
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,
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 {
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
178 static void SortNetworks(NetworkList* networks);
179
180 // Handle notification from |WLANListener|;
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;
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
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"]);
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];
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_);
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";
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__;
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);
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))
364 return;
365
366 CWNetwork* network = [networks anyObject];
367 if (network != nil) {
stevenjb 2013/12/27 19:53:44 if (network == nil) { *error = "Error.NotFound";
mef 2013/12/27 21:08:12 Done.
368 // Remember previously connected network.
369 std::string connected_network_guid = GUIDFromSSID([interface_ ssid]);
370 // Check, whether desired network is already connected.
371 if (network_guid == connected_network_guid) {
372 NotifyNetworkChanged(connected_network_guid);
373 return;
374 }
375 // Check whether WiFi Password is set in |network_properties_|
376 base::DictionaryValue* properties;
377 base::DictionaryValue* wifi;
378 std::string passphrase;
379 NSString* nsPassword = nil;
380 if (network_properties_.GetDictionaryWithoutPathExpansion(network_guid,
381 &properties) &&
382 properties->GetDictionary(onc::network_type::kWiFi, &wifi) &&
383 wifi->GetString(onc::wifi::kPassphrase, &passphrase)) {
384 nsPassword = [NSString stringWithUTF8String:passphrase.c_str()];
385 }
386
387 // Disable automatic network change notifications as they get fired
388 // when network is just connected, but not yet accessible (doesn't
389 // have valid IP address).
390 enable_notify_network_changed_ = false;
391
392 // Try to associate to network at least 3 times.
393 for (int i = 0; i < 3; ++i) {
stevenjb 2013/12/27 19:53:44 Avoid magic numbers; make 3 a constant and comment
mef 2013/12/27 21:08:12 I've 'borrowed' this from ChromeCast setup app (As
394 // Clear PMK for the interface.
395 [interface_ setPairwiseMasterKey:nil error:&nsError];
396 if ([interface_ associateToNetwork:network
397 password:nsPassword
398 error:&nsError]) {
399 // Notify that previously connected network has changed.
400 NotifyNetworkChanged(connected_network_guid);
401
402 // Start waiting for network connection state change.
403 if (!networks_changed_observer_.is_null()) {
404 WaitForNetworkConnect(network_guid, 0);
405 return;
406 }
407 } else {
408 long error_code = [nsError code];
409 if (error_code != kCWTimeoutErr && error_code != kCWInvalidPMKErr) {
410 break;
411 }
412 }
413 }
414 enable_notify_network_changed_ = true;
415 CheckError(nsError, "Error.associateToNetwork", error);
416 } else {
417 *error = "Error.NotFound";
418 }
419 }
420
421 void WiFiServiceImpl::StartDisconnect(const std::string& network_guid,
422 std::string* error) {
423 base::mac::ScopedNSAutoreleasePool auto_pool;
424 DVLOG(1) << "*** StartDisconnect: " << network_guid;
425
426 if (network_guid == GUIDFromSSID([interface_ ssid])) {
427 [interface_ disassociate];
428 //[interface_ setPower:NO error:nil];
429 //[interface_ setPower:YES error:nil];
stevenjb 2013/12/27 19:53:44 Remove (or comment better).
mef 2013/12/27 21:08:12 Done.
430 NotifyNetworkChanged(network_guid);
431 } else {
432 *error = "not-connected";
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;
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 =
466 SCNetworkReachabilityCreateWithAddress(
467 kCFAllocatorDefault,
468 (const struct sockaddr*)&localWiFiAddress);
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;
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_guids;
stevenjb 2013/12/27 19:53:44 Avoid using a & in a map, it's hard to read; use a
mef 2013/12/27 21:08:12 Done.
511
512 CWNetwork* network;
513 for(network in networks) {
514 NetworkProperties network_properties;
515 NetworkPropertiesFromCWNetwork(network, &network_properties);
516
517 if (network_guids.find(network_properties.guid) == network_guids.end()) {
518 network_list->push_back(network_properties);
519 network_guids.insert(
520 std::pair<std::string, NetworkProperties&>(
521 network_properties.guid, network_list->back()));
stevenjb 2013/12/27 19:53:44 network_guids[network_properties.guid] = &network_
mef 2013/12/27 21:08:12 Done.
522 } else {
523 NetworkProperties& existing = network_guids.at(network_properties.guid);
524 existing.frequency_set.insert(*network_properties.frequency_set.begin());
525 }
526 }
527 DVLOG(1) << ">>> GetVisibleNetworkList: " << network_guid;
528
529 return nil;
530 }
531
532 bool WiFiServiceImpl::CheckError(NSError* nsError,
533 const char* error_name,
534 std::string* error) const {
535 if (nsError != nil) {
536 DLOG(ERROR) << "*** Error:" << error_name << ":" << [nsError code];
537 *error = error_name;
538 return true;
539 }
540 return false;
541 }
542
543 void WiFiServiceImpl::NetworkPropertiesFromCWNetwork(
544 const CWNetwork* network,
545 NetworkProperties* properties) const {
546
547 if (NSOrderedSame == [[network ssid] compare:[interface_ ssid]])
548 properties->connection_state = onc::connection_state::kConnected;
549 else
550 properties->connection_state = onc::connection_state::kNotConnected;
551
552 properties->ssid = [[network ssid] UTF8String];
553 properties->name = properties->ssid;
554 properties->guid = GUIDFromSSID([network ssid]);
555 properties->type = onc::network_type::kWiFi;
556
557 properties->bssid = [[network bssid] UTF8String];
558 if ([[network wlanChannel] channelBand] == kCWChannelBand2GHz)
559 properties->frequency = kFrequency2400;
560 else
561 properties->frequency = kFrequency5000;
562 properties->frequency_set.insert(properties->frequency);
563 properties->security = SecurityFromCWSecurityMode(
564 static_cast<CWSecurityMode>([[network securityMode] intValue]));
565
566 properties->signal_strength = [[network rssi] intValue];
567 }
568
569 std::string WiFiServiceImpl::SecurityFromCWSecurityMode(
570 CWSecurityMode security) const {
571 switch (security) {
572 case kCWSecurityModeWPA_Enterprise:
573 case kCWSecurityModeWPA2_Enterprise:
574 return onc::wifi::kWPA_EAP;
575 case kCWSecurityModeWPA_PSK:
576 case kCWSecurityModeWPA2_PSK:
577 return onc::wifi::kWPA_PSK;
578 case kCWSecurityModeWEP:
579 return onc::wifi::kWEP_PSK;
580 case kCWSecurityModeOpen:
581 return onc::wifi::kNone;
582 // TODO(mef): Figure out correct mapping.
583 case kCWSecurityModeWPS:
584 case kCWSecurityModeDynamicWEP:
585 default:
stevenjb 2013/12/27 19:53:44 nit: Omit the default so that the compiler will ca
mef 2013/12/27 21:08:12 Done.
586 return onc::wifi::kWPA_EAP;
587 }
588 return onc::wifi::kWPA_EAP;
589 }
590
591 void WiFiServiceImpl::SortNetworks(NetworkList* networks) {
592 networks->sort(NetworkProperties::OrderByType);
593 }
594
595
596 void WiFiServiceImpl::OnListenerNotification() {
597 std::string connected_network_guid = GUIDFromSSID([interface_ ssid]);
598 DVLOG(1) << " *** Got Notification: " << connected_network_guid;
599 if (connected_network_guid.empty()) {
600 // Find previously connected network and notify that it is disconnected.
601 for (WiFiService::NetworkList::iterator it = networks_.begin();
602 it != networks_.end();
603 ++it) {
604 if (it->connection_state == onc::connection_state::kConnected) {
605 it->connection_state = onc::connection_state::kNotConnected;
606 NotifyNetworkChanged(it->guid);
607 }
608 }
609 } else {
610 NotifyNetworkChanged(connected_network_guid);
611 }
612 }
613
614 void WiFiServiceImpl::NotifyNetworkListChanged(const NetworkList& networks) {
615 if (network_list_changed_observer_.is_null())
616 return;
617
618 NetworkGuidList current_networks;
619 for (NetworkList::const_iterator it = networks.begin();
620 it != networks.end();
621 ++it) {
622 current_networks.push_back(it->guid);
623 }
624
625 message_loop_proxy_->PostTask(
626 FROM_HERE,
627 base::Bind(network_list_changed_observer_, current_networks));
628 }
629
630 void WiFiServiceImpl::NotifyNetworkChanged(const std::string& network_guid) {
631 if (!enable_notify_network_changed_ || networks_changed_observer_.is_null())
632 return;
633
634 DVLOG(1) << "NotifyNetworkChanged: " << network_guid;
635 NetworkGuidList changed_networks(1, network_guid);
636 message_loop_proxy_->PostTask(
637 FROM_HERE,
638 base::Bind(networks_changed_observer_, changed_networks));
639 }
640
641 WiFiService* WiFiService::Create() { return new WiFiServiceImpl(); }
642
643 } // namespace wifi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698