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

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 comments. Created 6 years, 12 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>
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 // Number of attempts to associate to network.
217 static const int kMaxAssociationAttempts = 3;
stevenjb 2013/12/27 21:22:05 Since this is only used once, define this in the f
mef 2014/01/06 20:23:42 Done.
218 };
219
220 WiFiServiceImpl::WiFiServiceImpl() : enable_notify_network_changed_(true) {
221 }
222
223 WiFiServiceImpl::~WiFiServiceImpl() {
224 }
225
226 void WiFiServiceImpl::Initialize(
227 scoped_refptr<base::SequencedTaskRunner> task_runner) {
228 // As the WLAN api binding runs on its own thread, we need to provide our own
229 // auto release pool. It's simplest to do this as an automatic variable in
230 // each method that needs it, to ensure the scoping is correct and does not
231 // interfere with any other code using autorelease pools on the thread.
232 base::mac::ScopedNSAutoreleasePool auto_pool;
233
234 task_runner_.swap(task_runner);
235
236 bundle_.reset([[NSBundle alloc]
237 initWithPath:@"/System/Library/Frameworks/CoreWLAN.framework"]);
238 if (!bundle_) {
239 DVLOG(1) << "Failed to load the CoreWLAN framework bundle";
240 return;
241 }
242
243 Class cw_interface_class = [bundle_ classNamed:@"CWInterface"];
244 interface_.reset([[cw_interface_class interface] retain]);
245 if (!bundle_) {
246 DVLOG(1) << "Failed to initialize default interface";
247 return;
248 }
249
250 WLANNotificationObserver* observer = [[WLANNotificationObserver alloc] init];
251 [observer startListen:base::Bind(&WiFiServiceImpl::OnListenerNotification,
252 base::Unretained(this))
253 usingTaskRunner:task_runner_];
254 wlan_observer_.reset(observer);
255 }
256
257 void WiFiServiceImpl::UnInitialize() {
258 [wlan_observer_ stopListen];
259 }
260
261 void WiFiServiceImpl::GetProperties(const std::string& network_guid,
262 base::DictionaryValue* properties,
263 std::string* error) {
264 base::mac::ScopedNSAutoreleasePool auto_pool;
265
266 if (networks_.empty()) {
267 DVLOG(1) << "GetProperties";
268 NSError* nsError = GetVisibleNetworkList(std::string(), &networks_);
269 if (CheckError(nsError, "Error.GetProperties", error))
270 return;
271 }
272
273 for (WiFiService::NetworkList::iterator it = networks_.begin();
274 it != networks_.end();
275 ++it) {
276 if (it->guid == network_guid) {
277 bool is_connected = network_guid == GUIDFromSSID([interface_ ssid]);
278 it->connection_state =
279 is_connected ? onc::connection_state::kConnected :
280 onc::connection_state::kNotConnected;
281 scoped_ptr<base::DictionaryValue> network(it->ToValue(false));
282 properties->Swap(network.get());
283 DVLOG(1) << *properties;
284 return;
285 }
286 }
287
288 *error = "Error.NotFound";
289 }
290
291 void WiFiServiceImpl::GetManagedProperties(
292 const std::string& network_guid,
293 base::DictionaryValue* managed_properties,
294 std::string* error) {
295 *error = "Error.NotImplemented";
296 }
297
298 void WiFiServiceImpl::GetState(const std::string& network_guid,
299 base::DictionaryValue* properties,
300 std::string* error) {
301 *error = "Error.NotImplemented";
302 }
303
304 void WiFiServiceImpl::SetProperties(
305 const std::string& network_guid,
306 scoped_ptr<base::DictionaryValue> properties,
307 std::string* error) {
308 base::mac::ScopedNSAutoreleasePool auto_pool;
309 network_properties_.SetWithoutPathExpansion(network_guid,
310 properties.release());
311 }
312
313 void WiFiServiceImpl::CreateNetwork(
314 bool shared,
315 scoped_ptr<base::DictionaryValue> properties,
316 std::string* network_guid,
317 std::string* error) {
318 *error = "Error.NotImplemented";
319 }
320
321 void WiFiServiceImpl::GetVisibleNetworks(const std::string& network_type,
322 base::ListValue* network_list) {
323 if (!network_type.empty() &&
324 network_type != onc::network_type::kAllTypes &&
325 network_type != onc::network_type::kWiFi) {
326 return;
327 }
328
329 DVLOG(1) << __FUNCTION__;
330
331 base::mac::ScopedNSAutoreleasePool auto_pool;
332
333 GetVisibleNetworkList(std::string(), &networks_);
334
335 SortNetworks(&networks_);
336 for (WiFiService::NetworkList::const_iterator it = networks_.begin();
337 it != networks_.end();
338 ++it) {
339 scoped_ptr<base::DictionaryValue> network(it->ToValue(true));
340 network_list->Append(network.release());
341 }
342 }
343
344 void WiFiServiceImpl::RequestNetworkScan() {
345 base::mac::ScopedNSAutoreleasePool auto_pool;
346 NetworkList networks;
347 DVLOG(1) << __FUNCTION__;
348
349 NSError* nsError = GetVisibleNetworkList(std::string(), &networks);
350 if (nsError == nil && !networks.empty()) {
351 NotifyNetworkListChanged(networks);
352 }
353 }
354
355 void WiFiServiceImpl::StartConnect(const std::string& network_guid,
356 std::string* error) {
357 base::mac::ScopedNSAutoreleasePool auto_pool;
358 NSError* nsError = nil;
359
360 DVLOG(1) << "*** StartConnect: " << network_guid;
361 NSSet* networks = [interface_
362 scanForNetworksWithName:SSIDFromGUID(network_guid)
363 error:&nsError];
364
365 if (CheckError(nsError, "Error.scanForNetworksWithName", error))
366 return;
367
368 CWNetwork* network = [networks anyObject];
369 if (network == nil) {
370 *error = "Error.NotFound";
371 return;
372 }
373 // Remember previously connected network.
374 std::string connected_network_guid = GUIDFromSSID([interface_ ssid]);
arw 2014/01/06 23:08:54 Can this check and return logic be moved higher up
mef 2014/01/08 21:00:03 Done.
375 // Check, whether desired network is already connected.
376 if (network_guid == connected_network_guid) {
377 NotifyNetworkChanged(connected_network_guid);
378 return;
379 }
380 // Check whether WiFi Password is set in |network_properties_|
381 base::DictionaryValue* properties;
382 base::DictionaryValue* wifi;
383 std::string passphrase;
384 NSString* nsPassword = nil;
385 if (network_properties_.GetDictionaryWithoutPathExpansion(network_guid,
386 &properties) &&
387 properties->GetDictionary(onc::network_type::kWiFi, &wifi) &&
388 wifi->GetString(onc::wifi::kPassphrase, &passphrase)) {
389 nsPassword = [NSString stringWithUTF8String:passphrase.c_str()];
390 }
391
392 // Disable automatic network change notifications as they get fired
393 // when network is just connected, but not yet accessible (doesn't
394 // have valid IP address).
395 enable_notify_network_changed_ = false;
396
397 // Try to associate to network several times if timeout or PMK error occurs.
398 for (int i = 0; i < kMaxAssociationAttempts; ++i) {
399 // Nil out the PMK to prevent stale data from causing invalid PMK error
400 // (CoreWLANTypes -3924).
401 [interface_ setPairwiseMasterKey:nil error:&nsError];
402 if ([interface_ associateToNetwork:network
403 password:nsPassword
404 error:&nsError]) {
405 // Notify that previously connected network has changed.
406 NotifyNetworkChanged(connected_network_guid);
407
408 // Start waiting for network connection state change.
409 if (!networks_changed_observer_.is_null()) {
410 WaitForNetworkConnect(network_guid, 0);
411 return;
412 }
413 } else {
414 long error_code = [nsError code];
415 if (error_code != kCWTimeoutErr && error_code != kCWInvalidPMKErr) {
416 break;
417 }
418 }
419 }
420 enable_notify_network_changed_ = true;
421 CheckError(nsError, "Error.associateToNetwork", error);
422 }
423
424 void WiFiServiceImpl::StartDisconnect(const std::string& network_guid,
425 std::string* error) {
426 base::mac::ScopedNSAutoreleasePool auto_pool;
427 DVLOG(1) << "*** StartDisconnect: " << network_guid;
428
429 if (network_guid == GUIDFromSSID([interface_ ssid])) {
430 [interface_ disassociate];
431 NotifyNetworkChanged(network_guid);
432 } else {
433 *error = "not-connected";
434 }
435 }
436
437 void WiFiServiceImpl::SetEventObservers(
438 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
439 const NetworkGuidListCallback& networks_changed_observer,
440 const NetworkGuidListCallback& network_list_changed_observer) {
441 base::mac::ScopedNSAutoreleasePool auto_pool;
442 message_loop_proxy_.swap(message_loop_proxy);
443 networks_changed_observer_ = networks_changed_observer;
444 network_list_changed_observer_ = network_list_changed_observer;
445 }
446
447 void WiFiServiceImpl::WaitForNetworkConnect(const std::string& network_guid,
448 int attempt) {
449 // If network didn't get connected in |kMaxAttempts|, then restore automatic
450 // network change notifications and stop waiting.
451 if (attempt > kMaxAttempts) {
452 DLOG(ERROR) << kMaxAttempts << " attempts exceeded waiting for connect to "
453 << network_guid;
454 // Restore previously suppressed notifications.
455 enable_notify_network_changed_ = true;
456 return;
457 }
458
459 // Check whether WiFi network is reachable.
460 struct sockaddr_in localWiFiAddress;
461 bzero(&localWiFiAddress, sizeof(localWiFiAddress));
462 localWiFiAddress.sin_len = sizeof(localWiFiAddress);
463 localWiFiAddress.sin_family = AF_INET;
464 localWiFiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
465
466 SCNetworkReachabilityRef reachability =
467 SCNetworkReachabilityCreateWithAddress(
468 kCFAllocatorDefault,
469 (const struct sockaddr*)&localWiFiAddress);
470 SCNetworkReachabilityFlags flags = 0u;
471 if (SCNetworkReachabilityGetFlags(reachability, &flags) &&
472 (flags & kSCNetworkReachabilityFlagsReachable) &&
473 (flags & kSCNetworkReachabilityFlagsIsDirect)) {
474 DVLOG(1) << "WiFi Connected, Reachable: " << network_guid;
475 // Restore previously suppressed notifications.
476 enable_notify_network_changed_ = true;
477 NotifyNetworkChanged(network_guid);
478 } else {
479 DVLOG(1) << "Attempt:" << attempt << ", reachability:" << flags;
480 // Continue waiting for network connection state change.
481 task_runner_->PostDelayedTask(
482 FROM_HERE,
483 base::Bind(&WiFiServiceImpl::WaitForNetworkConnect,
484 base::Unretained(this),
485 network_guid,
486 ++attempt),
487 base::TimeDelta::FromMilliseconds(kAttemptDelayMs));
488 }
489
490 if (reachability)
491 CFRelease(reachability);
492 }
493
494
495 NSError* WiFiServiceImpl::GetVisibleNetworkList(const std::string& network_guid,
496 NetworkList* network_list) {
497
498 NSError* nsError = nil;
499 NSString* networkName = nil;
500
501 DVLOG(1) << "<<< GetVisibleNetworkList: " << network_guid;
502
503 if (!network_guid.empty())
504 networkName = SSIDFromGUID(network_guid);
505
506 NSSet* networks = [interface_ scanForNetworksWithName:networkName
507 error:&nsError];
508 if (nsError != nil)
509 return nsError;
510
511 std::map<std::string, NetworkProperties*> network_properties_map;
512
513 CWNetwork* network;
514 // There is one |network| per BSS in |networks|, so go through the set and
515 // combine them, paying attention to supported frequencies.
516 for(network in networks) {
517 NetworkProperties network_properties;
518 NetworkPropertiesFromCWNetwork(network, &network_properties);
519
520 if (network_properties_map.find(network_properties.guid) ==
521 network_properties_map.end()) {
522 network_list->push_back(network_properties);
523 network_properties_map[network_properties.guid] = &network_list->back();
524 } else {
525 NetworkProperties* existing = network_properties_map.at(
526 network_properties.guid);
527 existing->frequency_set.insert(*network_properties.frequency_set.begin());
528 }
529 }
530 DVLOG(1) << ">>> GetVisibleNetworkList: " << network_guid;
531
532 return nil;
533 }
534
535 bool WiFiServiceImpl::CheckError(NSError* nsError,
536 const char* error_name,
537 std::string* error) const {
538 if (nsError != nil) {
539 DLOG(ERROR) << "*** Error:" << error_name << ":" << [nsError code];
540 *error = error_name;
541 return true;
542 }
543 return false;
544 }
545
546 void WiFiServiceImpl::NetworkPropertiesFromCWNetwork(
547 const CWNetwork* network,
548 NetworkProperties* properties) const {
549
550 if (NSOrderedSame == [[network ssid] compare:[interface_ ssid]])
551 properties->connection_state = onc::connection_state::kConnected;
552 else
553 properties->connection_state = onc::connection_state::kNotConnected;
554
555 properties->ssid = [[network ssid] UTF8String];
556 properties->name = properties->ssid;
557 properties->guid = GUIDFromSSID([network ssid]);
558 properties->type = onc::network_type::kWiFi;
559
560 properties->bssid = [[network bssid] UTF8String];
561 if ([[network wlanChannel] channelBand] == kCWChannelBand2GHz)
562 properties->frequency = kFrequency2400;
563 else
564 properties->frequency = kFrequency5000;
565 properties->frequency_set.insert(properties->frequency);
566 properties->security = SecurityFromCWSecurityMode(
567 static_cast<CWSecurityMode>([[network securityMode] intValue]));
568
569 properties->signal_strength = [[network rssi] intValue];
570 }
571
572 std::string WiFiServiceImpl::SecurityFromCWSecurityMode(
573 CWSecurityMode security) const {
574 switch (security) {
575 case kCWSecurityModeWPA_Enterprise:
576 case kCWSecurityModeWPA2_Enterprise:
577 return onc::wifi::kWPA_EAP;
578 case kCWSecurityModeWPA_PSK:
579 case kCWSecurityModeWPA2_PSK:
580 return onc::wifi::kWPA_PSK;
581 case kCWSecurityModeWEP:
582 return onc::wifi::kWEP_PSK;
583 case kCWSecurityModeOpen:
584 return onc::wifi::kNone;
585 // TODO(mef): Figure out correct mapping.
586 case kCWSecurityModeWPS:
587 case kCWSecurityModeDynamicWEP:
588 return onc::wifi::kWPA_EAP;
589 }
590 return onc::wifi::kWPA_EAP;
591 }
592
593 void WiFiServiceImpl::SortNetworks(NetworkList* networks) {
594 networks->sort(NetworkProperties::OrderByType);
595 }
596
597
598 void WiFiServiceImpl::OnListenerNotification() {
599 std::string connected_network_guid = GUIDFromSSID([interface_ ssid]);
600 DVLOG(1) << " *** Got Notification: " << connected_network_guid;
601 if (connected_network_guid.empty()) {
602 // Find previously connected network and notify that it is disconnected.
603 for (WiFiService::NetworkList::iterator it = networks_.begin();
604 it != networks_.end();
605 ++it) {
606 if (it->connection_state == onc::connection_state::kConnected) {
607 it->connection_state = onc::connection_state::kNotConnected;
608 NotifyNetworkChanged(it->guid);
609 }
610 }
611 } else {
612 NotifyNetworkChanged(connected_network_guid);
613 }
614 }
615
616 void WiFiServiceImpl::NotifyNetworkListChanged(const NetworkList& networks) {
617 if (network_list_changed_observer_.is_null())
618 return;
619
620 NetworkGuidList current_networks;
621 for (NetworkList::const_iterator it = networks.begin();
622 it != networks.end();
623 ++it) {
624 current_networks.push_back(it->guid);
625 }
626
627 message_loop_proxy_->PostTask(
628 FROM_HERE,
629 base::Bind(network_list_changed_observer_, current_networks));
630 }
631
632 void WiFiServiceImpl::NotifyNetworkChanged(const std::string& network_guid) {
633 if (!enable_notify_network_changed_ || networks_changed_observer_.is_null())
634 return;
635
636 DVLOG(1) << "NotifyNetworkChanged: " << network_guid;
637 NetworkGuidList changed_networks(1, network_guid);
638 message_loop_proxy_->PostTask(
639 FROM_HERE,
640 base::Bind(networks_changed_observer_, changed_networks));
641 }
642
643 WiFiService* WiFiService::Create() { return new WiFiServiceImpl(); }
644
645 } // 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