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

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: Remove ScopedNSAutoreleasePool. 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
18 #if !defined(MAC_OS_X_VERSION_10_7) || \
19 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
20
21 // Local definitions of API added in Mac OS X 10.7
22
23 @interface CWInterface (LionAPI)
24 - (BOOL)associateToNetwork:(CWNetwork*)network
25 password:(NSString*)password
26 error:(NSError**)error;
27 - (NSSet*)scanForNetworksWithName:(NSString*)networkName
28 error:(NSError**)error;
29 @end
30
31 enum CWChannelBand {
32 kCWChannelBandUnknown = 0,
33 kCWChannelBand2GHz = 1,
34 kCWChannelBand5GHz = 2,
35 };
36
37 @interface CWChannel : NSObject
38 @property(readonly) CWChannelBand channelBand;
39 @end
40
41 @interface CWNetwork (LionAPI)
42 @property(readonly) CWChannel* wlanChannel;
43 @end
44
45 #endif // 10.7
46
47 namespace wifi {
48
49 const char kErrorAssociateToNetwork[] = "Error.AssociateToNetwork";
50 const char kErrorNotConnected[] = "Error.NotConnected";
51 const char kErrorNotFound[] = "Error.NotFound";
52 const char kErrorNotImplemented[] = "Error.NotImplemented";
53 const char kErrorScanForNetworksWithName[] = "Error.ScanForNetworksWithName";
54
55 // Implementation of WiFiService for Mac OS X.
56 class WiFiServiceMac : public WiFiService {
57 public:
58 WiFiServiceMac();
59 virtual ~WiFiServiceMac();
60
61 // WiFiService interface implementation.
62 virtual void Initialize(
63 scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE;
64
65 virtual void UnInitialize() OVERRIDE;
66
67 virtual void GetProperties(const std::string& network_guid,
68 base::DictionaryValue* properties,
69 std::string* error) OVERRIDE;
70
71 virtual void GetManagedProperties(const std::string& network_guid,
72 base::DictionaryValue* managed_properties,
73 std::string* error) OVERRIDE;
74
75 virtual void GetState(const std::string& network_guid,
76 base::DictionaryValue* properties,
77 std::string* error) OVERRIDE;
78
79 virtual void SetProperties(const std::string& network_guid,
80 scoped_ptr<base::DictionaryValue> properties,
81 std::string* error) OVERRIDE;
82
83 virtual void CreateNetwork(bool shared,
84 scoped_ptr<base::DictionaryValue> properties,
85 std::string* network_guid,
86 std::string* error) OVERRIDE;
87
88 virtual void GetVisibleNetworks(const std::string& network_type,
89 base::ListValue* network_list) OVERRIDE;
90
91 virtual void RequestNetworkScan() OVERRIDE;
92
93 virtual void StartConnect(const std::string& network_guid,
94 std::string* error) OVERRIDE;
95
96 virtual void StartDisconnect(const std::string& network_guid,
97 std::string* error) OVERRIDE;
98
99 virtual void SetEventObservers(
100 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
101 const NetworkGuidListCallback& networks_changed_observer,
102 const NetworkGuidListCallback& network_list_changed_observer) OVERRIDE;
103
104 private:
105 // Checks |ns_error| and if is not |nil|, then stores |error_name|
106 // into |error|.
107 bool CheckError(NSError* ns_error,
108 const char* error_name,
109 std::string* error) const;
110
111 // Gets |ssid| from unique |network_guid|.
112 NSString* SSIDFromGUID(const std::string& network_guid) const {
113 return base::SysUTF8ToNSString(network_guid);
114 }
115
116 // Gets unique |network_guid| string based on |ssid|.
117 std::string GUIDFromSSID(NSString* ssid) const {
118 return base::SysNSStringToUTF8(ssid);
119 }
120
121 // Populates |properties| from |network|.
122 void NetworkPropertiesFromCWNetwork(const CWNetwork* network,
123 NetworkProperties* properties) const;
124
125 // Convert s|CWSecurityMode| into onc::wifi::k{WPA|WEP}* security constant.
126 std::string SecurityFromCWSecurityMode(CWSecurityMode security) const;
127
128 // Waits up to |kMaxAttempts| with |kAttemptDelayMs| delay for connection to
129 // network with |network_guid|. Notifies that |NetworkChanged| upon success.
130 void WaitForNetworkConnect(const std::string& network_guid, int attempt);
131
132 // Gets current |onc::connection_state| for given |network_guid|.
133 std::string GetNetworkConnectionState(const std::string& network_guid) const;
134
135 // Updates |networks_| with the list of visible wireless networks.
136 void UpdateNetworks();
137
138 // Handles notification from |wlan_observer_|.
139 void OnWlanObserverNotification();
140
141 // Notifies |network_list_changed_observer_| that list of visible networks has
142 // changed to |networks|.
143 void NotifyNetworkListChanged(const NetworkList& networks);
144
145 // Notifies |networks_changed_observer_| that network |network_guid|
146 // connection state has changed.
147 void NotifyNetworkChanged(const std::string& network_guid);
148
149 // Default interface.
150 base::scoped_nsobject<CWInterface> interface_;
151 // WLAN Notifications observer.
152 base::scoped_nsobject<NSObject> wlan_observer_;
153
154 // Observer to get notified when network(s) have changed (e.g. connect).
155 NetworkGuidListCallback networks_changed_observer_;
156 // Observer to get notified when network list has changed (scan complete).
157 NetworkGuidListCallback network_list_changed_observer_;
158 // MessageLoopProxy to post events on UI thread.
159 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
160 // Task runner for worker tasks.
161 scoped_refptr<base::SequencedTaskRunner> task_runner_;
162 // Cache of network list collected by GetVisibleNetworks.
163 NetworkList networks_;
164 // Temporary storage of network properties indexed by |network_guid|.
165 base::DictionaryValue network_properties_;
166 // Number of attempts to check that network has connected successfully.
167 static const int kConnectionCheckMaxAttempts = 200;
168 // Delay between attempts to check that network has connected successfully.
169 static const int kConnectionCheckAttemptDelayMs = 100;
170 };
171
172 WiFiServiceMac::WiFiServiceMac() {
173 }
174
175 WiFiServiceMac::~WiFiServiceMac() {
176 }
177
178 void WiFiServiceMac::Initialize(
179 scoped_refptr<base::SequencedTaskRunner> task_runner) {
180 task_runner_.swap(task_runner);
181 interface_.reset([[CWInterface interface] retain]);
182 if (!interface_) {
183 DVLOG(1) << "Failed to initialize default interface.";
184 return;
185 }
186
187 if (![interface_
188 respondsToSelector:@selector(associateToNetwork:password:error:)]) {
189 DVLOG(1) << "CWInterface does not support associateToNetwork.";
190 interface_.reset();
191 return;
192 }
193 }
194
195 void WiFiServiceMac::UnInitialize() {
Robert Sesek 2014/01/13 19:10:28 Should you interface_.reset() here too?
mef 2014/01/13 22:05:34 Done.
196 [[NSNotificationCenter defaultCenter] removeObserver:wlan_observer_];
197 }
198
199 void WiFiServiceMac::GetProperties(const std::string& network_guid,
200 base::DictionaryValue* properties,
Robert Sesek 2014/01/13 19:10:28 nit: alignment
mef 2014/01/13 22:05:34 Done.
201 std::string* error) {
202 for (WiFiService::NetworkList::iterator it = networks_.begin();
203 it != networks_.end();
204 ++it) {
205 if (it->guid == network_guid) {
206 it->connection_state = GetNetworkConnectionState(network_guid);
207 scoped_ptr<base::DictionaryValue> network(it->ToValue(false));
208 properties->Swap(network.get());
209 DVLOG(1) << *properties;
210 return;
211 }
212 }
213
214 *error = kErrorNotFound;
Robert Sesek 2014/01/13 19:10:28 Is it assumed that *error == "" at entry?
mef 2014/01/13 22:05:34 Yes. Should I explicitly set it this way in public
215 }
216
217 void WiFiServiceMac::GetManagedProperties(
218 const std::string& network_guid,
219 base::DictionaryValue* managed_properties,
220 std::string* error) {
221 *error = kErrorNotImplemented;
222 }
223
224 void WiFiServiceMac::GetState(const std::string& network_guid,
225 base::DictionaryValue* properties,
Robert Sesek 2014/01/13 19:10:28 nit: alignment
mef 2014/01/13 22:05:34 Done. I think those are artifacts of Renaming WiFi
226 std::string* error) {
227 *error = kErrorNotImplemented;
228 }
229
230 void WiFiServiceMac::SetProperties(
231 const std::string& network_guid,
232 scoped_ptr<base::DictionaryValue> properties,
233 std::string* error) {
234 network_properties_.SetWithoutPathExpansion(network_guid,
235 properties.release());
236 }
237
238 void WiFiServiceMac::CreateNetwork(
239 bool shared,
240 scoped_ptr<base::DictionaryValue> properties,
241 std::string* network_guid,
242 std::string* error) {
243 *error = kErrorNotImplemented;
244 }
245
246 void WiFiServiceMac::GetVisibleNetworks(const std::string& network_type,
247 base::ListValue* network_list) {
Robert Sesek 2014/01/13 19:10:28 nit: alignment
mef 2014/01/13 22:05:34 Done.
248 if (!network_type.empty() &&
249 network_type != onc::network_type::kAllTypes &&
250 network_type != onc::network_type::kWiFi) {
251 return;
252 }
253
254 if (networks_.empty())
255 RequestNetworkScan();
Robert Sesek 2014/01/13 19:10:28 This will trigger a NetworkListChanged callback, r
mef 2014/01/13 22:05:34 Good question. Toni?
tbarzic 2014/01/16 19:41:48 It's not required, but it's ok if rescan happens h
mef 2014/01/16 23:42:48 Done.
256
257 for (WiFiService::NetworkList::const_iterator it = networks_.begin();
258 it != networks_.end();
259 ++it) {
260 scoped_ptr<base::DictionaryValue> network(it->ToValue(true));
261 network_list->Append(network.release());
262 }
263 }
264
265 void WiFiServiceMac::RequestNetworkScan() {
266 UpdateNetworks();
267 NotifyNetworkListChanged(networks_);
tbarzic 2014/01/13 19:39:30 NotifyNetworkListChanged should be part of UpdateN
mef 2014/01/14 22:10:31 Done.
268 }
269
270 void WiFiServiceMac::StartConnect(const std::string& network_guid,
271 std::string* error) {
Robert Sesek 2014/01/13 19:10:28 nit: alignment
mef 2014/01/13 22:05:34 Done.
272 NSError* ns_error = nil;
273
274 DVLOG(1) << "*** StartConnect: " << network_guid;
275 // Remember previously connected network.
276 std::string connected_network_guid = GUIDFromSSID([interface_ ssid]);
277 // Check, whether desired network is already connected.
Robert Sesek 2014/01/13 19:10:28 nit: remove ,
mef 2014/01/13 22:05:34 Done.
278 if (network_guid == connected_network_guid) {
279 NotifyNetworkChanged(connected_network_guid);
tbarzic 2014/01/13 19:39:30 no need for this, as there are no changes to the n
mef 2014/01/14 22:10:31 From my observations the extension didn't seem to
tbarzic 2014/01/16 19:41:48 hm, that looks like a bug. either in the extension
mef 2014/01/16 23:42:48 I'll try to debug this.
280 return;
281 }
282
283 NSSet* networks = [interface_
tbarzic 2014/01/13 19:39:30 If the scan does not find the network, if should b
mef 2014/01/14 22:10:31 Sounds good.
tbarzic 2014/01/16 19:41:48 Yeah, proper handling in this case would be to cre
mef 2014/01/16 23:42:48 Done. Implemented |CreateNetwork| to store network
284 scanForNetworksWithName:SSIDFromGUID(network_guid)
285 error:&ns_error];
286
287 if (CheckError(ns_error, kErrorScanForNetworksWithName, error))
288 return;
289
290 CWNetwork* network = [networks anyObject];
291 if (network == nil) {
292 *error = kErrorNotFound;
293 return;
294 }
295
296 // Check whether WiFi Password is set in |network_properties_|
Robert Sesek 2014/01/13 19:10:28 nit: end with punctuation
mef 2014/01/13 22:05:34 Done.
297 base::DictionaryValue* properties;
298 base::DictionaryValue* wifi;
299 std::string passphrase;
300 NSString* ns_password = nil;
301 if (network_properties_.GetDictionaryWithoutPathExpansion(network_guid,
302 &properties) &&
303 properties->GetDictionary(onc::network_type::kWiFi, &wifi) &&
304 wifi->GetString(onc::wifi::kPassphrase, &passphrase)) {
305 ns_password = base::SysUTF8ToNSString(passphrase);
306 }
307
308 // Number of attempts to associate to network.
309 static const int kMaxAssociationAttempts = 3;
310 // Try to associate to network several times if timeout or PMK error occurs.
311 for (int i = 0; i < kMaxAssociationAttempts; ++i) {
312 // Nil out the PMK to prevent stale data from causing invalid PMK error
313 // (CoreWLANTypes -3924).
314 [interface_ setPairwiseMasterKey:nil error:&ns_error];
315 if ([interface_ associateToNetwork:network
316 password:ns_password
317 error:&ns_error]) {
318 // Notify that previously connected network has changed.
tbarzic 2014/01/13 19:39:30 Can't this be done in OnWlanObserverNotification (
mef 2014/01/14 22:10:31 Done.
319 NotifyNetworkChanged(connected_network_guid);
320
321 // Start waiting for network connection state change. WaiForNetworkConnect
322 // is async and it'll reset enable_notify_network_changed_.
tbarzic 2014/01/13 19:39:30 the comment is outdated; you've gotten rid of enab
mef 2014/01/14 22:10:31 Done.
323 if (!networks_changed_observer_.is_null()) {
324 WaitForNetworkConnect(network_guid, 0);
325 return;
326 }
327 } else {
328 NSInteger error_code = [ns_error code];
329 if (error_code != kCWTimeoutErr && error_code != kCWInvalidPMKErr) {
330 break;
331 }
332 }
333 }
334 CheckError(ns_error, kErrorAssociateToNetwork, error);
335 }
336
337 void WiFiServiceMac::StartDisconnect(const std::string& network_guid,
338 std::string* error) {
Robert Sesek 2014/01/13 19:10:28 nit: alignment
mef 2014/01/13 22:05:34 Done.
339 DVLOG(1) << "*** StartDisconnect: " << network_guid;
340
341 if (network_guid == GUIDFromSSID([interface_ ssid])) {
342 [interface_ disassociate];
343 } else {
344 *error = kErrorNotConnected;
345 }
346 }
347
348 void WiFiServiceMac::SetEventObservers(
349 scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
350 const NetworkGuidListCallback& networks_changed_observer,
351 const NetworkGuidListCallback& network_list_changed_observer) {
352 message_loop_proxy_.swap(message_loop_proxy);
353 networks_changed_observer_ = networks_changed_observer;
354 network_list_changed_observer_ = network_list_changed_observer;
355
356 // Subscribe to OS notifications.
357 wlan_observer_.reset([[NSNotificationCenter defaultCenter]
Robert Sesek 2014/01/13 19:10:28 If SetEventObservers() is called twice, then you'l
mef 2014/01/13 22:05:34 Done.
358 addObserverForName:kCWSSIDDidChangeNotification
359 object:nil
360 queue:nil
361 usingBlock:^(NSNotification* notification) {
362 task_runner_->PostTask(
Robert Sesek 2014/01/13 19:10:28 nit: this is supposed to be indented 4 spaces from
mef 2014/01/13 22:05:34 Done. I think.
363 FROM_HERE,
364 base::Bind(&WiFiServiceMac::OnWlanObserverNotification,
365 base::Unretained(this)));
366 }]);
367 }
368
369 void WiFiServiceMac::WaitForNetworkConnect(const std::string& network_guid,
370 int attempt) {
Robert Sesek 2014/01/13 19:10:28 nit: alignment
mef 2014/01/13 22:05:34 Done.
371 // If network didn't get connected in |kMaxAttempts|, then stop waiting.
372 if (attempt > kConnectionCheckMaxAttempts) {
373 DLOG(ERROR) << kConnectionCheckMaxAttempts
374 << " attempts exceeded waiting for connect to "
375 << network_guid;
376 return;
377 }
378
379 if (GetNetworkConnectionState(network_guid) ==
380 onc::connection_state::kConnected) {
381 DVLOG(1) << "WiFi Connected, Reachable: " << network_guid;
382 NotifyNetworkChanged(network_guid);
383 } else {
384 // Continue waiting for network connection state change.
Robert Sesek 2014/01/13 19:10:28 Do you need to poll for this, or can you use SCNet
mef 2014/01/13 22:05:34 I think reachability is better, I'll try to use it
385 task_runner_->PostDelayedTask(
386 FROM_HERE,
387 base::Bind(&WiFiServiceMac::WaitForNetworkConnect,
388 base::Unretained(this),
389 network_guid,
390 ++attempt),
391 base::TimeDelta::FromMilliseconds(kConnectionCheckAttemptDelayMs));
392 }
393 }
394
395 std::string WiFiServiceMac::GetNetworkConnectionState(
396 const std::string& network_guid) const {
Robert Sesek 2014/01/13 19:10:28 nit: indent 2 more spaces
mef 2014/01/13 22:05:34 Done.
397 if(network_guid != GUIDFromSSID([interface_ ssid]))
Robert Sesek 2014/01/13 19:10:28 nit: space before (
mef 2014/01/13 22:05:34 Done.
398 return onc::connection_state::kNotConnected;
399
400 // Check whether WiFi network is reachable.
401 struct sockaddr_in local_wifi_address;
402 bzero(&local_wifi_address, sizeof(local_wifi_address));
403 local_wifi_address.sin_len = sizeof(local_wifi_address);
404 local_wifi_address.sin_family = AF_INET;
405 local_wifi_address.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
406 base::ScopedCFTypeRef<SCNetworkReachabilityRef> reachability(
407 SCNetworkReachabilityCreateWithAddress(
408 kCFAllocatorDefault,
409 reinterpret_cast<const struct sockaddr*>(&local_wifi_address)));
410 SCNetworkReachabilityFlags flags = 0u;
411 if (SCNetworkReachabilityGetFlags(reachability, &flags) &&
412 (flags & kSCNetworkReachabilityFlagsReachable) &&
413 (flags & kSCNetworkReachabilityFlagsIsDirect)) {
414 // Network is reachable, report is as |kConnected|.
415 return onc::connection_state::kConnected;
416 }
417 // Network is not reachable yet, so it must be |kConnecting|.
418 return onc::connection_state::kConnecting;
419 }
420
421
422 void WiFiServiceMac::UpdateNetworks() {
423
Robert Sesek 2014/01/13 19:10:28 nit: remove
mef 2014/01/13 22:05:34 Done.
424 NSError* ns_error = nil;
425 NSSet* cw_networks = [interface_ scanForNetworksWithName:nil
426 error:&ns_error];
427
428 if (ns_error != nil)
429 return;
430
431 std::map<std::string, NetworkProperties*> network_properties_map;
432 networks_.clear();
tbarzic 2014/01/13 19:39:30 it would be nice to gather the list of networks wh
mef 2014/01/14 22:10:31 I should be able to do that, just what about netwo
tbarzic 2014/01/16 19:41:48 hm, I think that ChromeOS version does send Networ
mef 2014/01/16 23:42:48 Sounds good. I'll add that to my TODO list for a f
433
434 CWNetwork* cw_network;
Robert Sesek 2014/01/13 19:10:28 You can move this into the for() loop expression.
mef 2014/01/13 22:05:34 Done.
435 // There is one |cw_network| per BSS in |cw_networks|, so go through the set
436 // and combine them, paying attention to supported frequencies.
437 for (cw_network in cw_networks) {
438 NetworkProperties network_properties;
439 NetworkPropertiesFromCWNetwork(cw_network, &network_properties);
440
441 if (network_properties_map.find(network_properties.guid) ==
442 network_properties_map.end()) {
Robert Sesek 2014/01/13 19:10:28 nit: indent 4 spaces more
mef 2014/01/13 22:05:34 Done.
443 networks_.push_back(network_properties);
444 network_properties_map[network_properties.guid] = &networks_.back();
445 } else {
Robert Sesek 2014/01/13 19:10:28 Do you need to update the networks_ list in case n
mef 2014/01/13 22:05:34 I'm just trying to coalesce all networks with same
446 NetworkProperties* existing = network_properties_map.at(
447 network_properties.guid);
448 existing->frequency_set.insert(*network_properties.frequency_set.begin());
449 }
450 }
451 // Sort networks, so connected/connecting is up front.
452 networks_.sort(NetworkProperties::OrderByType);
453 }
454
455 bool WiFiServiceMac::CheckError(NSError* ns_error,
456 const char* error_name,
Robert Sesek 2014/01/13 19:10:28 nit: alignment
mef 2014/01/13 22:05:34 Done.
457 std::string* error) const {
458 if (ns_error != nil) {
459 DLOG(ERROR) << "*** Error:" << error_name << ":" << [ns_error code];
460 *error = error_name;
461 return true;
462 }
463 return false;
464 }
465
466 void WiFiServiceMac::NetworkPropertiesFromCWNetwork(
467 const CWNetwork* network,
468 NetworkProperties* properties) const {
469 std::string network_guid = GUIDFromSSID([network ssid]);
470
471 properties->connection_state = GetNetworkConnectionState(network_guid);
472 properties->ssid = base::SysNSStringToUTF8([network ssid]);
473 properties->name = properties->ssid;
474 properties->guid = network_guid;
475 properties->type = onc::network_type::kWiFi;
476
477 properties->bssid = base::SysNSStringToUTF8([network bssid]);
478 if ([[network wlanChannel] channelBand] == kCWChannelBand2GHz)
479 properties->frequency = kFrequency2400;
480 else
481 properties->frequency = kFrequency5000;
482 properties->frequency_set.insert(properties->frequency);
483 properties->security = SecurityFromCWSecurityMode(
484 static_cast<CWSecurityMode>([[network securityMode] intValue]));
485
486 properties->signal_strength = [[network rssi] intValue];
487 }
488
489 std::string WiFiServiceMac::SecurityFromCWSecurityMode(
490 CWSecurityMode security) const {
491 switch (security) {
492 case kCWSecurityModeWPA_Enterprise:
493 case kCWSecurityModeWPA2_Enterprise:
494 return onc::wifi::kWPA_EAP;
495 case kCWSecurityModeWPA_PSK:
496 case kCWSecurityModeWPA2_PSK:
497 return onc::wifi::kWPA_PSK;
498 case kCWSecurityModeWEP:
499 return onc::wifi::kWEP_PSK;
500 case kCWSecurityModeOpen:
501 return onc::wifi::kNone;
502 // TODO(mef): Figure out correct mapping.
503 case kCWSecurityModeWPS:
504 case kCWSecurityModeDynamicWEP:
505 return onc::wifi::kWPA_EAP;
506 }
507 return onc::wifi::kWPA_EAP;
508 }
509
510 void WiFiServiceMac::OnWlanObserverNotification() {
511 std::string connected_network_guid = GUIDFromSSID([interface_ ssid]);
512 DVLOG(1) << " *** Got Notification: " << connected_network_guid;
513 // There are 2 notifications for every network switch:
514 // 1. When old WLAN is disconnected, |connected_network_guid| is empty.
515 // 2. When new WLAN is connected, |connected_network_guid| is new network
516 // guid.
517 if (connected_network_guid.empty()) {
518 // Find previously connected network and notify that it is disconnected.
519 for (WiFiService::NetworkList::iterator it = networks_.begin();
520 it != networks_.end();
521 ++it) {
522 if (it->connection_state == onc::connection_state::kConnected) {
523 it->connection_state = onc::connection_state::kNotConnected;
524 NotifyNetworkChanged(it->guid);
525 }
526 }
527 } else {
528 // Update connection_state of newly connected network.
529 for (WiFiService::NetworkList::iterator it = networks_.begin();
530 it != networks_.end();
531 ++it) {
532 if (it->guid == connected_network_guid) {
533 it->connection_state =
534 GetNetworkConnectionState(connected_network_guid);
535 NotifyNetworkChanged(connected_network_guid);
536 return;
537 }
538 }
539 // Can't find |connected_network_guid| in |networks_|, try to update it.
540 UpdateNetworks();
541 NotifyNetworkChanged(connected_network_guid);
tbarzic 2014/01/13 19:39:30 WaitForNetworkConnect should probably be done here
mef 2014/01/14 22:10:31 Done.
542 }
543 }
544
545 void WiFiServiceMac::NotifyNetworkListChanged(const NetworkList& networks) {
546 if (network_list_changed_observer_.is_null())
547 return;
548
549 NetworkGuidList current_networks;
550 for (NetworkList::const_iterator it = networks.begin();
551 it != networks.end();
552 ++it) {
553 current_networks.push_back(it->guid);
554 }
555
556 message_loop_proxy_->PostTask(
557 FROM_HERE,
558 base::Bind(network_list_changed_observer_, current_networks));
559 }
560
561 void WiFiServiceMac::NotifyNetworkChanged(const std::string& network_guid) {
562 if (networks_changed_observer_.is_null())
563 return;
564
565 DVLOG(1) << "NotifyNetworkChanged: " << network_guid;
566 NetworkGuidList changed_networks(1, network_guid);
567 message_loop_proxy_->PostTask(
568 FROM_HERE,
569 base::Bind(networks_changed_observer_, changed_networks));
570 }
571
572 // static
573 WiFiService* WiFiService::Create() { return new WiFiServiceMac(); }
574
575 } // 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