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.
5 #include "chromeos/network/network_state_handler.h"
8 #include "base/format_macros.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/metrics/histogram.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/values.h"
17 #include "chromeos/network/device_state.h"
18 #include "chromeos/network/managed_state.h"
19 #include "chromeos/network/network_event_log.h"
20 #include "chromeos/network/network_state.h"
21 #include "chromeos/network/network_state_handler_observer.h"
22 #include "chromeos/network/shill_property_handler.h"
23 #include "third_party/cros_system_api/dbus/service_constants.h"
29 bool ConnectionStateChanged(NetworkState
* network
,
30 const std::string
& prev_connection_state
) {
31 return (network
->connection_state() != prev_connection_state
) &&
32 (network
->connection_state() != shill::kStateIdle
||
33 !prev_connection_state
.empty());
36 std::string
GetManagedStateLogType(const ManagedState
* state
) {
37 switch (state
->managed_type()) {
38 case ManagedState::MANAGED_TYPE_NETWORK
:
40 case ManagedState::MANAGED_TYPE_DEVICE
:
47 std::string
GetLogName(const ManagedState
* state
) {
50 return base::StringPrintf("%s (%s)", state
->name().c_str(),
51 state
->path().c_str());
56 const char NetworkStateHandler::kDefaultCheckPortalList
[] =
57 "ethernet,wifi,cellular";
59 NetworkStateHandler::NetworkStateHandler()
60 : network_list_sorted_(false) {
63 NetworkStateHandler::~NetworkStateHandler() {
64 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
, IsShuttingDown());
65 STLDeleteContainerPointers(network_list_
.begin(), network_list_
.end());
66 STLDeleteContainerPointers(device_list_
.begin(), device_list_
.end());
69 void NetworkStateHandler::InitShillPropertyHandler() {
70 shill_property_handler_
.reset(new internal::ShillPropertyHandler(this));
71 shill_property_handler_
->Init();
75 NetworkStateHandler
* NetworkStateHandler::InitializeForTest() {
76 NetworkStateHandler
* handler
= new NetworkStateHandler();
77 handler
->InitShillPropertyHandler();
81 void NetworkStateHandler::AddObserver(
82 NetworkStateHandlerObserver
* observer
,
83 const tracked_objects::Location
& from_here
) {
84 observers_
.AddObserver(observer
);
85 network_event_log::internal::AddEntry(
86 from_here
.file_name(), from_here
.line_number(),
87 network_event_log::LOG_LEVEL_DEBUG
,
88 "NetworkStateHandler::AddObserver", "");
91 void NetworkStateHandler::RemoveObserver(
92 NetworkStateHandlerObserver
* observer
,
93 const tracked_objects::Location
& from_here
) {
94 observers_
.RemoveObserver(observer
);
95 network_event_log::internal::AddEntry(
96 from_here
.file_name(), from_here
.line_number(),
97 network_event_log::LOG_LEVEL_DEBUG
,
98 "NetworkStateHandler::RemoveObserver", "");
101 NetworkStateHandler::TechnologyState
NetworkStateHandler::GetTechnologyState(
102 const NetworkTypePattern
& type
) const {
103 std::string technology
= GetTechnologyForType(type
);
104 TechnologyState state
;
105 if (shill_property_handler_
->IsTechnologyEnabled(technology
))
106 state
= TECHNOLOGY_ENABLED
;
107 else if (shill_property_handler_
->IsTechnologyEnabling(technology
))
108 state
= TECHNOLOGY_ENABLING
;
109 else if (shill_property_handler_
->IsTechnologyUninitialized(technology
))
110 state
= TECHNOLOGY_UNINITIALIZED
;
111 else if (shill_property_handler_
->IsTechnologyAvailable(technology
))
112 state
= TECHNOLOGY_AVAILABLE
;
114 state
= TECHNOLOGY_UNAVAILABLE
;
115 VLOG(2) << "GetTechnologyState: " << type
.ToDebugString() << " = " << state
;
119 void NetworkStateHandler::SetTechnologyEnabled(
120 const NetworkTypePattern
& type
,
122 const network_handler::ErrorCallback
& error_callback
) {
123 ScopedVector
<std::string
> technologies
= GetTechnologiesForType(type
);
124 for (ScopedVector
<std::string
>::iterator it
= technologies
.begin();
125 it
!= technologies
.end(); ++it
) {
126 std::string
* technology
= *it
;
128 if (!shill_property_handler_
->IsTechnologyAvailable(*technology
))
130 NET_LOG_USER("SetTechnologyEnabled",
131 base::StringPrintf("%s:%d", technology
->c_str(), enabled
));
132 shill_property_handler_
->SetTechnologyEnabled(
133 *technology
, enabled
, error_callback
);
135 // Signal Device/Technology state changed.
136 NotifyDeviceListChanged();
139 const DeviceState
* NetworkStateHandler::GetDeviceState(
140 const std::string
& device_path
) const {
141 const DeviceState
* device
= GetModifiableDeviceState(device_path
);
142 if (device
&& !device
->update_received())
147 const DeviceState
* NetworkStateHandler::GetDeviceStateByType(
148 const NetworkTypePattern
& type
) const {
149 for (ManagedStateList::const_iterator iter
= device_list_
.begin();
150 iter
!= device_list_
.end(); ++iter
) {
151 ManagedState
* device
= *iter
;
152 if (!device
->update_received())
154 if (device
->Matches(type
))
155 return device
->AsDeviceState();
160 bool NetworkStateHandler::GetScanningByType(
161 const NetworkTypePattern
& type
) const {
162 for (ManagedStateList::const_iterator iter
= device_list_
.begin();
163 iter
!= device_list_
.end(); ++iter
) {
164 const DeviceState
* device
= (*iter
)->AsDeviceState();
166 if (!device
->update_received())
168 if (device
->Matches(type
) && device
->scanning())
174 const NetworkState
* NetworkStateHandler::GetNetworkState(
175 const std::string
& service_path
) const {
176 const NetworkState
* network
= GetModifiableNetworkState(service_path
);
177 if (network
&& !network
->update_received())
182 const NetworkState
* NetworkStateHandler::DefaultNetwork() const {
183 if (default_network_path_
.empty())
185 return GetNetworkState(default_network_path_
);
188 const NetworkState
* NetworkStateHandler::ConnectedNetworkByType(
189 const NetworkTypePattern
& type
) const {
190 // Active networks are always listed first by Shill so no need to sort.
191 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
192 iter
!= network_list_
.end(); ++iter
) {
193 const NetworkState
* network
= (*iter
)->AsNetworkState();
195 if (!network
->update_received())
197 if (!network
->IsConnectedState())
198 break; // Connected networks are listed first.
199 if (network
->Matches(type
))
205 const NetworkState
* NetworkStateHandler::ConnectingNetworkByType(
206 const NetworkTypePattern
& type
) const {
207 // Active networks are always listed first by Shill so no need to sort.
208 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
209 iter
!= network_list_
.end(); ++iter
) {
210 const NetworkState
* network
= (*iter
)->AsNetworkState();
212 if (!network
->update_received() || network
->IsConnectedState())
214 if (!network
->IsConnectingState())
215 break; // Connected and connecting networks are listed first.
216 if (network
->Matches(type
))
222 const NetworkState
* NetworkStateHandler::FirstNetworkByType(
223 const NetworkTypePattern
& type
) {
224 if (!network_list_sorted_
)
225 SortNetworkList(); // Sort to ensure visible networks are listed first.
226 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
227 iter
!= network_list_
.end(); ++iter
) {
228 const NetworkState
* network
= (*iter
)->AsNetworkState();
230 if (!network
->update_received())
232 if (!network
->visible())
234 if (network
->Matches(type
))
240 std::string
NetworkStateHandler::FormattedHardwareAddressForType(
241 const NetworkTypePattern
& type
) const {
242 const DeviceState
* device
= NULL
;
243 const NetworkState
* network
= ConnectedNetworkByType(type
);
245 device
= GetDeviceState(network
->device_path());
247 device
= GetDeviceStateByType(type
);
249 return std::string();
250 return network_util::FormattedMacAddress(device
->mac_address());
253 void NetworkStateHandler::GetVisibleNetworkListByType(
254 const NetworkTypePattern
& type
,
255 NetworkStateList
* list
) {
256 GetNetworkListByType(type
,
257 false /* configured_only */,
258 true /* visible_only */,
263 void NetworkStateHandler::GetVisibleNetworkList(NetworkStateList
* list
) {
264 GetVisibleNetworkListByType(NetworkTypePattern::Default(), list
);
267 void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern
& type
,
268 bool configured_only
,
271 NetworkStateList
* list
) {
275 // Sort the network list if necessary.
276 if (!network_list_sorted_
)
278 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
279 iter
!= network_list_
.end(); ++iter
) {
280 const NetworkState
* network
= (*iter
)->AsNetworkState();
282 if (!network
->update_received() || !network
->Matches(type
))
284 if (configured_only
&& !network
->IsInProfile())
286 if (visible_only
&& !network
->visible())
288 list
->push_back(network
);
289 if (limit
> 0 && ++count
>= limit
)
294 const NetworkState
* NetworkStateHandler::GetNetworkStateFromServicePath(
295 const std::string
& service_path
,
296 bool configured_only
) const {
297 ManagedState
* managed
=
298 GetModifiableManagedState(&network_list_
, service_path
);
301 const NetworkState
* network
= managed
->AsNetworkState();
303 if (!network
->update_received() ||
304 (configured_only
&& !network
->IsInProfile())) {
310 const NetworkState
* NetworkStateHandler::GetNetworkStateFromGuid(
311 const std::string
& guid
) const {
312 DCHECK(!guid
.empty());
313 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
314 iter
!= network_list_
.end(); ++iter
) {
315 const NetworkState
* network
= (*iter
)->AsNetworkState();
316 if (network
->guid() == guid
)
322 void NetworkStateHandler::GetDeviceList(DeviceStateList
* list
) const {
323 GetDeviceListByType(NetworkTypePattern::Default(), list
);
326 void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern
& type
,
327 DeviceStateList
* list
) const {
330 for (ManagedStateList::const_iterator iter
= device_list_
.begin();
331 iter
!= device_list_
.end(); ++iter
) {
332 const DeviceState
* device
= (*iter
)->AsDeviceState();
334 if (device
->update_received() && device
->Matches(type
))
335 list
->push_back(device
);
339 void NetworkStateHandler::RequestScan() const {
340 NET_LOG_USER("RequestScan", "");
341 shill_property_handler_
->RequestScan();
344 void NetworkStateHandler::WaitForScan(const std::string
& type
,
345 const base::Closure
& callback
) {
346 scan_complete_callbacks_
[type
].push_back(callback
);
347 if (!GetScanningByType(NetworkTypePattern::Primitive(type
)))
351 void NetworkStateHandler::ConnectToBestWifiNetwork() {
352 NET_LOG_USER("ConnectToBestWifiNetwork", "");
353 WaitForScan(shill::kTypeWifi
,
354 base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices
,
355 shill_property_handler_
->AsWeakPtr()));
358 void NetworkStateHandler::RequestUpdateForNetwork(
359 const std::string
& service_path
) {
360 NetworkState
* network
= GetModifiableNetworkState(service_path
);
362 network
->set_update_requested(true);
363 NET_LOG_EVENT("RequestUpdate", service_path
);
364 shill_property_handler_
->RequestProperties(
365 ManagedState::MANAGED_TYPE_NETWORK
, service_path
);
368 void NetworkStateHandler::ClearLastErrorForNetwork(
369 const std::string
& service_path
) {
370 NetworkState
* network
= GetModifiableNetworkState(service_path
);
372 network
->clear_last_error();
375 void NetworkStateHandler::SetCheckPortalList(
376 const std::string
& check_portal_list
) {
377 NET_LOG_EVENT("SetCheckPortalList", check_portal_list
);
378 shill_property_handler_
->SetCheckPortalList(check_portal_list
);
381 const NetworkState
* NetworkStateHandler::GetEAPForEthernet(
382 const std::string
& service_path
) {
383 const NetworkState
* network
= GetNetworkState(service_path
);
385 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path
);
388 if (network
->type() != shill::kTypeEthernet
) {
389 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path
);
392 if (!network
->IsConnectedState())
395 // The same EAP service is shared for all ethernet services/devices.
396 // However EAP is used/enabled per device and only if the connection was
397 // successfully established.
398 const DeviceState
* device
= GetDeviceState(network
->device_path());
402 base::StringPrintf("Unknown device %s of connected ethernet service %s",
403 network
->device_path().c_str(),
404 service_path
.c_str()));
407 if (!device
->eap_authentication_completed())
410 NetworkStateList list
;
411 GetNetworkListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap
),
412 true /* configured_only */,
413 false /* visible_only */,
417 NET_LOG_ERROR("GetEAPForEthernet",
419 "Ethernet service %s connected using EAP, but no "
420 "EAP service found.",
421 service_path
.c_str()));
427 //------------------------------------------------------------------------------
428 // ShillPropertyHandler::Delegate overrides
430 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type
,
431 const base::ListValue
& entries
) {
432 ManagedStateList
* managed_list
= GetManagedList(type
);
433 NET_LOG_DEBUG("UpdateManagedList: " + ManagedState::TypeToString(type
),
434 base::StringPrintf("%" PRIuS
, entries
.GetSize()));
435 // Create a map of existing entries. Assumes all entries in |managed_list|
437 typedef std::map
<std::string
, ManagedState
*> ManagedMap
;
438 ManagedMap managed_map
;
439 for (ManagedStateList::iterator iter
= managed_list
->begin();
440 iter
!= managed_list
->end(); ++iter
) {
441 ManagedState
* managed
= *iter
;
442 DCHECK(!ContainsKey(managed_map
, managed
->path()));
443 managed_map
[managed
->path()] = managed
;
445 // Clear the list (pointers are temporarily owned by managed_map).
446 managed_list
->clear();
447 // Updates managed_list and request updates for new entries.
448 std::set
<std::string
> list_entries
;
449 for (base::ListValue::const_iterator iter
= entries
.begin();
450 iter
!= entries
.end(); ++iter
) {
452 (*iter
)->GetAsString(&path
);
453 if (path
.empty() || path
== shill::kFlimflamServicePath
) {
454 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type
), path
);
457 ManagedMap::iterator found
= managed_map
.find(path
);
458 if (found
== managed_map
.end()) {
459 if (list_entries
.count(path
) != 0) {
460 NET_LOG_ERROR("Duplicate entry in list", path
);
463 ManagedState
* managed
= ManagedState::Create(type
, path
);
464 managed_list
->push_back(managed
);
466 managed_list
->push_back(found
->second
);
467 managed_map
.erase(found
);
469 list_entries
.insert(path
);
471 // Delete any remaining entries in managed_map.
472 STLDeleteContainerPairSecondPointers(managed_map
.begin(), managed_map
.end());
475 void NetworkStateHandler::ProfileListChanged() {
476 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
477 for (ManagedStateList::iterator iter
= network_list_
.begin();
478 iter
!= network_list_
.end(); ++iter
) {
479 NetworkState
* network
= (*iter
)->AsNetworkState();
481 shill_property_handler_
->RequestProperties(
482 ManagedState::MANAGED_TYPE_NETWORK
, network
->path());
486 void NetworkStateHandler::UpdateManagedStateProperties(
487 ManagedState::ManagedType type
,
488 const std::string
& path
,
489 const base::DictionaryValue
& properties
) {
490 ManagedStateList
* managed_list
= GetManagedList(type
);
491 ManagedState
* managed
= GetModifiableManagedState(managed_list
, path
);
493 // The network has been removed from the list of networks.
494 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path
);
497 managed
->set_update_received();
499 std::string desc
= GetManagedStateLogType(managed
) + " Properties Received";
500 NET_LOG_DEBUG(desc
, GetLogName(managed
));
502 if (type
== ManagedState::MANAGED_TYPE_NETWORK
) {
503 UpdateNetworkStateProperties(managed
->AsNetworkState(), properties
);
506 for (base::DictionaryValue::Iterator
iter(properties
);
507 !iter
.IsAtEnd(); iter
.Advance()) {
508 managed
->PropertyChanged(iter
.key(), iter
.value());
510 managed
->InitialPropertiesReceived(properties
);
512 managed
->set_update_requested(false);
515 void NetworkStateHandler::UpdateNetworkStateProperties(
516 NetworkState
* network
,
517 const base::DictionaryValue
& properties
) {
519 bool network_property_updated
= false;
520 std::string prev_connection_state
= network
->connection_state();
521 for (base::DictionaryValue::Iterator
iter(properties
);
522 !iter
.IsAtEnd(); iter
.Advance()) {
523 if (network
->PropertyChanged(iter
.key(), iter
.value()))
524 network_property_updated
= true;
526 network_property_updated
|= network
->InitialPropertiesReceived(properties
);
528 network_list_sorted_
= false;
530 // Notify observers of NetworkState changes.
531 if (network_property_updated
|| network
->update_requested()) {
532 // Signal connection state changed after all properties have been updated.
533 if (ConnectionStateChanged(network
, prev_connection_state
))
534 OnNetworkConnectionStateChanged(network
);
535 NET_LOG_EVENT("NetworkPropertiesUpdated", GetLogName(network
));
536 NotifyNetworkPropertiesUpdated(network
);
540 void NetworkStateHandler::UpdateNetworkServiceProperty(
541 const std::string
& service_path
,
542 const std::string
& key
,
543 const base::Value
& value
) {
544 bool changed
= false;
545 NetworkState
* network
= GetModifiableNetworkState(service_path
);
548 std::string prev_connection_state
= network
->connection_state();
549 std::string prev_profile_path
= network
->profile_path();
550 changed
|= network
->PropertyChanged(key
, value
);
554 if (key
== shill::kStateProperty
|| key
== shill::kVisibleProperty
) {
555 network_list_sorted_
= false;
556 if (ConnectionStateChanged(network
, prev_connection_state
)) {
557 OnNetworkConnectionStateChanged(network
);
558 // If the connection state changes, other properties such as IPConfig
559 // may have changed, so request a full update.
560 RequestUpdateForNetwork(service_path
);
563 std::string value_str
;
564 value
.GetAsString(&value_str
);
565 // Some property changes are noisy and not interesting:
566 // * Wifi SignalStrength
567 // * WifiFrequencyList updates
568 // * Device property changes to "/" (occurs before a service is removed)
569 if (key
!= shill::kSignalStrengthProperty
&&
570 key
!= shill::kWifiFrequencyListProperty
&&
571 (key
!= shill::kDeviceProperty
|| value_str
!= "/")) {
572 std::string log_event
= "NetworkPropertyUpdated";
573 // Trigger a default network update for interesting changes only.
574 if (network
->path() == default_network_path_
) {
575 NotifyDefaultNetworkChanged(network
);
576 log_event
= "Default" + log_event
;
579 std::string detail
= network
->name() + "." + key
;
580 detail
+= " = " + network_event_log::ValueAsString(value
);
581 network_event_log::LogLevel log_level
;
582 if (key
== shill::kErrorProperty
|| key
== shill::kErrorDetailsProperty
) {
583 log_level
= network_event_log::LOG_LEVEL_ERROR
;
585 log_level
= network_event_log::LOG_LEVEL_EVENT
;
587 NET_LOG_LEVEL(log_level
, log_event
, detail
);
591 // All property updates signal 'NetworkPropertiesUpdated'.
592 NotifyNetworkPropertiesUpdated(network
);
594 // If added to a Profile, request a full update so that a NetworkState
596 if (prev_profile_path
.empty() && !network
->profile_path().empty())
597 RequestUpdateForNetwork(service_path
);
600 void NetworkStateHandler::UpdateDeviceProperty(const std::string
& device_path
,
601 const std::string
& key
,
602 const base::Value
& value
) {
603 DeviceState
* device
= GetModifiableDeviceState(device_path
);
606 if (!device
->PropertyChanged(key
, value
))
609 std::string detail
= device
->name() + "." + key
;
610 detail
+= " = " + network_event_log::ValueAsString(value
);
611 NET_LOG_EVENT("DevicePropertyUpdated", detail
);
613 NotifyDeviceListChanged();
614 NotifyDevicePropertiesUpdated(device
);
616 if (key
== shill::kScanningProperty
&& device
->scanning() == false)
617 ScanCompleted(device
->type());
618 if (key
== shill::kEapAuthenticationCompletedProperty
) {
619 // Notify a change for each Ethernet service using this device.
620 NetworkStateList ethernet_services
;
621 GetNetworkListByType(NetworkTypePattern::Ethernet(),
622 false /* configured_only */,
623 false /* visible_only */,
626 for (NetworkStateList::const_iterator it
= ethernet_services
.begin();
627 it
!= ethernet_services
.end(); ++it
) {
628 const NetworkState
* ethernet_service
= *it
;
629 if (ethernet_service
->update_received() ||
630 ethernet_service
->device_path() != device
->path()) {
633 RequestUpdateForNetwork(ethernet_service
->path());
638 void NetworkStateHandler::UpdateIPConfigProperties(
639 ManagedState::ManagedType type
,
640 const std::string
& path
,
641 const std::string
& ip_config_path
,
642 const base::DictionaryValue
& properties
) {
643 if (type
== ManagedState::MANAGED_TYPE_NETWORK
) {
644 NetworkState
* network
= GetModifiableNetworkState(path
);
647 network
->IPConfigPropertiesChanged(properties
);
648 NotifyNetworkPropertiesUpdated(network
);
649 if (network
->path() == default_network_path_
)
650 NotifyDefaultNetworkChanged(network
);
651 } else if (type
== ManagedState::MANAGED_TYPE_DEVICE
) {
652 DeviceState
* device
= GetModifiableDeviceState(path
);
655 device
->IPConfigPropertiesChanged(ip_config_path
, properties
);
656 NotifyDevicePropertiesUpdated(device
);
657 if (!default_network_path_
.empty()) {
658 const NetworkState
* default_network
=
659 GetNetworkState(default_network_path_
);
660 if (default_network
&& default_network
->device_path() == path
)
661 NotifyDefaultNetworkChanged(default_network
);
666 void NetworkStateHandler::CheckPortalListChanged(
667 const std::string
& check_portal_list
) {
668 check_portal_list_
= check_portal_list
;
671 void NetworkStateHandler::TechnologyListChanged() {
672 // Eventually we would like to replace Technology state with Device state.
673 // For now, treat technology state changes as device list changes.
674 NotifyDeviceListChanged();
677 void NetworkStateHandler::ManagedStateListChanged(
678 ManagedState::ManagedType type
) {
679 if (type
== ManagedState::MANAGED_TYPE_NETWORK
) {
681 UpdateNetworkStats();
682 // Notify observers that the list of networks has changed.
683 NET_LOG_EVENT("NOTIFY:NetworkListChanged",
684 base::StringPrintf("Size:%" PRIuS
, network_list_
.size()));
685 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
686 NetworkListChanged());
687 } else if (type
== ManagedState::MANAGED_TYPE_DEVICE
) {
689 for (ManagedStateList::const_iterator iter
= device_list_
.begin();
690 iter
!= device_list_
.end(); ++iter
) {
691 if (iter
!= device_list_
.begin())
693 devices
+= (*iter
)->name();
695 NET_LOG_EVENT("DeviceList", devices
);
696 NotifyDeviceListChanged();
702 void NetworkStateHandler::SortNetworkList() {
703 // Note: usually active networks will precede inactive networks, however
704 // this may briefly be untrue during state transitions (e.g. a network may
705 // transition to idle before the list is updated).
706 ManagedStateList active
, non_wifi_visible
, wifi_visible
, hidden
, new_networks
;
707 for (ManagedStateList::iterator iter
= network_list_
.begin();
708 iter
!= network_list_
.end(); ++iter
) {
709 NetworkState
* network
= (*iter
)->AsNetworkState();
710 if (!network
->update_received()) {
711 new_networks
.push_back(network
);
714 if (network
->IsConnectedState() || network
->IsConnectingState()) {
715 active
.push_back(network
);
718 if (network
->visible()) {
719 if (NetworkTypePattern::WiFi().MatchesType(network
->type()))
720 wifi_visible
.push_back(network
);
722 non_wifi_visible
.push_back(network
);
724 hidden
.push_back(network
);
727 network_list_
.clear();
728 network_list_
.insert(network_list_
.end(), active
.begin(), active
.end());
729 network_list_
.insert(
730 network_list_
.end(), non_wifi_visible
.begin(), non_wifi_visible
.end());
731 network_list_
.insert(
732 network_list_
.end(), wifi_visible
.begin(), wifi_visible
.end());
733 network_list_
.insert(network_list_
.end(), hidden
.begin(), hidden
.end());
734 network_list_
.insert(
735 network_list_
.end(), new_networks
.begin(), new_networks
.end());
736 network_list_sorted_
= true;
739 void NetworkStateHandler::UpdateNetworkStats() {
740 size_t shared
= 0, unshared
= 0, visible
= 0;
741 for (ManagedStateList::iterator iter
= network_list_
.begin();
742 iter
!= network_list_
.end(); ++iter
) {
743 NetworkState
* network
= (*iter
)->AsNetworkState();
744 if (network
->visible())
746 if (network
->IsInProfile()) {
747 if (network
->IsPrivate())
753 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", visible
);
754 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared
);
755 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared
);
758 void NetworkStateHandler::DefaultNetworkServiceChanged(
759 const std::string
& service_path
) {
760 // Shill uses '/' for empty service path values; check explicitly for that.
761 const char* kEmptyServicePath
= "/";
762 std::string new_service_path
=
763 (service_path
!= kEmptyServicePath
) ? service_path
: "";
764 if (new_service_path
== default_network_path_
)
767 default_network_path_
= service_path
;
768 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_
);
769 const NetworkState
* network
= NULL
;
770 if (!default_network_path_
.empty()) {
771 network
= GetNetworkState(default_network_path_
);
773 // If NetworkState is not available yet, do not notify observers here,
774 // they will be notified when the state is received.
775 NET_LOG_DEBUG("Default NetworkState not available",
776 default_network_path_
);
780 if (network
&& !network
->IsConnectedState()) {
782 "DefaultNetwork is not connected: " + network
->connection_state(),
785 NotifyDefaultNetworkChanged(network
);
788 //------------------------------------------------------------------------------
791 void NetworkStateHandler::UpdateGuid(NetworkState
* network
) {
792 std::string specifier
= network
->GetSpecifier();
793 DCHECK(!specifier
.empty());
794 if (!network
->guid().empty()) {
795 // If the network is saved in a profile, remove the entry from the map.
796 // Otherwise ensure that the entry matches the specified GUID. (e.g. in
797 // case a visible network with a specified guid gets configured with a
799 if (network
->IsInProfile())
800 specifier_guid_map_
.erase(specifier
);
802 specifier_guid_map_
[specifier
] = network
->guid();
805 // Ensure that the NetworkState has a valid GUID.
807 SpecifierGuidMap::iterator iter
= specifier_guid_map_
.find(specifier
);
808 if (iter
!= specifier_guid_map_
.end()) {
811 guid
= base::GenerateGUID();
812 specifier_guid_map_
[specifier
] = guid
;
814 network
->SetGuid(guid
);
817 void NetworkStateHandler::NotifyDeviceListChanged() {
818 NET_LOG_DEBUG("NOTIFY:DeviceListChanged",
819 base::StringPrintf("Size:%" PRIuS
, device_list_
.size()));
820 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
821 DeviceListChanged());
824 DeviceState
* NetworkStateHandler::GetModifiableDeviceState(
825 const std::string
& device_path
) const {
826 ManagedState
* managed
= GetModifiableManagedState(&device_list_
, device_path
);
829 return managed
->AsDeviceState();
832 NetworkState
* NetworkStateHandler::GetModifiableNetworkState(
833 const std::string
& service_path
) const {
834 ManagedState
* managed
=
835 GetModifiableManagedState(&network_list_
, service_path
);
838 return managed
->AsNetworkState();
841 ManagedState
* NetworkStateHandler::GetModifiableManagedState(
842 const ManagedStateList
* managed_list
,
843 const std::string
& path
) const {
844 for (ManagedStateList::const_iterator iter
= managed_list
->begin();
845 iter
!= managed_list
->end(); ++iter
) {
846 ManagedState
* managed
= *iter
;
847 if (managed
->path() == path
)
853 NetworkStateHandler::ManagedStateList
* NetworkStateHandler::GetManagedList(
854 ManagedState::ManagedType type
) {
856 case ManagedState::MANAGED_TYPE_NETWORK
:
857 return &network_list_
;
858 case ManagedState::MANAGED_TYPE_DEVICE
:
859 return &device_list_
;
865 void NetworkStateHandler::OnNetworkConnectionStateChanged(
866 NetworkState
* network
) {
868 std::string event
= "NetworkConnectionStateChanged";
869 if (network
->path() == default_network_path_
) {
870 event
= "Default" + event
;
871 if (!network
->IsConnectedState()) {
873 "DefaultNetwork is not connected: " + network
->connection_state(),
875 default_network_path_
.clear();
877 NotifyDefaultNetworkChanged(NULL
);
880 NET_LOG_EVENT("NOTIFY:" + event
+ ": " + network
->connection_state(),
881 GetLogName(network
));
882 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
883 NetworkConnectionStateChanged(network
));
884 if (network
->path() == default_network_path_
)
885 NotifyDefaultNetworkChanged(network
);
888 void NetworkStateHandler::NotifyDefaultNetworkChanged(
889 const NetworkState
* default_network
) {
890 NET_LOG_EVENT("NOTIFY:DefaultNetworkChanged", GetLogName(default_network
));
891 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
892 DefaultNetworkChanged(default_network
));
895 void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
896 const NetworkState
* network
) {
897 NET_LOG_DEBUG("NOTIFY:NetworkPropertiesUpdated", GetLogName(network
));
898 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
899 NetworkPropertiesUpdated(network
));
902 void NetworkStateHandler::NotifyDevicePropertiesUpdated(
903 const DeviceState
* device
) {
904 NET_LOG_DEBUG("NOTIFY:DevicePropertiesUpdated", GetLogName(device
));
905 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
906 DevicePropertiesUpdated(device
));
909 void NetworkStateHandler::ScanCompleted(const std::string
& type
) {
910 size_t num_callbacks
= scan_complete_callbacks_
.count(type
);
911 NET_LOG_EVENT("ScanCompleted",
912 base::StringPrintf("%s:%" PRIuS
, type
.c_str(), num_callbacks
));
913 if (num_callbacks
== 0)
915 ScanCallbackList
& callback_list
= scan_complete_callbacks_
[type
];
916 for (ScanCallbackList::iterator iter
= callback_list
.begin();
917 iter
!= callback_list
.end(); ++iter
) {
920 scan_complete_callbacks_
.erase(type
);
923 std::string
NetworkStateHandler::GetTechnologyForType(
924 const NetworkTypePattern
& type
) const {
925 if (type
.MatchesType(shill::kTypeEthernet
))
926 return shill::kTypeEthernet
;
928 if (type
.MatchesType(shill::kTypeWifi
))
929 return shill::kTypeWifi
;
931 if (type
.Equals(NetworkTypePattern::Wimax()))
932 return shill::kTypeWimax
;
934 // Prefer Wimax over Cellular only if it's available.
935 if (type
.MatchesType(shill::kTypeWimax
) &&
936 shill_property_handler_
->IsTechnologyAvailable(shill::kTypeWimax
)) {
937 return shill::kTypeWimax
;
940 if (type
.MatchesType(shill::kTypeCellular
))
941 return shill::kTypeCellular
;
944 return std::string();
947 ScopedVector
<std::string
> NetworkStateHandler::GetTechnologiesForType(
948 const NetworkTypePattern
& type
) const {
949 ScopedVector
<std::string
> technologies
;
950 if (type
.MatchesType(shill::kTypeEthernet
))
951 technologies
.push_back(new std::string(shill::kTypeEthernet
));
952 if (type
.MatchesType(shill::kTypeWifi
))
953 technologies
.push_back(new std::string(shill::kTypeWifi
));
954 if (type
.MatchesType(shill::kTypeWimax
))
955 technologies
.push_back(new std::string(shill::kTypeWimax
));
956 if (type
.MatchesType(shill::kTypeCellular
))
957 technologies
.push_back(new std::string(shill::kTypeCellular
));
958 if (type
.MatchesType(shill::kTypeBluetooth
))
959 technologies
.push_back(new std::string(shill::kTypeBluetooth
));
960 if (type
.MatchesType(shill::kTypeVPN
))
961 technologies
.push_back(new std::string(shill::kTypeVPN
));
963 CHECK_GT(technologies
.size(), 0ul);
964 return technologies
.Pass();
967 } // namespace chromeos