OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 "chrome/browser/chromeos/cros/network_library_impl_base.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/json/json_writer.h" | |
9 #include "base/memory/scoped_vector.h" | |
10 #include "base/stl_util.h" | |
11 #include "base/strings/string_util.h" | |
12 #include "chrome/browser/chromeos/cros/network_constants.h" | |
13 #include "chrome/browser/chromeos/login/user_manager.h" | |
14 #include "chrome/browser/chromeos/net/onc_utils.h" | |
15 #include "chromeos/network/network_state_handler.h" | |
16 #include "chromeos/network/network_ui_data.h" | |
17 #include "chromeos/network/onc/onc_constants.h" | |
18 #include "chromeos/network/onc/onc_normalizer.h" | |
19 #include "chromeos/network/onc/onc_signature.h" | |
20 #include "chromeos/network/onc/onc_translator.h" | |
21 #include "chromeos/network/onc/onc_utils.h" | |
22 #include "content/public/browser/browser_thread.h" | |
23 #include "crypto/nss_util.h" // crypto::GetTPMTokenInfo() for 802.1X and VPN. | |
24 #include "third_party/cros_system_api/dbus/service_constants.h" | |
25 | |
26 using content::BrowserThread; | |
27 | |
28 namespace chromeos { | |
29 | |
30 namespace { | |
31 | |
32 // Only send network change notifications to observers once every 50ms. | |
33 const int kNetworkNotifyDelayMs = 50; | |
34 | |
35 // How long we should remember that cellular plan payment was received. | |
36 const int kRecentPlanPaymentHours = 6; | |
37 | |
38 NetworkProfileType GetProfileTypeForSource(onc::ONCSource source) { | |
39 switch (source) { | |
40 case onc::ONC_SOURCE_DEVICE_POLICY: | |
41 return PROFILE_SHARED; | |
42 case onc::ONC_SOURCE_USER_POLICY: | |
43 return PROFILE_USER; | |
44 case onc::ONC_SOURCE_NONE: | |
45 case onc::ONC_SOURCE_USER_IMPORT: | |
46 return PROFILE_NONE; | |
47 } | |
48 NOTREACHED() << "Unknown ONC source " << source; | |
49 return PROFILE_NONE; | |
50 } | |
51 | |
52 } // namespace | |
53 | |
54 NetworkLibraryImplBase::NetworkLibraryImplBase() | |
55 : ethernet_(NULL), | |
56 active_wifi_(NULL), | |
57 active_cellular_(NULL), | |
58 active_wimax_(NULL), | |
59 active_virtual_(NULL), | |
60 available_devices_(0), | |
61 uninitialized_devices_(0), | |
62 enabled_devices_(0), | |
63 busy_devices_(0), | |
64 wifi_scanning_(false), | |
65 is_locked_(false), | |
66 sim_operation_(SIM_OPERATION_NONE), | |
67 notify_manager_weak_factory_(this) { | |
68 } | |
69 | |
70 NetworkLibraryImplBase::~NetworkLibraryImplBase() { | |
71 network_profile_observers_.Clear(); | |
72 network_manager_observers_.Clear(); | |
73 pin_operation_observers_.Clear(); | |
74 STLDeleteValues(&network_map_); | |
75 ClearNetworks(); | |
76 DeleteRememberedNetworks(); | |
77 STLDeleteValues(&device_map_); | |
78 STLDeleteValues(&network_device_observers_); | |
79 STLDeleteValues(&network_observers_); | |
80 STLDeleteValues(&network_onc_map_); | |
81 } | |
82 | |
83 ////////////////////////////////////////////////////////////////////////////// | |
84 // NetworkLibrary implementation. | |
85 | |
86 void NetworkLibraryImplBase::AddNetworkProfileObserver( | |
87 NetworkProfileObserver* observer) { | |
88 network_profile_observers_.AddObserver(observer); | |
89 } | |
90 | |
91 void NetworkLibraryImplBase::RemoveNetworkProfileObserver( | |
92 NetworkProfileObserver* observer) { | |
93 network_profile_observers_.RemoveObserver(observer); | |
94 } | |
95 | |
96 void NetworkLibraryImplBase::AddNetworkManagerObserver( | |
97 NetworkManagerObserver* observer) { | |
98 if (!network_manager_observers_.HasObserver(observer)) | |
99 network_manager_observers_.AddObserver(observer); | |
100 } | |
101 | |
102 void NetworkLibraryImplBase::RemoveNetworkManagerObserver( | |
103 NetworkManagerObserver* observer) { | |
104 network_manager_observers_.RemoveObserver(observer); | |
105 } | |
106 | |
107 void NetworkLibraryImplBase::AddNetworkObserver( | |
108 const std::string& service_path, NetworkObserver* observer) { | |
109 // First, add the observer to the callback map. | |
110 NetworkObserverMap::iterator iter = network_observers_.find(service_path); | |
111 NetworkObserverList* oblist; | |
112 if (iter != network_observers_.end()) { | |
113 oblist = iter->second; | |
114 } else { | |
115 oblist = new NetworkObserverList(); | |
116 network_observers_[service_path] = oblist; | |
117 } | |
118 if (observer && !oblist->HasObserver(observer)) | |
119 oblist->AddObserver(observer); | |
120 MonitorNetworkStart(service_path); | |
121 } | |
122 | |
123 void NetworkLibraryImplBase::RemoveNetworkObserver( | |
124 const std::string& service_path, NetworkObserver* observer) { | |
125 DCHECK(service_path.size()); | |
126 NetworkObserverMap::iterator map_iter = | |
127 network_observers_.find(service_path); | |
128 if (map_iter != network_observers_.end()) { | |
129 map_iter->second->RemoveObserver(observer); | |
130 if (!map_iter->second->might_have_observers()) { | |
131 MonitorNetworkStop(service_path); | |
132 delete map_iter->second; | |
133 network_observers_.erase(map_iter); | |
134 } | |
135 } | |
136 } | |
137 | |
138 void NetworkLibraryImplBase::RemoveObserverForAllNetworks( | |
139 NetworkObserver* observer) { | |
140 DCHECK(observer); | |
141 NetworkObserverMap::iterator map_iter = network_observers_.begin(); | |
142 while (map_iter != network_observers_.end()) { | |
143 map_iter->second->RemoveObserver(observer); | |
144 if (!map_iter->second->might_have_observers()) { | |
145 MonitorNetworkStop(map_iter->first); | |
146 delete map_iter->second; | |
147 network_observers_.erase(map_iter++); | |
148 } else { | |
149 ++map_iter; | |
150 } | |
151 } | |
152 } | |
153 | |
154 void NetworkLibraryImplBase::AddNetworkDeviceObserver( | |
155 const std::string& device_path, NetworkDeviceObserver* observer) { | |
156 // First, add the observer to the callback map. | |
157 NetworkDeviceObserverMap::iterator iter = | |
158 network_device_observers_.find(device_path); | |
159 NetworkDeviceObserverList* oblist; | |
160 if (iter != network_device_observers_.end()) { | |
161 oblist = iter->second; | |
162 } else { | |
163 oblist = new NetworkDeviceObserverList(); | |
164 network_device_observers_[device_path] = oblist; | |
165 } | |
166 if (!oblist->HasObserver(observer)) | |
167 oblist->AddObserver(observer); | |
168 MonitorNetworkDeviceStart(device_path); | |
169 } | |
170 | |
171 void NetworkLibraryImplBase::RemoveNetworkDeviceObserver( | |
172 const std::string& device_path, NetworkDeviceObserver* observer) { | |
173 DCHECK(device_path.size()); | |
174 NetworkDeviceObserverMap::iterator map_iter = | |
175 network_device_observers_.find(device_path); | |
176 if (map_iter != network_device_observers_.end()) { | |
177 map_iter->second->RemoveObserver(observer); | |
178 } | |
179 } | |
180 | |
181 void NetworkLibraryImplBase::DeleteDeviceFromDeviceObserversMap( | |
182 const std::string& device_path) { | |
183 // Delete all device observers associated with this device. | |
184 NetworkDeviceObserverMap::iterator map_iter = | |
185 network_device_observers_.find(device_path); | |
186 if (map_iter != network_device_observers_.end()) { | |
187 delete map_iter->second; | |
188 network_device_observers_.erase(map_iter); | |
189 } | |
190 } | |
191 | |
192 ////////////////////////////////////////////////////////////////////////////// | |
193 | |
194 void NetworkLibraryImplBase::AddPinOperationObserver( | |
195 PinOperationObserver* observer) { | |
196 if (!pin_operation_observers_.HasObserver(observer)) | |
197 pin_operation_observers_.AddObserver(observer); | |
198 } | |
199 | |
200 void NetworkLibraryImplBase::RemovePinOperationObserver( | |
201 PinOperationObserver* observer) { | |
202 pin_operation_observers_.RemoveObserver(observer); | |
203 } | |
204 | |
205 const EthernetNetwork* NetworkLibraryImplBase::ethernet_network() const { | |
206 return ethernet_; | |
207 } | |
208 | |
209 bool NetworkLibraryImplBase::ethernet_connecting() const { | |
210 return ethernet_ ? ethernet_->connecting() : false; | |
211 } | |
212 bool NetworkLibraryImplBase::ethernet_connected() const { | |
213 return ethernet_ ? ethernet_->connected() : false; | |
214 } | |
215 const WifiNetwork* NetworkLibraryImplBase::wifi_network() const { | |
216 return active_wifi_; | |
217 } | |
218 bool NetworkLibraryImplBase::wifi_connecting() const { | |
219 return active_wifi_ ? active_wifi_->connecting() : false; | |
220 } | |
221 bool NetworkLibraryImplBase::wifi_connected() const { | |
222 return active_wifi_ ? active_wifi_->connected() : false; | |
223 } | |
224 const CellularNetwork* NetworkLibraryImplBase::cellular_network() const { | |
225 return active_cellular_; | |
226 } | |
227 bool NetworkLibraryImplBase::cellular_connecting() const { | |
228 return active_cellular_ ? active_cellular_->connecting() : false; | |
229 } | |
230 bool NetworkLibraryImplBase::cellular_connected() const { | |
231 return active_cellular_ ? active_cellular_->connected() : false; | |
232 } | |
233 const WimaxNetwork* NetworkLibraryImplBase::wimax_network() const { | |
234 return active_wimax_; | |
235 } | |
236 bool NetworkLibraryImplBase::wimax_connecting() const { | |
237 return active_wimax_ ? active_wimax_->connecting() : false; | |
238 } | |
239 bool NetworkLibraryImplBase::wimax_connected() const { | |
240 return active_wimax_ ? active_wimax_->connected() : false; | |
241 } | |
242 const VirtualNetwork* NetworkLibraryImplBase::virtual_network() const { | |
243 return active_virtual_; | |
244 } | |
245 bool NetworkLibraryImplBase::virtual_network_connecting() const { | |
246 return active_virtual_ ? active_virtual_->connecting() : false; | |
247 } | |
248 bool NetworkLibraryImplBase::virtual_network_connected() const { | |
249 return active_virtual_ ? active_virtual_->connected() : false; | |
250 } | |
251 bool NetworkLibraryImplBase::Connected() const { | |
252 return ethernet_connected() || wifi_connected() || | |
253 cellular_connected() || wimax_connected(); | |
254 } | |
255 bool NetworkLibraryImplBase::Connecting() const { | |
256 return ethernet_connecting() || wifi_connecting() || | |
257 cellular_connecting() || wimax_connecting(); | |
258 } | |
259 const WifiNetworkVector& NetworkLibraryImplBase::wifi_networks() const { | |
260 return wifi_networks_; | |
261 } | |
262 const WifiNetworkVector& | |
263 NetworkLibraryImplBase::remembered_wifi_networks() const { | |
264 return remembered_wifi_networks_; | |
265 } | |
266 const CellularNetworkVector& NetworkLibraryImplBase::cellular_networks() const { | |
267 return cellular_networks_; | |
268 } | |
269 const WimaxNetworkVector& NetworkLibraryImplBase::wimax_networks() const { | |
270 return wimax_networks_; | |
271 } | |
272 const VirtualNetworkVector& NetworkLibraryImplBase::virtual_networks() const { | |
273 return virtual_networks_; | |
274 } | |
275 const VirtualNetworkVector& | |
276 NetworkLibraryImplBase::remembered_virtual_networks() const { | |
277 return remembered_virtual_networks_; | |
278 } | |
279 | |
280 namespace { | |
281 | |
282 // Use shill's ordering of the services to determine which type of | |
283 // network to return (i.e. don't assume priority of network types). | |
284 // Note: This does not include any virtual networks. | |
285 const Network* highest_priority(const Network* a, const Network*b) { | |
286 if (!a) | |
287 return b; | |
288 if (!b) | |
289 return a; | |
290 if (b->priority_order() < a->priority_order()) | |
291 return b; | |
292 return a; | |
293 } | |
294 | |
295 } // namespace | |
296 | |
297 const Network* NetworkLibraryImplBase::active_network() const { | |
298 const Network* result = active_nonvirtual_network(); | |
299 if (active_virtual_ && active_virtual_->is_active()) | |
300 result = highest_priority(result, active_virtual_); | |
301 return result; | |
302 } | |
303 | |
304 const Network* NetworkLibraryImplBase::active_nonvirtual_network() const { | |
305 const Network* result = NULL; | |
306 if (ethernet_ && ethernet_->is_active()) | |
307 result = ethernet_; | |
308 if (active_wifi_ && active_wifi_->is_active()) | |
309 result = highest_priority(result, active_wifi_); | |
310 if (active_cellular_ && active_cellular_->is_active()) | |
311 result = highest_priority(result, active_cellular_); | |
312 if (active_wimax_ && active_wimax_->is_active()) | |
313 result = highest_priority(result, active_wimax_); | |
314 return result; | |
315 } | |
316 | |
317 const Network* NetworkLibraryImplBase::connected_network() const { | |
318 const Network* result = NULL; | |
319 if (ethernet_ && ethernet_->connected()) | |
320 result = ethernet_; | |
321 if (active_wifi_ && active_wifi_->connected()) | |
322 result = highest_priority(result, active_wifi_); | |
323 if (active_cellular_ && active_cellular_->connected()) | |
324 result = highest_priority(result, active_cellular_); | |
325 if (active_wimax_ && active_wimax_->connected()) | |
326 result = highest_priority(result, active_wimax_); | |
327 return result; | |
328 } | |
329 | |
330 // Connecting order in logical preference. | |
331 const Network* NetworkLibraryImplBase::connecting_network() const { | |
332 if (ethernet_connecting()) | |
333 return ethernet_network(); | |
334 else if (wifi_connecting()) | |
335 return wifi_network(); | |
336 else if (cellular_connecting()) | |
337 return cellular_network(); | |
338 else if (wimax_connecting()) | |
339 return wimax_network(); | |
340 return NULL; | |
341 } | |
342 | |
343 bool NetworkLibraryImplBase::ethernet_available() const { | |
344 return available_devices_ & (1 << TYPE_ETHERNET); | |
345 } | |
346 | |
347 bool NetworkLibraryImplBase::wifi_available() const { | |
348 return available_devices_ & (1 << TYPE_WIFI); | |
349 } | |
350 | |
351 bool NetworkLibraryImplBase::wimax_available() const { | |
352 return available_devices_ & (1 << TYPE_WIMAX); | |
353 } | |
354 | |
355 bool NetworkLibraryImplBase::cellular_available() const { | |
356 return available_devices_ & (1 << TYPE_CELLULAR); | |
357 } | |
358 | |
359 bool NetworkLibraryImplBase::ethernet_enabled() const { | |
360 return enabled_devices_ & (1 << TYPE_ETHERNET); | |
361 } | |
362 | |
363 bool NetworkLibraryImplBase::wifi_enabled() const { | |
364 return enabled_devices_ & (1 << TYPE_WIFI); | |
365 } | |
366 | |
367 bool NetworkLibraryImplBase::wimax_enabled() const { | |
368 return enabled_devices_ & (1 << TYPE_WIMAX); | |
369 } | |
370 | |
371 bool NetworkLibraryImplBase::cellular_enabled() const { | |
372 return enabled_devices_ & (1 << TYPE_CELLULAR); | |
373 } | |
374 | |
375 bool NetworkLibraryImplBase::wifi_scanning() const { | |
376 return wifi_scanning_; | |
377 } | |
378 | |
379 bool NetworkLibraryImplBase::cellular_initializing() const { | |
380 if (uninitialized_devices_ & (1 << TYPE_CELLULAR)) | |
381 return true; | |
382 const NetworkDevice* device = FindDeviceByType(TYPE_CELLULAR); | |
383 if (device && device->scanning()) | |
384 return true; | |
385 return false; | |
386 } | |
387 | |
388 ///////////////////////////////////////////////////////////////////////////// | |
389 | |
390 const NetworkDevice* NetworkLibraryImplBase::FindNetworkDeviceByPath( | |
391 const std::string& path) const { | |
392 NetworkDeviceMap::const_iterator iter = device_map_.find(path); | |
393 if (iter != device_map_.end()) | |
394 return iter->second; | |
395 LOG(WARNING) << "Device path not found: " << path; | |
396 return NULL; | |
397 } | |
398 | |
399 NetworkDevice* NetworkLibraryImplBase::FindNetworkDeviceByPath( | |
400 const std::string& path) { | |
401 NetworkDeviceMap::iterator iter = device_map_.find(path); | |
402 if (iter != device_map_.end()) | |
403 return iter->second; | |
404 LOG(WARNING) << "Device path not found: " << path; | |
405 return NULL; | |
406 } | |
407 | |
408 const NetworkDevice* NetworkLibraryImplBase::FindCellularDevice() const { | |
409 return FindDeviceByType(TYPE_CELLULAR); | |
410 } | |
411 | |
412 const NetworkDevice* NetworkLibraryImplBase::FindMobileDevice() const { | |
413 const NetworkDevice* device = FindDeviceByType(TYPE_CELLULAR); | |
414 if (device) | |
415 return device; | |
416 | |
417 return FindDeviceByType(TYPE_WIMAX); | |
418 } | |
419 | |
420 Network* NetworkLibraryImplBase::FindNetworkByPath( | |
421 const std::string& path) const { | |
422 NetworkMap::const_iterator iter = network_map_.find(path); | |
423 if (iter != network_map_.end()) | |
424 return iter->second; | |
425 return NULL; | |
426 } | |
427 | |
428 Network* NetworkLibraryImplBase::FindNetworkByUniqueId( | |
429 const std::string& unique_id) const { | |
430 NetworkMap::const_iterator found = network_unique_id_map_.find(unique_id); | |
431 if (found != network_unique_id_map_.end()) | |
432 return found->second; | |
433 return NULL; | |
434 } | |
435 | |
436 WirelessNetwork* NetworkLibraryImplBase::FindWirelessNetworkByPath( | |
437 const std::string& path) const { | |
438 Network* network = FindNetworkByPath(path); | |
439 if (network && | |
440 (network->type() == TYPE_WIFI || network->type() == TYPE_WIMAX || | |
441 network->type() == TYPE_CELLULAR)) | |
442 return static_cast<WirelessNetwork*>(network); | |
443 return NULL; | |
444 } | |
445 | |
446 WifiNetwork* NetworkLibraryImplBase::FindWifiNetworkByPath( | |
447 const std::string& path) const { | |
448 Network* network = FindNetworkByPath(path); | |
449 if (network && network->type() == TYPE_WIFI) | |
450 return static_cast<WifiNetwork*>(network); | |
451 return NULL; | |
452 } | |
453 | |
454 WimaxNetwork* NetworkLibraryImplBase::FindWimaxNetworkByPath( | |
455 const std::string& path) const { | |
456 Network* network = FindNetworkByPath(path); | |
457 if (network && (network->type() == TYPE_WIMAX)) | |
458 return static_cast<WimaxNetwork*>(network); | |
459 return NULL; | |
460 } | |
461 | |
462 CellularNetwork* NetworkLibraryImplBase::FindCellularNetworkByPath( | |
463 const std::string& path) const { | |
464 Network* network = FindNetworkByPath(path); | |
465 if (network && network->type() == TYPE_CELLULAR) | |
466 return static_cast<CellularNetwork*>(network); | |
467 return NULL; | |
468 } | |
469 | |
470 VirtualNetwork* NetworkLibraryImplBase::FindVirtualNetworkByPath( | |
471 const std::string& path) const { | |
472 Network* network = FindNetworkByPath(path); | |
473 if (network && network->type() == TYPE_VPN) | |
474 return static_cast<VirtualNetwork*>(network); | |
475 return NULL; | |
476 } | |
477 | |
478 Network* NetworkLibraryImplBase::FindRememberedFromNetwork( | |
479 const Network* network) const { | |
480 for (NetworkMap::const_iterator iter = remembered_network_map_.begin(); | |
481 iter != remembered_network_map_.end(); ++iter) { | |
482 if (iter->second->unique_id() == network->unique_id()) | |
483 return iter->second; | |
484 } | |
485 return NULL; | |
486 } | |
487 | |
488 Network* NetworkLibraryImplBase::FindRememberedNetworkByPath( | |
489 const std::string& path) const { | |
490 NetworkMap::const_iterator iter = remembered_network_map_.find(path); | |
491 if (iter != remembered_network_map_.end()) | |
492 return iter->second; | |
493 return NULL; | |
494 } | |
495 | |
496 const base::DictionaryValue* NetworkLibraryImplBase::FindOncForNetwork( | |
497 const std::string& unique_id) const { | |
498 NetworkOncMap::const_iterator iter = network_onc_map_.find(unique_id); | |
499 return iter != network_onc_map_.end() ? iter->second : NULL; | |
500 } | |
501 | |
502 void NetworkLibraryImplBase::SignalCellularPlanPayment() { | |
503 DCHECK(!HasRecentCellularPlanPayment()); | |
504 cellular_plan_payment_time_ = base::Time::Now(); | |
505 } | |
506 | |
507 bool NetworkLibraryImplBase::HasRecentCellularPlanPayment() { | |
508 return (base::Time::Now() - | |
509 cellular_plan_payment_time_).InHours() < kRecentPlanPaymentHours; | |
510 } | |
511 | |
512 const std::string& NetworkLibraryImplBase::GetCellularHomeCarrierId() const { | |
513 const NetworkDevice* cellular = FindCellularDevice(); | |
514 if (cellular) | |
515 return cellular->home_provider_id(); | |
516 return EmptyString(); | |
517 } | |
518 | |
519 bool NetworkLibraryImplBase::CellularDeviceUsesDirectActivation() const { | |
520 const NetworkDevice* cellular = FindCellularDevice(); | |
521 return cellular && (cellular->carrier() == shill::kCarrierSprint); | |
522 } | |
523 | |
524 ///////////////////////////////////////////////////////////////////////////// | |
525 // Profiles. | |
526 | |
527 bool NetworkLibraryImplBase::HasProfileType(NetworkProfileType type) const { | |
528 for (NetworkProfileList::const_iterator iter = profile_list_.begin(); | |
529 iter != profile_list_.end(); ++iter) { | |
530 if ((*iter).type == type) | |
531 return true; | |
532 } | |
533 return false; | |
534 } | |
535 | |
536 NetworkLibraryImplBase::NetworkProfile::NetworkProfile(const std::string& p, | |
537 NetworkProfileType t) | |
538 : path(p), | |
539 type(t) { | |
540 } | |
541 | |
542 NetworkLibraryImplBase::NetworkProfile::~NetworkProfile() {} | |
543 | |
544 NetworkLibraryImplBase::ConnectData::ConnectData() | |
545 : security(SECURITY_NONE), | |
546 eap_method(EAP_METHOD_UNKNOWN), | |
547 eap_auth(EAP_PHASE_2_AUTH_AUTO), | |
548 eap_use_system_cas(false), | |
549 save_credentials(false), | |
550 profile_type(PROFILE_NONE) { | |
551 } | |
552 | |
553 NetworkLibraryImplBase::ConnectData::~ConnectData() {} | |
554 | |
555 const NetworkDevice* NetworkLibraryImplBase::FindDeviceByType( | |
556 ConnectionType type) const { | |
557 for (NetworkDeviceMap::const_iterator iter = device_map_.begin(); | |
558 iter != device_map_.end(); ++iter) { | |
559 if (iter->second && iter->second->type() == type) | |
560 return iter->second; | |
561 } | |
562 return NULL; | |
563 } | |
564 | |
565 ///////////////////////////////////////////////////////////////////////////// | |
566 // Connect to an existing network. | |
567 | |
568 bool NetworkLibraryImplBase::CanConnectToNetwork(const Network* network) const { | |
569 if (!HasProfileType(PROFILE_USER) && network->RequiresUserProfile()) | |
570 return false; | |
571 return true; | |
572 } | |
573 | |
574 // 1. Request a connection to an existing wifi network. | |
575 // Use |shared| to pass along the desired profile type. | |
576 void NetworkLibraryImplBase::ConnectToWifiNetwork( | |
577 WifiNetwork* wifi, bool shared) { | |
578 NetworkConnectStartWifi(wifi, shared ? PROFILE_SHARED : PROFILE_USER); | |
579 } | |
580 | |
581 // 1. Request a connection to an existing wifi network. | |
582 void NetworkLibraryImplBase::ConnectToWifiNetwork(WifiNetwork* wifi) { | |
583 NetworkConnectStartWifi(wifi, PROFILE_NONE); | |
584 } | |
585 | |
586 // 1. Request a connection to an existing wimax network. | |
587 // Use |shared| to pass along the desired profile type. | |
588 void NetworkLibraryImplBase::ConnectToWimaxNetwork( | |
589 WimaxNetwork* wimax, bool shared) { | |
590 NetworkConnectStart(wimax, shared ? PROFILE_SHARED : PROFILE_USER); | |
591 } | |
592 | |
593 // 1. Request a connection to an existing wimax network. | |
594 void NetworkLibraryImplBase::ConnectToWimaxNetwork(WimaxNetwork* wimax) { | |
595 NetworkConnectStart(wimax, PROFILE_NONE); | |
596 } | |
597 | |
598 // 1. Connect to a cellular network. | |
599 void NetworkLibraryImplBase::ConnectToCellularNetwork( | |
600 CellularNetwork* cellular) { | |
601 NetworkConnectStart(cellular, PROFILE_NONE); | |
602 } | |
603 | |
604 // 1. Connect to an existing virtual network. | |
605 void NetworkLibraryImplBase::ConnectToVirtualNetwork(VirtualNetwork* vpn) { | |
606 NetworkConnectStartVPN(vpn); | |
607 } | |
608 | |
609 // 2. Start the connection. | |
610 void NetworkLibraryImplBase::NetworkConnectStartWifi( | |
611 WifiNetwork* wifi, NetworkProfileType profile_type) { | |
612 DCHECK(!wifi->connection_started()); | |
613 // This will happen if a network resets, gets out of range or is forgotten. | |
614 if (wifi->user_passphrase_ != wifi->passphrase_ || | |
615 wifi->passphrase_required()) | |
616 wifi->SetPassphrase(wifi->user_passphrase_); | |
617 // For enterprise 802.1X networks, always provide TPM PIN when available. | |
618 // shill uses the PIN if it needs to access certificates in the TPM and | |
619 // ignores it otherwise. | |
620 if (wifi->encryption() == SECURITY_8021X) { | |
621 // If the TPM initialization has not completed, GetTpmPin() will return | |
622 // an empty value, in which case we do not want to clear the PIN since | |
623 // that will cause shill to flag the network as unconfigured. | |
624 // TODO(stevenjb): We may want to delay attempting to connect, or fail | |
625 // immediately, rather than let the network layer attempt a connection. | |
626 std::string tpm_pin = GetTpmPin(); | |
627 if (!tpm_pin.empty()) | |
628 wifi->SetCertificatePin(tpm_pin); | |
629 } | |
630 NetworkConnectStart(wifi, profile_type); | |
631 } | |
632 | |
633 void NetworkLibraryImplBase::NetworkConnectStartVPN(VirtualNetwork* vpn) { | |
634 // shill needs the TPM PIN for some VPN networks to access client | |
635 // certificates, and ignores the PIN if it doesn't need them. Only set this | |
636 // if the TPM is ready (see comment in NetworkConnectStartWifi). | |
637 std::string tpm_pin = GetTpmPin(); | |
638 if (!tpm_pin.empty()) { | |
639 std::string tpm_slot = GetTpmSlot(); | |
640 vpn->SetCertificateSlotAndPin(tpm_slot, tpm_pin); | |
641 } | |
642 NetworkConnectStart(vpn, PROFILE_NONE); | |
643 } | |
644 | |
645 void NetworkLibraryImplBase::NetworkConnectStart( | |
646 Network* network, NetworkProfileType profile_type) { | |
647 DCHECK(network); | |
648 DCHECK(!network->connection_started()); | |
649 // In order to be certain to trigger any notifications, set the connecting | |
650 // state locally and notify observers. Otherwise there might be a state | |
651 // change without a forced notify. | |
652 network->set_connecting(); | |
653 // Distinguish between user-initiated connection attempts | |
654 // and auto-connect. | |
655 network->set_user_connect_state(USER_CONNECT_STARTED); | |
656 NotifyNetworkManagerChanged(true); // Forced update. | |
657 VLOG(1) << "Requesting connect to network: " << network->name() | |
658 << " profile type: " << profile_type; | |
659 // Specify the correct profile for wifi networks (if specified or unset). | |
660 if ((network->type() == TYPE_WIFI || network->type() == TYPE_WIMAX) && | |
661 (profile_type != PROFILE_NONE || | |
662 network->profile_type() == PROFILE_NONE)) { | |
663 if (network->RequiresUserProfile()) | |
664 profile_type = PROFILE_USER; // Networks with certs can not be shared. | |
665 else if (profile_type == PROFILE_NONE) | |
666 profile_type = PROFILE_SHARED; // Other networks are shared by default. | |
667 std::string profile_path = GetProfilePath(profile_type); | |
668 if (!profile_path.empty()) { | |
669 if (profile_path != network->profile_path()) | |
670 SetProfileType(network, profile_type); | |
671 } else if (profile_type == PROFILE_USER) { | |
672 // The user profile was specified but is not available (i.e. pre-login). | |
673 // Add this network to the list of networks to move to the user profile | |
674 // when it becomes available. | |
675 VLOG(1) << "Queuing: " << network->name() << " to user_networks list."; | |
676 user_networks_.push_back(network->service_path()); | |
677 } | |
678 } | |
679 CallConnectToNetwork(network); | |
680 } | |
681 | |
682 // 3. Start the connection attempt for Network. | |
683 // Must Call NetworkConnectCompleted when the connection attempt completes. | |
684 // virtual void CallConnectToNetwork(Network* network) = 0; | |
685 | |
686 // 4. Complete the connection. | |
687 void NetworkLibraryImplBase::NetworkConnectCompleted( | |
688 Network* network, NetworkConnectStatus status) { | |
689 DCHECK(network); | |
690 if (status != CONNECT_SUCCESS) { | |
691 // This will trigger the connection failed notification. | |
692 // TODO(stevenjb): Remove if chromium-os:13203 gets fixed. | |
693 network->SetState(STATE_FAILURE); | |
694 if (status == CONNECT_BAD_PASSPHRASE) { | |
695 network->SetError(ERROR_BAD_PASSPHRASE); | |
696 } else { | |
697 network->SetError(ERROR_CONNECT_FAILED); | |
698 } | |
699 NotifyNetworkManagerChanged(true); // Forced update. | |
700 NotifyNetworkChanged(network); | |
701 VLOG(1) << "Error connecting to network: " << network->name() | |
702 << " Status: " << status; | |
703 return; | |
704 } | |
705 | |
706 VLOG(1) << "Connected to network: " << network->name() | |
707 << " State: " << network->state() | |
708 << " Status: " << status; | |
709 | |
710 // If the user asked not to save credentials, shill will have | |
711 // forgotten them. Wipe our cache as well. | |
712 if (!network->save_credentials()) | |
713 network->EraseCredentials(); | |
714 | |
715 ClearActiveNetwork(network->type()); | |
716 UpdateActiveNetwork(network); | |
717 | |
718 // Notify observers. | |
719 NotifyNetworkManagerChanged(true); // Forced update. | |
720 NotifyNetworkChanged(network); | |
721 } | |
722 | |
723 ///////////////////////////////////////////////////////////////////////////// | |
724 // Request a network and connect to it. | |
725 | |
726 // 1. Connect to an unconfigured or unlisted wifi network. | |
727 // This needs to request information about the named service. | |
728 // The connection attempt will occur in the callback. | |
729 void NetworkLibraryImplBase::ConnectToUnconfiguredWifiNetwork( | |
730 const std::string& ssid, | |
731 ConnectionSecurity security, | |
732 const std::string& passphrase, | |
733 const EAPConfigData* eap_config, | |
734 bool save_credentials, | |
735 bool shared) { | |
736 // Store the connection data to be used by the callback. | |
737 connect_data_.security = security; | |
738 connect_data_.service_name = ssid; | |
739 connect_data_.passphrase = passphrase; | |
740 connect_data_.save_credentials = save_credentials; | |
741 connect_data_.profile_type = shared ? PROFILE_SHARED : PROFILE_USER; | |
742 if (security == SECURITY_8021X) { | |
743 DCHECK(eap_config); | |
744 connect_data_.service_name = ssid; | |
745 connect_data_.eap_method = eap_config->method; | |
746 connect_data_.eap_auth = eap_config->auth; | |
747 connect_data_.server_ca_cert_pem = eap_config->server_ca_cert_pem; | |
748 connect_data_.eap_use_system_cas = eap_config->use_system_cas; | |
749 connect_data_.client_cert_pkcs11_id = | |
750 eap_config->client_cert_pkcs11_id; | |
751 connect_data_.eap_identity = eap_config->identity; | |
752 connect_data_.eap_anonymous_identity = eap_config->anonymous_identity; | |
753 } | |
754 | |
755 CallRequestWifiNetworkAndConnect(ssid, security); | |
756 } | |
757 | |
758 // 1. Connect to a virtual network with a PSK. | |
759 void NetworkLibraryImplBase::ConnectToUnconfiguredVirtualNetwork( | |
760 const std::string& service_name, | |
761 const std::string& server_hostname, | |
762 ProviderType provider_type, | |
763 const VPNConfigData& config) { | |
764 // Store the connection data to be used by the callback. | |
765 connect_data_.service_name = service_name; | |
766 connect_data_.server_hostname = server_hostname; | |
767 connect_data_.psk_key = config.psk; | |
768 connect_data_.server_ca_cert_pem = config.server_ca_cert_pem; | |
769 connect_data_.client_cert_pkcs11_id = config.client_cert_pkcs11_id; | |
770 connect_data_.username = config.username; | |
771 connect_data_.passphrase = config.user_passphrase; | |
772 connect_data_.otp = config.otp; | |
773 connect_data_.group_name = config.group_name; | |
774 connect_data_.save_credentials = config.save_credentials; | |
775 CallRequestVirtualNetworkAndConnect( | |
776 service_name, server_hostname, provider_type); | |
777 } | |
778 | |
779 // 2. Requests a WiFi Network by SSID and security. | |
780 // Calls ConnectToWifiNetworkUsingConnectData if network request succeeds. | |
781 // virtual void CallRequestWifiNetworkAndConnect( | |
782 // const std::string& ssid, ConnectionSecurity security) = 0; | |
783 | |
784 // 2. Requests a Virtual Network by service name, etc. | |
785 // Calls ConnectToVirtualNetworkUsingConnectData if network request succeeds. | |
786 // virtual void CallRequestVirtualNetworkAndConnect( | |
787 // const std::string& service_name, | |
788 // const std::string& server_hostname, | |
789 // ProviderType provider_type) = 0; | |
790 | |
791 // 3. Sets network properties stored in ConnectData and calls | |
792 // NetworkConnectStart. | |
793 void NetworkLibraryImplBase::ConnectToWifiNetworkUsingConnectData( | |
794 WifiNetwork* wifi) { | |
795 ConnectData& data = connect_data_; | |
796 if (wifi->name() != data.service_name) { | |
797 LOG(WARNING) << "WiFi network name does not match ConnectData: " | |
798 << wifi->name() << " != " << data.service_name; | |
799 return; | |
800 } | |
801 wifi->set_added(true); | |
802 if (data.security == SECURITY_8021X) { | |
803 // Enterprise 802.1X EAP network. | |
804 wifi->SetEAPMethod(data.eap_method); | |
805 wifi->SetEAPPhase2Auth(data.eap_auth); | |
806 wifi->SetEAPServerCaCertPEM(data.server_ca_cert_pem); | |
807 wifi->SetEAPUseSystemCAs(data.eap_use_system_cas); | |
808 wifi->SetEAPClientCertPkcs11Id(data.client_cert_pkcs11_id); | |
809 wifi->SetEAPIdentity(data.eap_identity); | |
810 wifi->SetEAPAnonymousIdentity(data.eap_anonymous_identity); | |
811 wifi->SetEAPPassphrase(data.passphrase); | |
812 wifi->SetSaveCredentials(data.save_credentials); | |
813 } else { | |
814 // Ordinary, non-802.1X network. | |
815 wifi->SetPassphrase(data.passphrase); | |
816 } | |
817 | |
818 NetworkConnectStartWifi(wifi, data.profile_type); | |
819 } | |
820 | |
821 // 3. Sets network properties stored in ConnectData and calls | |
822 // ConnectToVirtualNetwork. | |
823 void NetworkLibraryImplBase::ConnectToVirtualNetworkUsingConnectData( | |
824 VirtualNetwork* vpn) { | |
825 ConnectData& data = connect_data_; | |
826 if (vpn->name() != data.service_name) { | |
827 LOG(WARNING) << "Virtual network name does not match ConnectData: " | |
828 << vpn->name() << " != " << data.service_name; | |
829 return; | |
830 } | |
831 | |
832 // When a L2TP/IPsec certificate-based VPN is created, the VirtualNetwork | |
833 // instance is created by NativeNetworkParser::CreateNetworkFromInfo(). | |
834 // At that point, the provider type is deduced based on the value of | |
835 // client_cert_id_ of the VirtualNetwork instance, which hasn't been | |
836 // updated to the value of connect_data_.client_cert_pkcs11_id. Thus, | |
837 // the provider type is always incorrectly set to L2TP_IPSEC_PSK when | |
838 // L2TP_IPSEC_USER_CERT is expected. Here we fix the provider type based | |
839 // on connect_data_.client_cert_pkcs11_id. | |
840 // | |
841 // TODO(benchan): This is a quick and dirty workaround, we should refactor | |
842 // the code to make the flow more straightforward. See crosbug.com/24636 | |
843 if (vpn->provider_type() == PROVIDER_TYPE_L2TP_IPSEC_PSK && | |
844 !connect_data_.client_cert_pkcs11_id.empty()) { | |
845 vpn->set_provider_type(PROVIDER_TYPE_L2TP_IPSEC_USER_CERT); | |
846 } | |
847 | |
848 vpn->set_added(true); | |
849 if (!data.server_hostname.empty()) | |
850 vpn->set_server_hostname(data.server_hostname); | |
851 | |
852 vpn->SetCACertPEM(data.server_ca_cert_pem); | |
853 switch (vpn->provider_type()) { | |
854 case PROVIDER_TYPE_L2TP_IPSEC_PSK: | |
855 vpn->SetL2TPIPsecPSKCredentials( | |
856 data.psk_key, data.username, data.passphrase, data.group_name); | |
857 break; | |
858 case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: { | |
859 vpn->SetL2TPIPsecCertCredentials( | |
860 data.client_cert_pkcs11_id, | |
861 data.username, data.passphrase, data.group_name); | |
862 break; | |
863 } | |
864 case PROVIDER_TYPE_OPEN_VPN: { | |
865 vpn->SetOpenVPNCredentials( | |
866 data.client_cert_pkcs11_id, | |
867 data.username, data.passphrase, data.otp); | |
868 break; | |
869 } | |
870 case PROVIDER_TYPE_MAX: | |
871 NOTREACHED(); | |
872 break; | |
873 } | |
874 vpn->SetSaveCredentials(data.save_credentials); | |
875 | |
876 NetworkConnectStartVPN(vpn); | |
877 } | |
878 | |
879 ///////////////////////////////////////////////////////////////////////////// | |
880 | |
881 void NetworkLibraryImplBase::ForgetNetwork(const std::string& service_path) { | |
882 // Remove network from remembered list and notify observers. | |
883 DeleteRememberedNetwork(service_path); | |
884 NotifyNetworkManagerChanged(true); // Forced update. | |
885 } | |
886 | |
887 ///////////////////////////////////////////////////////////////////////////// | |
888 | |
889 void NetworkLibraryImplBase::EnableEthernetNetworkDevice(bool enable) { | |
890 if (is_locked_) | |
891 return; | |
892 CallEnableNetworkDeviceType(TYPE_ETHERNET, enable); | |
893 } | |
894 | |
895 void NetworkLibraryImplBase::EnableWifiNetworkDevice(bool enable) { | |
896 if (is_locked_) | |
897 return; | |
898 CallEnableNetworkDeviceType(TYPE_WIFI, enable); | |
899 } | |
900 | |
901 void NetworkLibraryImplBase::EnableWimaxNetworkDevice(bool enable) { | |
902 if (is_locked_) | |
903 return; | |
904 CallEnableNetworkDeviceType(TYPE_WIMAX, enable); | |
905 } | |
906 | |
907 void NetworkLibraryImplBase::EnableCellularNetworkDevice(bool enable) { | |
908 if (is_locked_) | |
909 return; | |
910 CallEnableNetworkDeviceType(TYPE_CELLULAR, enable); | |
911 } | |
912 | |
913 void NetworkLibraryImplBase::SwitchToPreferredNetwork() { | |
914 // If current network (if any) is not preferred, check network service list to | |
915 // see if the first not connected network is preferred and set to autoconnect. | |
916 // If so, connect to it. | |
917 if (!wifi_enabled() || (active_wifi_ && active_wifi_->preferred())) | |
918 return; | |
919 for (WifiNetworkVector::const_iterator it = wifi_networks_.begin(); | |
920 it != wifi_networks_.end(); ++it) { | |
921 WifiNetwork* wifi = *it; | |
922 if (wifi->connected() || wifi->connecting()) // Skip connected/connecting. | |
923 continue; | |
924 if (!wifi->preferred()) // All preferred networks are sorted in front. | |
925 break; | |
926 if (wifi->auto_connect()) { | |
927 ConnectToWifiNetwork(wifi); | |
928 break; | |
929 } | |
930 } | |
931 } | |
932 | |
933 namespace { | |
934 | |
935 class UserStringSubstitution : public onc::StringSubstitution { | |
936 public: | |
937 UserStringSubstitution() {} | |
938 virtual bool GetSubstitute(const std::string& placeholder, | |
939 std::string* substitute) const OVERRIDE { | |
940 if (!UserManager::Get()->IsUserLoggedIn()) | |
941 return false; | |
942 const User* logged_in_user = UserManager::Get()->GetLoggedInUser(); | |
943 if (placeholder == onc::substitutes::kLoginIDField) | |
944 *substitute = logged_in_user->GetAccountName(false); | |
945 else if (placeholder == onc::substitutes::kEmailField) | |
946 *substitute = logged_in_user->email(); | |
947 else | |
948 return false; | |
949 return true; | |
950 } | |
951 }; | |
952 | |
953 } // namespace | |
954 | |
955 void NetworkLibraryImplBase::LoadOncNetworks( | |
956 const base::ListValue& network_configs, | |
957 onc::ONCSource source) { | |
958 VLOG(2) << __func__ << ": called on " << network_configs; | |
959 NetworkProfile* profile = NULL; | |
960 bool from_policy = (source == onc::ONC_SOURCE_USER_POLICY || | |
961 source == onc::ONC_SOURCE_DEVICE_POLICY); | |
962 | |
963 // Policies are applied to a specific Shill profile. User ONC import however | |
964 // is applied to whatever profile Shill chooses. This should be the profile | |
965 // that is already associated with a network and if no profile is associated | |
966 // yet, it should be the user profile. | |
967 if (from_policy) { | |
968 profile = GetProfileForType(GetProfileTypeForSource(source)); | |
969 if (profile == NULL) { | |
970 VLOG(2) << "Profile for ONC source " << onc::GetSourceAsString(source) | |
971 << " doesn't exist."; | |
972 return; | |
973 } | |
974 } | |
975 | |
976 std::set<std::string> removal_ids; | |
977 std::set<std::string>& network_ids(network_source_map_[source]); | |
978 network_ids.clear(); | |
979 VLOG(2) << "ONC file has " << network_configs.GetSize() << " networks"; | |
980 for (base::ListValue::const_iterator it(network_configs.begin()); | |
981 it != network_configs.end(); ++it) { | |
982 const base::DictionaryValue* network; | |
983 (*it)->GetAsDictionary(&network); | |
984 | |
985 bool marked_for_removal = false; | |
986 network->GetBooleanWithoutPathExpansion(onc::kRemove, | |
987 &marked_for_removal); | |
988 | |
989 std::string type; | |
990 network->GetStringWithoutPathExpansion(onc::network_config::kType, &type); | |
991 | |
992 std::string guid; | |
993 network->GetStringWithoutPathExpansion(onc::network_config::kGUID, &guid); | |
994 | |
995 if (source == onc::ONC_SOURCE_USER_IMPORT && marked_for_removal) { | |
996 // User import supports the removal of networks by ID. | |
997 removal_ids.insert(guid); | |
998 continue; | |
999 } | |
1000 | |
1001 // Don't configure a network that is supposed to be removed. For | |
1002 // policy-managed networks, the "remove" functionality of ONC is | |
1003 // irrelevant. Instead, in general, all previously configured networks | |
1004 // that are no longer configured are removed. | |
1005 if (marked_for_removal) | |
1006 continue; | |
1007 | |
1008 // Store the network's identifier. The identifiers are later used to clean | |
1009 // out any previously-existing networks that had been configured through | |
1010 // policy but are no longer specified in the updated ONC blob. | |
1011 network_ids.insert(guid); | |
1012 | |
1013 // Expand strings like LoginID | |
1014 base::DictionaryValue* expanded_network = network->DeepCopy(); | |
1015 UserStringSubstitution substitution; | |
1016 onc::ExpandStringsInOncObject(onc::kNetworkConfigurationSignature, | |
1017 substitution, | |
1018 expanded_network); | |
1019 | |
1020 // Update the ONC map. | |
1021 const base::DictionaryValue*& entry = network_onc_map_[guid]; | |
1022 if (entry && entry->Equals(expanded_network)) | |
1023 continue; | |
1024 | |
1025 delete entry; | |
1026 entry = expanded_network; | |
1027 | |
1028 // Normalize the ONC: Remove irrelevant fields. | |
1029 onc::Normalizer normalizer(true /* remove recommended fields */); | |
1030 scoped_ptr<base::DictionaryValue> normalized_network = | |
1031 normalizer.NormalizeObject(&onc::kNetworkConfigurationSignature, | |
1032 *expanded_network); | |
1033 | |
1034 // Configure the network. | |
1035 scoped_ptr<base::DictionaryValue> shill_dict = | |
1036 onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature, | |
1037 *normalized_network); | |
1038 | |
1039 // Set the UIData. | |
1040 scoped_ptr<NetworkUIData> ui_data = | |
1041 NetworkUIData::CreateFromONC(source, *normalized_network); | |
1042 base::DictionaryValue ui_data_dict; | |
1043 ui_data->FillDictionary(&ui_data_dict); | |
1044 std::string ui_data_json; | |
1045 base::JSONWriter::Write(&ui_data_dict, &ui_data_json); | |
1046 shill_dict->SetStringWithoutPathExpansion(flimflam::kUIDataProperty, | |
1047 ui_data_json); | |
1048 | |
1049 // Set the appropriate profile for |source|. | |
1050 if (profile != NULL) { | |
1051 shill_dict->SetStringWithoutPathExpansion(flimflam::kProfileProperty, | |
1052 profile->path); | |
1053 } | |
1054 | |
1055 // For Ethernet networks, apply them to the current Ethernet service. | |
1056 if (type == onc::network_type::kEthernet) { | |
1057 const EthernetNetwork* ethernet = ethernet_network(); | |
1058 if (ethernet) { | |
1059 CallConfigureService(ethernet->unique_id(), shill_dict.get()); | |
1060 } else { | |
1061 LOG(WARNING) << "Tried to import ONC with an Ethernet network when " | |
1062 << "there is no active Ethernet connection."; | |
1063 } | |
1064 } else { | |
1065 CallConfigureService(guid, shill_dict.get()); | |
1066 } | |
1067 } | |
1068 | |
1069 if (from_policy) { | |
1070 // For policy-managed networks, go through the list of existing remembered | |
1071 // networks and clean out the ones that no longer have a definition in the | |
1072 // ONC blob. We first collect the networks and do the actual deletion later | |
1073 // because ForgetNetwork() changes the remembered network vectors. | |
1074 ForgetNetworksById(source, network_ids, false); | |
1075 } else if (source == onc::ONC_SOURCE_USER_IMPORT && !removal_ids.empty()) { | |
1076 ForgetNetworksById(source, removal_ids, true); | |
1077 } | |
1078 // Ensure NetworkStateHandler properties are up-to-date. | |
1079 if (NetworkHandler::IsInitialized()) { | |
1080 NetworkHandler::Get()->network_state_handler()-> | |
1081 RequestUpdateForAllNetworks(); | |
1082 } | |
1083 } | |
1084 | |
1085 //////////////////////////////////////////////////////////////////////////// | |
1086 // Testing functions. | |
1087 | |
1088 bool NetworkLibraryImplBase::SetActiveNetwork( | |
1089 ConnectionType type, const std::string& service_path) { | |
1090 Network* network = NULL; | |
1091 if (!service_path.empty()) | |
1092 network = FindNetworkByPath(service_path); | |
1093 if (network && network->type() != type) { | |
1094 LOG(WARNING) << "SetActiveNetwork type mismatch for: " << network->name(); | |
1095 return false; | |
1096 } | |
1097 | |
1098 ClearActiveNetwork(type); | |
1099 | |
1100 if (!network) | |
1101 return true; | |
1102 | |
1103 // Set |network| to active. | |
1104 UpdateActiveNetwork(network); | |
1105 return true; | |
1106 } | |
1107 | |
1108 //////////////////////////////////////////////////////////////////////////// | |
1109 // Network list management functions. | |
1110 | |
1111 // Note: sometimes shill still returns networks when the device type is | |
1112 // disabled. Always check the appropriate enabled() state before adding | |
1113 // networks to a list or setting an active network so that we do not show them | |
1114 // in the UI. | |
1115 | |
1116 // This relies on services being requested from shill in priority order, | |
1117 // and the updates getting processed and received in order. | |
1118 void NetworkLibraryImplBase::UpdateActiveNetwork(Network* network) { | |
1119 network->set_is_active(true); | |
1120 ConnectionType type(network->type()); | |
1121 if (type == TYPE_ETHERNET) { | |
1122 if (ethernet_enabled()) { | |
1123 // Set ethernet_ to the first connected ethernet service, or the first | |
1124 // disconnected ethernet service if none are connected. | |
1125 if (ethernet_ == NULL || !ethernet_->connected()) { | |
1126 ethernet_ = static_cast<EthernetNetwork*>(network); | |
1127 VLOG(2) << "Active ethernet -> " << ethernet_->name(); | |
1128 } | |
1129 } | |
1130 } else if (type == TYPE_WIFI) { | |
1131 if (wifi_enabled()) { | |
1132 // Set active_wifi_ to the first connected or connecting wifi service. | |
1133 if (active_wifi_ == NULL && network->connecting_or_connected()) { | |
1134 active_wifi_ = static_cast<WifiNetwork*>(network); | |
1135 VLOG(2) << "Active wifi -> " << active_wifi_->name(); | |
1136 } | |
1137 } | |
1138 } else if (type == TYPE_CELLULAR) { | |
1139 if (cellular_enabled()) { | |
1140 // Set active_cellular_ to first connected/connecting celluar service. | |
1141 if (active_cellular_ == NULL && network->connecting_or_connected()) { | |
1142 active_cellular_ = static_cast<CellularNetwork*>(network); | |
1143 VLOG(2) << "Active cellular -> " << active_cellular_->name(); | |
1144 } | |
1145 } | |
1146 } else if (type == TYPE_WIMAX) { | |
1147 if (wimax_enabled()) { | |
1148 // Set active_wimax_ to first connected/connecting wimax service. | |
1149 if (active_wimax_ == NULL && network->connecting_or_connected()) { | |
1150 active_wimax_ = static_cast<WimaxNetwork*>(network); | |
1151 VLOG(2) << "Active wimax -> " << active_wimax_->name(); | |
1152 } | |
1153 } | |
1154 } else if (type == TYPE_VPN) { | |
1155 // Set active_virtual_ to the first connected or connecting vpn service. { | |
1156 if (active_virtual_ == NULL && network->connecting_or_connected()) { | |
1157 active_virtual_ = static_cast<VirtualNetwork*>(network); | |
1158 VLOG(2) << "Active virtual -> " << active_virtual_->name(); | |
1159 } | |
1160 } | |
1161 } | |
1162 | |
1163 void NetworkLibraryImplBase::ClearActiveNetwork(ConnectionType type) { | |
1164 // Clear any existing active network matching |type|. | |
1165 for (NetworkMap::iterator iter = network_map_.begin(); | |
1166 iter != network_map_.end(); ++iter) { | |
1167 Network* other = iter->second; | |
1168 if (other->type() == type) | |
1169 other->set_is_active(false); | |
1170 } | |
1171 switch (type) { | |
1172 case TYPE_ETHERNET: | |
1173 ethernet_ = NULL; | |
1174 break; | |
1175 case TYPE_WIFI: | |
1176 active_wifi_ = NULL; | |
1177 break; | |
1178 case TYPE_CELLULAR: | |
1179 active_cellular_ = NULL; | |
1180 break; | |
1181 case TYPE_WIMAX: | |
1182 active_wimax_ = NULL; | |
1183 break; | |
1184 case TYPE_VPN: | |
1185 active_virtual_ = NULL; | |
1186 break; | |
1187 default: | |
1188 break; | |
1189 } | |
1190 } | |
1191 | |
1192 void NetworkLibraryImplBase::AddNetwork(Network* network) { | |
1193 std::pair<NetworkMap::iterator, bool> result = | |
1194 network_map_.insert(std::make_pair(network->service_path(), network)); | |
1195 DCHECK(result.second); // Should only get called with new network. | |
1196 VLOG(2) << "Adding Network: " << network->service_path() | |
1197 << " (" << network->name() << ")"; | |
1198 ConnectionType type(network->type()); | |
1199 if (type == TYPE_WIFI) { | |
1200 if (wifi_enabled()) | |
1201 wifi_networks_.push_back(static_cast<WifiNetwork*>(network)); | |
1202 } else if (type == TYPE_CELLULAR) { | |
1203 if (cellular_enabled()) | |
1204 cellular_networks_.push_back(static_cast<CellularNetwork*>(network)); | |
1205 } else if (type == TYPE_WIMAX) { | |
1206 if (wimax_enabled()) | |
1207 wimax_networks_.push_back(static_cast<WimaxNetwork*>(network)); | |
1208 } else if (type == TYPE_VPN) { | |
1209 virtual_networks_.push_back(static_cast<VirtualNetwork*>(network)); | |
1210 } | |
1211 // Do not set the active network here. Wait until we parse the network. | |
1212 } | |
1213 | |
1214 // Deletes a network. It must already be removed from any lists. | |
1215 void NetworkLibraryImplBase::DeleteNetwork(Network* network) { | |
1216 CHECK(network_map_.find(network->service_path()) == network_map_.end()); | |
1217 delete network; | |
1218 } | |
1219 | |
1220 void NetworkLibraryImplBase::ForgetNetworksById( | |
1221 onc::ONCSource source, | |
1222 std::set<std::string> ids, | |
1223 bool if_found) { | |
1224 std::vector<std::string> to_be_forgotten; | |
1225 for (WifiNetworkVector::iterator i = remembered_wifi_networks_.begin(); | |
1226 i != remembered_wifi_networks_.end(); ++i) { | |
1227 WifiNetwork* wifi_network = *i; | |
1228 if (wifi_network->ui_data().onc_source() == source && | |
1229 if_found == (ids.find(wifi_network->unique_id()) != ids.end())) | |
1230 to_be_forgotten.push_back(wifi_network->service_path()); | |
1231 } | |
1232 | |
1233 for (VirtualNetworkVector::iterator i = remembered_virtual_networks_.begin(); | |
1234 i != remembered_virtual_networks_.end(); ++i) { | |
1235 VirtualNetwork* virtual_network = *i; | |
1236 if (virtual_network->ui_data().onc_source() == source && | |
1237 if_found == (ids.find(virtual_network->unique_id()) != ids.end())) | |
1238 to_be_forgotten.push_back(virtual_network->service_path()); | |
1239 } | |
1240 | |
1241 for (std::vector<std::string>::const_iterator i = to_be_forgotten.begin(); | |
1242 i != to_be_forgotten.end(); ++i) { | |
1243 ForgetNetwork(*i); | |
1244 } | |
1245 } | |
1246 | |
1247 bool NetworkLibraryImplBase::ValidateRememberedNetwork(Network* network) { | |
1248 std::pair<NetworkMap::iterator, bool> result = | |
1249 remembered_network_map_.insert( | |
1250 std::make_pair(network->service_path(), network)); | |
1251 DCHECK(result.second); // Should only get called with new network. | |
1252 | |
1253 // See if this is a policy-configured network that has meanwhile been removed. | |
1254 // This situation may arise when the full list of remembered networks is not | |
1255 // available to LoadOncNetworks(), which can happen due to the asynchronous | |
1256 // communication between shill and NetworkLibrary. Just tell shill to | |
1257 // delete the network now. | |
1258 const onc::ONCSource source = network->ui_data().onc_source(); | |
1259 if (source == onc::ONC_SOURCE_USER_POLICY || | |
1260 source == onc::ONC_SOURCE_DEVICE_POLICY) { | |
1261 NetworkSourceMap::const_iterator network_id_set( | |
1262 network_source_map_.find(source)); | |
1263 if (network_id_set != network_source_map_.end() && | |
1264 network_id_set->second.find(network->unique_id()) == | |
1265 network_id_set->second.end()) { | |
1266 DeleteRememberedNetwork(network->service_path()); | |
1267 return false; | |
1268 } | |
1269 } | |
1270 | |
1271 return true; | |
1272 } | |
1273 | |
1274 bool NetworkLibraryImplBase::ValidateAndAddRememberedNetwork(Network* network) { | |
1275 if (!ValidateRememberedNetwork(network)) | |
1276 return false; | |
1277 | |
1278 if (network->type() == TYPE_WIFI) { | |
1279 remembered_wifi_networks_.push_back( | |
1280 static_cast<WifiNetwork*>(network)); | |
1281 } else if (network->type() == TYPE_VPN) { | |
1282 remembered_virtual_networks_.push_back( | |
1283 static_cast<VirtualNetwork*>(network)); | |
1284 } else { | |
1285 NOTREACHED(); | |
1286 } | |
1287 | |
1288 VLOG(1) << "ValidateAndAddRememberedNetwork: " << network->service_path(); | |
1289 return true; | |
1290 } | |
1291 | |
1292 void NetworkLibraryImplBase::DeleteRememberedNetwork( | |
1293 const std::string& service_path) { | |
1294 NetworkMap::iterator found = remembered_network_map_.find(service_path); | |
1295 if (found == remembered_network_map_.end()) { | |
1296 LOG(WARNING) << "Attempt to delete non-existent remembered network: " | |
1297 << service_path; | |
1298 return; | |
1299 } | |
1300 Network* remembered_network = found->second; | |
1301 VLOG(1) << "Deleting remembered network: " | |
1302 << remembered_network->service_path(); | |
1303 | |
1304 // Update any associated network service before removing from profile | |
1305 // so that shill doesn't recreate the service (e.g. when we disconenct it). | |
1306 Network* network = FindNetworkByUniqueId(remembered_network->unique_id()); | |
1307 if (network) { | |
1308 // Clear the stored credentials for any forgotten networks. | |
1309 network->EraseCredentials(); | |
1310 network->ClearUIData(); | |
1311 SetProfileType(network, PROFILE_NONE); | |
1312 // Remove VPN from list of networks. | |
1313 if (network->type() == TYPE_VPN) | |
1314 CallRemoveNetwork(network); | |
1315 } else { | |
1316 // Network is not in service list. | |
1317 VLOG(2) << "Remembered Network not in service list: " | |
1318 << remembered_network->unique_id(); | |
1319 } | |
1320 | |
1321 // Delete remembered network from lists. | |
1322 remembered_network_map_.erase(found); | |
1323 | |
1324 if (remembered_network->type() == TYPE_WIFI) { | |
1325 WifiNetworkVector::iterator iter = std::find( | |
1326 remembered_wifi_networks_.begin(), | |
1327 remembered_wifi_networks_.end(), | |
1328 remembered_network); | |
1329 if (iter != remembered_wifi_networks_.end()) | |
1330 remembered_wifi_networks_.erase(iter); | |
1331 } else if (remembered_network->type() == TYPE_VPN) { | |
1332 VirtualNetworkVector::iterator iter = std::find( | |
1333 remembered_virtual_networks_.begin(), | |
1334 remembered_virtual_networks_.end(), | |
1335 remembered_network); | |
1336 if (iter != remembered_virtual_networks_.end()) | |
1337 remembered_virtual_networks_.erase(iter); | |
1338 } | |
1339 | |
1340 // Delete remembered network from all profiles it is in. | |
1341 for (NetworkProfileList::iterator iter = profile_list_.begin(); | |
1342 iter != profile_list_.end(); ++iter) { | |
1343 NetworkProfile& profile = *iter; | |
1344 NetworkProfile::ServiceList::iterator found = | |
1345 profile.services.find(remembered_network->service_path()); | |
1346 if (found != profile.services.end()) { | |
1347 VLOG(1) << "Deleting: " << remembered_network->service_path() | |
1348 << " From: " << profile.path; | |
1349 CallDeleteRememberedNetwork(profile.path, | |
1350 remembered_network->service_path()); | |
1351 profile.services.erase(found); | |
1352 } | |
1353 } | |
1354 | |
1355 // Remove the ONC blob for the network, if present. | |
1356 NetworkOncMap::iterator onc_map_entry = | |
1357 network_onc_map_.find(remembered_network->unique_id()); | |
1358 if (onc_map_entry != network_onc_map_.end()) { | |
1359 delete onc_map_entry->second; | |
1360 network_onc_map_.erase(onc_map_entry); | |
1361 } | |
1362 | |
1363 delete remembered_network; | |
1364 } | |
1365 | |
1366 //////////////////////////////////////////////////////////////////////////// | |
1367 | |
1368 void NetworkLibraryImplBase::ClearNetworks() { | |
1369 network_map_.clear(); | |
1370 network_unique_id_map_.clear(); | |
1371 ethernet_ = NULL; | |
1372 active_wifi_ = NULL; | |
1373 active_cellular_ = NULL; | |
1374 active_wimax_ = NULL; | |
1375 active_virtual_ = NULL; | |
1376 wifi_networks_.clear(); | |
1377 cellular_networks_.clear(); | |
1378 wimax_networks_.clear(); | |
1379 virtual_networks_.clear(); | |
1380 } | |
1381 | |
1382 void NetworkLibraryImplBase::DeleteRememberedNetworks() { | |
1383 STLDeleteValues(&remembered_network_map_); | |
1384 remembered_network_map_.clear(); | |
1385 remembered_wifi_networks_.clear(); | |
1386 remembered_virtual_networks_.clear(); | |
1387 } | |
1388 | |
1389 void NetworkLibraryImplBase::DeleteDevice(const std::string& device_path) { | |
1390 NetworkDeviceMap::iterator found = device_map_.find(device_path); | |
1391 if (found == device_map_.end()) { | |
1392 LOG(WARNING) << "Attempt to delete non-existent device: " | |
1393 << device_path; | |
1394 return; | |
1395 } | |
1396 VLOG(2) << " Deleting device: " << device_path; | |
1397 NetworkDevice* device = found->second; | |
1398 device_map_.erase(found); | |
1399 delete device; | |
1400 DeleteDeviceFromDeviceObserversMap(device_path); | |
1401 } | |
1402 | |
1403 //////////////////////////////////////////////////////////////////////////// | |
1404 | |
1405 void NetworkLibraryImplBase::AddProfile(const std::string& profile_path, | |
1406 NetworkProfileType profile_type) { | |
1407 VLOG(1) << "Adding profile " << profile_path; | |
1408 profile_list_.push_back(NetworkProfile(profile_path, profile_type)); | |
1409 // Check to see if we connected to any networks before a user profile was | |
1410 // available (i.e. before login), but unchecked the "Share" option (i.e. | |
1411 // the desired pofile is the user profile). Move these networks to the | |
1412 // user profile when it becomes available. | |
1413 if (profile_type == PROFILE_USER && !user_networks_.empty()) { | |
1414 for (std::list<std::string>::iterator iter2 = user_networks_.begin(); | |
1415 iter2 != user_networks_.end(); ++iter2) { | |
1416 Network* network = FindNetworkByPath(*iter2); | |
1417 if (network && network->profile_path() != profile_path) | |
1418 network->SetProfilePath(profile_path); | |
1419 } | |
1420 user_networks_.clear(); | |
1421 } | |
1422 } | |
1423 | |
1424 NetworkLibraryImplBase::NetworkProfile* | |
1425 NetworkLibraryImplBase::GetProfileForType(NetworkProfileType type) { | |
1426 for (NetworkProfileList::iterator iter = profile_list_.begin(); | |
1427 iter != profile_list_.end(); ++iter) { | |
1428 NetworkProfile& profile = *iter; | |
1429 if (profile.type == type) | |
1430 return &profile; | |
1431 } | |
1432 return NULL; | |
1433 } | |
1434 | |
1435 void NetworkLibraryImplBase::SetProfileType( | |
1436 Network* network, NetworkProfileType type) { | |
1437 if (type == PROFILE_NONE) { | |
1438 network->SetProfilePath(std::string()); | |
1439 network->set_profile_type(PROFILE_NONE); | |
1440 } else { | |
1441 std::string profile_path = GetProfilePath(type); | |
1442 if (!profile_path.empty()) { | |
1443 network->SetProfilePath(profile_path); | |
1444 network->set_profile_type(type); | |
1445 } else { | |
1446 LOG(WARNING) << "Profile type not found: " << type; | |
1447 network->set_profile_type(PROFILE_NONE); | |
1448 } | |
1449 } | |
1450 } | |
1451 | |
1452 void NetworkLibraryImplBase::SetProfileTypeFromPath(Network* network) { | |
1453 if (network->profile_path().empty()) { | |
1454 network->set_profile_type(PROFILE_NONE); | |
1455 return; | |
1456 } | |
1457 for (NetworkProfileList::iterator iter = profile_list_.begin(); | |
1458 iter != profile_list_.end(); ++iter) { | |
1459 NetworkProfile& profile = *iter; | |
1460 if (profile.path == network->profile_path()) { | |
1461 network->set_profile_type(profile.type); | |
1462 return; | |
1463 } | |
1464 } | |
1465 LOG(WARNING) << "Profile path not found: " << network->profile_path(); | |
1466 network->set_profile_type(PROFILE_NONE); | |
1467 } | |
1468 | |
1469 std::string NetworkLibraryImplBase::GetProfilePath(NetworkProfileType type) { | |
1470 std::string profile_path; | |
1471 NetworkProfile* profile = GetProfileForType(type); | |
1472 if (profile) | |
1473 profile_path = profile->path; | |
1474 return profile_path; | |
1475 } | |
1476 | |
1477 //////////////////////////////////////////////////////////////////////////// | |
1478 // Notifications. | |
1479 | |
1480 void NetworkLibraryImplBase::NotifyNetworkProfileObservers() { | |
1481 FOR_EACH_OBSERVER(NetworkProfileObserver, | |
1482 network_profile_observers_, | |
1483 OnProfileListChanged()); | |
1484 } | |
1485 | |
1486 // We call this any time something in NetworkLibrary changes. | |
1487 // TODO(stevenjb): We should consider breaking this into multiple | |
1488 // notifications, e.g. connection state, devices, services, etc. | |
1489 void NetworkLibraryImplBase::NotifyNetworkManagerChanged(bool force_update) { | |
1490 // Cancel any pending signals. | |
1491 notify_manager_weak_factory_.InvalidateWeakPtrs(); | |
1492 if (force_update) { | |
1493 // Signal observers now. | |
1494 SignalNetworkManagerObservers(); | |
1495 } else { | |
1496 // Schedule a delayed signal to limit the frequency of notifications. | |
1497 BrowserThread::PostDelayedTask( | |
1498 BrowserThread::UI, | |
1499 FROM_HERE, | |
1500 base::Bind(&NetworkLibraryImplBase::SignalNetworkManagerObservers, | |
1501 notify_manager_weak_factory_.GetWeakPtr()), | |
1502 base::TimeDelta::FromMilliseconds(kNetworkNotifyDelayMs)); | |
1503 } | |
1504 } | |
1505 | |
1506 void NetworkLibraryImplBase::SignalNetworkManagerObservers() { | |
1507 FOR_EACH_OBSERVER(NetworkManagerObserver, | |
1508 network_manager_observers_, | |
1509 OnNetworkManagerChanged(this)); | |
1510 // Clear notification flags. | |
1511 for (NetworkMap::iterator iter = network_map_.begin(); | |
1512 iter != network_map_.end(); ++iter) { | |
1513 iter->second->set_notify_failure(false); | |
1514 } | |
1515 } | |
1516 | |
1517 void NetworkLibraryImplBase::NotifyNetworkChanged(const Network* network) { | |
1518 DCHECK(network); | |
1519 VLOG(2) << "Network changed: " << network->name(); | |
1520 NetworkObserverMap::const_iterator iter = network_observers_.find( | |
1521 network->service_path()); | |
1522 if (iter != network_observers_.end()) { | |
1523 FOR_EACH_OBSERVER(NetworkObserver, | |
1524 *(iter->second), | |
1525 OnNetworkChanged(this, network)); | |
1526 } else if (IsCros()) { | |
1527 LOG(ERROR) << "Unexpected signal for unobserved network: " | |
1528 << network->name(); | |
1529 } | |
1530 } | |
1531 | |
1532 void NetworkLibraryImplBase::NotifyNetworkDeviceChanged( | |
1533 NetworkDevice* device, PropertyIndex index) { | |
1534 DCHECK(device); | |
1535 VLOG(2) << "Network device changed: " << device->name(); | |
1536 NetworkDeviceObserverMap::const_iterator iter = | |
1537 network_device_observers_.find(device->device_path()); | |
1538 if (iter != network_device_observers_.end()) { | |
1539 NetworkDeviceObserverList* device_observer_list = iter->second; | |
1540 if (index == PROPERTY_INDEX_FOUND_NETWORKS) { | |
1541 FOR_EACH_OBSERVER(NetworkDeviceObserver, | |
1542 *device_observer_list, | |
1543 OnNetworkDeviceFoundNetworks(this, device)); | |
1544 } else if (index == PROPERTY_INDEX_SIM_LOCK) { | |
1545 FOR_EACH_OBSERVER(NetworkDeviceObserver, | |
1546 *device_observer_list, | |
1547 OnNetworkDeviceSimLockChanged(this, device)); | |
1548 } | |
1549 } else { | |
1550 LOG(ERROR) << "Unexpected signal for unobserved device: " | |
1551 << device->name(); | |
1552 } | |
1553 } | |
1554 | |
1555 void NetworkLibraryImplBase::NotifyPinOperationCompleted( | |
1556 PinOperationError error) { | |
1557 FOR_EACH_OBSERVER(PinOperationObserver, | |
1558 pin_operation_observers_, | |
1559 OnPinOperationCompleted(this, error)); | |
1560 sim_operation_ = SIM_OPERATION_NONE; | |
1561 } | |
1562 | |
1563 ////////////////////////////////////////////////////////////////////////////// | |
1564 // Pin related functions. | |
1565 | |
1566 void NetworkLibraryImplBase::GetTpmInfo() { | |
1567 // Avoid making multiple synchronous D-Bus calls to cryptohome by caching | |
1568 // the TPM PIN, which does not change during a session. | |
1569 if (tpm_pin_.empty()) { | |
1570 if (crypto::IsTPMTokenReady()) { | |
1571 std::string tpm_label; | |
1572 crypto::GetTPMTokenInfo(&tpm_label, &tpm_pin_); | |
1573 // VLOG(1) << "TPM Label: " << tpm_label << ", PIN: " << tpm_pin_; | |
1574 // TODO(stevenjb): GetTPMTokenInfo returns a label, but the network | |
1575 // code expects a slot ID. See chromium-os:17998. | |
1576 // For now, use a hard coded, well known slot instead. | |
1577 const char kHardcodedTpmSlot[] = "0"; | |
1578 tpm_slot_ = kHardcodedTpmSlot; | |
1579 } else if (IsCros()) { | |
1580 LOG(WARNING) << "TPM token not ready"; | |
1581 } | |
1582 } | |
1583 } | |
1584 | |
1585 const std::string& NetworkLibraryImplBase::GetTpmSlot() { | |
1586 GetTpmInfo(); | |
1587 return tpm_slot_; | |
1588 } | |
1589 | |
1590 const std::string& NetworkLibraryImplBase::GetTpmPin() { | |
1591 GetTpmInfo(); | |
1592 return tpm_pin_; | |
1593 } | |
1594 | |
1595 } // namespace chromeos | |
OLD | NEW |