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/json/json_string_value_serializer.h"
11 #include "base/json/json_writer.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/metrics/histogram.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/values.h"
19 #include "chromeos/network/device_state.h"
20 #include "chromeos/network/network_event_log.h"
21 #include "chromeos/network/network_state.h"
22 #include "chromeos/network/network_state_handler_observer.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 bool prev_is_captive_portal
) {
32 return ((network
->connection_state() != prev_connection_state
) &&
33 !((network
->connection_state() == shill::kStateIdle
) &&
34 prev_connection_state
.empty())) ||
35 (network
->is_captive_portal() != prev_is_captive_portal
);
38 std::string
GetManagedStateLogType(const ManagedState
* state
) {
39 switch (state
->managed_type()) {
40 case ManagedState::MANAGED_TYPE_NETWORK
:
42 case ManagedState::MANAGED_TYPE_DEVICE
:
49 std::string
GetLogName(const ManagedState
* state
) {
52 return base::StringPrintf("%s (%s)", state
->name().c_str(),
53 state
->path().c_str());
56 std::string
ValueAsString(const base::Value
& value
) {
58 base::JSONWriter::WriteWithOptions(
59 value
, base::JSONWriter::OPTIONS_OMIT_BINARY_VALUES
, &vstr
);
60 return vstr
.empty() ? "''" : vstr
;
65 const char NetworkStateHandler::kDefaultCheckPortalList
[] =
66 "ethernet,wifi,cellular";
68 NetworkStateHandler::NetworkStateHandler() : network_list_sorted_(false) {
71 NetworkStateHandler::~NetworkStateHandler() {
72 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
, IsShuttingDown());
73 STLDeleteContainerPointers(network_list_
.begin(), network_list_
.end());
74 STLDeleteContainerPointers(device_list_
.begin(), device_list_
.end());
77 void NetworkStateHandler::InitShillPropertyHandler() {
78 shill_property_handler_
.reset(new internal::ShillPropertyHandler(this));
79 shill_property_handler_
->Init();
83 NetworkStateHandler
* NetworkStateHandler::InitializeForTest() {
84 NetworkStateHandler
* handler
= new NetworkStateHandler();
85 handler
->InitShillPropertyHandler();
89 void NetworkStateHandler::AddObserver(
90 NetworkStateHandlerObserver
* observer
,
91 const tracked_objects::Location
& from_here
) {
92 observers_
.AddObserver(observer
);
93 device_event_log::AddEntry(from_here
.file_name(), from_here
.line_number(),
94 device_event_log::LOG_TYPE_NETWORK
,
95 device_event_log::LOG_LEVEL_DEBUG
,
96 "NetworkStateHandler::AddObserver");
99 void NetworkStateHandler::RemoveObserver(
100 NetworkStateHandlerObserver
* observer
,
101 const tracked_objects::Location
& from_here
) {
102 observers_
.RemoveObserver(observer
);
103 device_event_log::AddEntry(from_here
.file_name(), from_here
.line_number(),
104 device_event_log::LOG_TYPE_NETWORK
,
105 device_event_log::LOG_LEVEL_DEBUG
,
106 "NetworkStateHandler::RemoveObserver");
109 NetworkStateHandler::TechnologyState
NetworkStateHandler::GetTechnologyState(
110 const NetworkTypePattern
& type
) const {
111 std::string technology
= GetTechnologyForType(type
);
112 TechnologyState state
;
113 if (shill_property_handler_
->IsTechnologyEnabled(technology
))
114 state
= TECHNOLOGY_ENABLED
;
115 else if (shill_property_handler_
->IsTechnologyEnabling(technology
))
116 state
= TECHNOLOGY_ENABLING
;
117 else if (shill_property_handler_
->IsTechnologyUninitialized(technology
))
118 state
= TECHNOLOGY_UNINITIALIZED
;
119 else if (shill_property_handler_
->IsTechnologyAvailable(technology
))
120 state
= TECHNOLOGY_AVAILABLE
;
122 state
= TECHNOLOGY_UNAVAILABLE
;
123 VLOG(2) << "GetTechnologyState: " << type
.ToDebugString() << " = " << state
;
127 void NetworkStateHandler::SetTechnologyEnabled(
128 const NetworkTypePattern
& type
,
130 const network_handler::ErrorCallback
& error_callback
) {
131 ScopedVector
<std::string
> technologies
= GetTechnologiesForType(type
);
132 for (ScopedVector
<std::string
>::iterator it
= technologies
.begin();
133 it
!= technologies
.end(); ++it
) {
134 std::string
* technology
= *it
;
136 if (!shill_property_handler_
->IsTechnologyAvailable(*technology
))
138 NET_LOG_USER("SetTechnologyEnabled",
139 base::StringPrintf("%s:%d", technology
->c_str(), enabled
));
140 shill_property_handler_
->SetTechnologyEnabled(*technology
, enabled
,
143 // Signal Device/Technology state changed.
144 NotifyDeviceListChanged();
147 const DeviceState
* NetworkStateHandler::GetDeviceState(
148 const std::string
& device_path
) const {
149 const DeviceState
* device
= GetModifiableDeviceState(device_path
);
150 if (device
&& !device
->update_received())
155 const DeviceState
* NetworkStateHandler::GetDeviceStateByType(
156 const NetworkTypePattern
& type
) const {
157 for (ManagedStateList::const_iterator iter
= device_list_
.begin();
158 iter
!= device_list_
.end(); ++iter
) {
159 ManagedState
* device
= *iter
;
160 if (!device
->update_received())
162 if (device
->Matches(type
))
163 return device
->AsDeviceState();
168 bool NetworkStateHandler::GetScanningByType(
169 const NetworkTypePattern
& type
) const {
170 for (ManagedStateList::const_iterator iter
= device_list_
.begin();
171 iter
!= device_list_
.end(); ++iter
) {
172 const DeviceState
* device
= (*iter
)->AsDeviceState();
174 if (!device
->update_received())
176 if (device
->Matches(type
) && device
->scanning())
182 const NetworkState
* NetworkStateHandler::GetNetworkState(
183 const std::string
& service_path
) const {
184 const NetworkState
* network
= GetModifiableNetworkState(service_path
);
185 if (network
&& !network
->update_received())
190 const NetworkState
* NetworkStateHandler::DefaultNetwork() const {
191 if (default_network_path_
.empty())
193 return GetNetworkState(default_network_path_
);
196 const NetworkState
* NetworkStateHandler::ConnectedNetworkByType(
197 const NetworkTypePattern
& type
) const {
198 // Active networks are always listed first by Shill so no need to sort.
199 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
200 iter
!= network_list_
.end(); ++iter
) {
201 const NetworkState
* network
= (*iter
)->AsNetworkState();
203 if (!network
->update_received())
205 if (!network
->IsConnectedState())
206 break; // Connected networks are listed first.
207 if (network
->Matches(type
))
213 const NetworkState
* NetworkStateHandler::ConnectingNetworkByType(
214 const NetworkTypePattern
& type
) const {
215 // Active networks are always listed first by Shill so no need to sort.
216 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
217 iter
!= network_list_
.end(); ++iter
) {
218 const NetworkState
* network
= (*iter
)->AsNetworkState();
220 if (!network
->update_received() || network
->IsConnectedState())
222 if (!network
->IsConnectingState())
223 break; // Connected and connecting networks are listed first.
224 if (network
->Matches(type
))
230 const NetworkState
* NetworkStateHandler::FirstNetworkByType(
231 const NetworkTypePattern
& type
) {
232 if (!network_list_sorted_
)
233 SortNetworkList(); // Sort to ensure visible networks are listed first.
234 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
235 iter
!= network_list_
.end(); ++iter
) {
236 const NetworkState
* network
= (*iter
)->AsNetworkState();
238 if (!network
->update_received())
240 if (!network
->visible())
242 if (network
->Matches(type
))
248 std::string
NetworkStateHandler::FormattedHardwareAddressForType(
249 const NetworkTypePattern
& type
) const {
250 const DeviceState
* device
= nullptr;
251 const NetworkState
* network
= ConnectedNetworkByType(type
);
253 device
= GetDeviceState(network
->device_path());
255 device
= GetDeviceStateByType(type
);
257 return std::string();
258 return network_util::FormattedMacAddress(device
->mac_address());
261 void NetworkStateHandler::GetVisibleNetworkListByType(
262 const NetworkTypePattern
& type
,
263 NetworkStateList
* list
) {
264 GetNetworkListByType(type
, false /* configured_only */,
265 true /* visible_only */, 0 /* no limit */, list
);
268 void NetworkStateHandler::GetVisibleNetworkList(NetworkStateList
* list
) {
269 GetVisibleNetworkListByType(NetworkTypePattern::Default(), list
);
272 void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern
& type
,
273 bool configured_only
,
276 NetworkStateList
* list
) {
280 // Sort the network list if necessary.
281 if (!network_list_sorted_
)
283 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
284 iter
!= network_list_
.end(); ++iter
) {
285 const NetworkState
* network
= (*iter
)->AsNetworkState();
287 if (!network
->update_received() || !network
->Matches(type
))
289 if (configured_only
&& !network
->IsInProfile())
291 if (visible_only
&& !network
->visible())
293 list
->push_back(network
);
294 if (limit
> 0 && ++count
>= limit
)
299 const NetworkState
* NetworkStateHandler::GetNetworkStateFromServicePath(
300 const std::string
& service_path
,
301 bool configured_only
) const {
302 ManagedState
* managed
=
303 GetModifiableManagedState(&network_list_
, service_path
);
306 const NetworkState
* network
= managed
->AsNetworkState();
308 if (!network
->update_received() ||
309 (configured_only
&& !network
->IsInProfile())) {
315 const NetworkState
* NetworkStateHandler::GetNetworkStateFromGuid(
316 const std::string
& guid
) const {
317 DCHECK(!guid
.empty());
318 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
319 iter
!= network_list_
.end(); ++iter
) {
320 const NetworkState
* network
= (*iter
)->AsNetworkState();
321 if (network
->guid() == guid
)
327 void NetworkStateHandler::GetDeviceList(DeviceStateList
* list
) const {
328 GetDeviceListByType(NetworkTypePattern::Default(), list
);
331 void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern
& type
,
332 DeviceStateList
* list
) const {
335 for (ManagedStateList::const_iterator iter
= device_list_
.begin();
336 iter
!= device_list_
.end(); ++iter
) {
337 const DeviceState
* device
= (*iter
)->AsDeviceState();
339 if (device
->update_received() && device
->Matches(type
))
340 list
->push_back(device
);
344 void NetworkStateHandler::RequestScan() const {
345 NET_LOG_USER("RequestScan", "");
346 shill_property_handler_
->RequestScan();
349 void NetworkStateHandler::RequestUpdateForNetwork(
350 const std::string
& service_path
) {
351 NetworkState
* network
= GetModifiableNetworkState(service_path
);
353 network
->set_update_requested(true);
354 NET_LOG_EVENT("RequestUpdate", service_path
);
355 shill_property_handler_
->RequestProperties(ManagedState::MANAGED_TYPE_NETWORK
,
359 void NetworkStateHandler::ClearLastErrorForNetwork(
360 const std::string
& service_path
) {
361 NetworkState
* network
= GetModifiableNetworkState(service_path
);
363 network
->clear_last_error();
366 void NetworkStateHandler::SetCheckPortalList(
367 const std::string
& check_portal_list
) {
368 NET_LOG_EVENT("SetCheckPortalList", check_portal_list
);
369 shill_property_handler_
->SetCheckPortalList(check_portal_list
);
372 void NetworkStateHandler::SetWakeOnLanEnabled(bool enabled
) {
373 NET_LOG_EVENT("SetWakeOnLanEnabled", enabled
? "true" : "false");
374 shill_property_handler_
->SetWakeOnLanEnabled(enabled
);
377 const NetworkState
* NetworkStateHandler::GetEAPForEthernet(
378 const std::string
& service_path
) {
379 const NetworkState
* network
= GetNetworkState(service_path
);
381 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path
);
384 if (network
->type() != shill::kTypeEthernet
) {
385 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path
);
388 if (!network
->IsConnectedState())
391 // The same EAP service is shared for all ethernet services/devices.
392 // However EAP is used/enabled per device and only if the connection was
393 // successfully established.
394 const DeviceState
* device
= GetDeviceState(network
->device_path());
396 NET_LOG(ERROR
) << "GetEAPForEthernet: Unknown device "
397 << network
->device_path()
398 << " for connected ethernet service: " << service_path
;
401 if (!device
->eap_authentication_completed())
404 NetworkStateList list
;
405 GetNetworkListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap
),
406 true /* configured_only */, false /* visible_only */,
407 1 /* limit */, &list
);
409 NET_LOG_ERROR("GetEAPForEthernet",
411 "Ethernet service %s connected using EAP, but no "
412 "EAP service found.",
413 service_path
.c_str()));
419 void NetworkStateHandler::SetLastErrorForTest(const std::string
& service_path
,
420 const std::string
& error
) {
421 NetworkState
* network_state
= GetModifiableNetworkState(service_path
);
422 if (!network_state
) {
423 LOG(ERROR
) << "No matching NetworkState for: " << service_path
;
426 network_state
->last_error_
= error
;
429 //------------------------------------------------------------------------------
430 // ShillPropertyHandler::Delegate overrides
432 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type
,
433 const base::ListValue
& entries
) {
434 ManagedStateList
* managed_list
= GetManagedList(type
);
435 NET_LOG_DEBUG("UpdateManagedList: " + ManagedState::TypeToString(type
),
436 base::StringPrintf("%" PRIuS
, entries
.GetSize()));
437 // Create a map of existing entries. Assumes all entries in |managed_list|
439 typedef std::map
<std::string
, ManagedState
*> ManagedMap
;
440 ManagedMap managed_map
;
441 for (ManagedStateList::iterator iter
= managed_list
->begin();
442 iter
!= managed_list
->end(); ++iter
) {
443 ManagedState
* managed
= *iter
;
444 DCHECK(!ContainsKey(managed_map
, managed
->path()));
445 managed_map
[managed
->path()] = managed
;
447 // Clear the list (pointers are temporarily owned by managed_map).
448 managed_list
->clear();
449 // Updates managed_list and request updates for new entries.
450 std::set
<std::string
> list_entries
;
451 for (base::ListValue::const_iterator iter
= entries
.begin();
452 iter
!= entries
.end(); ++iter
) {
454 (*iter
)->GetAsString(&path
);
455 if (path
.empty() || path
== shill::kFlimflamServicePath
) {
456 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type
), path
);
459 ManagedMap::iterator found
= managed_map
.find(path
);
460 if (found
== managed_map
.end()) {
461 if (list_entries
.count(path
) != 0) {
462 NET_LOG_ERROR("Duplicate entry in list", path
);
465 ManagedState
* managed
= ManagedState::Create(type
, path
);
466 managed_list
->push_back(managed
);
468 managed_list
->push_back(found
->second
);
469 managed_map
.erase(found
);
471 list_entries
.insert(path
);
473 // Delete any remaining entries in managed_map.
474 STLDeleteContainerPairSecondPointers(managed_map
.begin(), managed_map
.end());
477 void NetworkStateHandler::ProfileListChanged() {
478 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
479 for (ManagedStateList::iterator iter
= network_list_
.begin();
480 iter
!= network_list_
.end(); ++iter
) {
481 NetworkState
* network
= (*iter
)->AsNetworkState();
483 shill_property_handler_
->RequestProperties(
484 ManagedState::MANAGED_TYPE_NETWORK
, network
->path());
488 void NetworkStateHandler::UpdateManagedStateProperties(
489 ManagedState::ManagedType type
,
490 const std::string
& path
,
491 const base::DictionaryValue
& properties
) {
492 ManagedStateList
* managed_list
= GetManagedList(type
);
493 ManagedState
* managed
= GetModifiableManagedState(managed_list
, path
);
495 // The network has been removed from the list of networks.
496 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path
);
499 managed
->set_update_received();
501 std::string desc
= GetManagedStateLogType(managed
) + " Properties Received";
502 NET_LOG_DEBUG(desc
, GetLogName(managed
));
504 if (type
== ManagedState::MANAGED_TYPE_NETWORK
) {
505 UpdateNetworkStateProperties(managed
->AsNetworkState(), properties
);
508 for (base::DictionaryValue::Iterator
iter(properties
); !iter
.IsAtEnd();
510 managed
->PropertyChanged(iter
.key(), iter
.value());
512 managed
->InitialPropertiesReceived(properties
);
514 managed
->set_update_requested(false);
517 void NetworkStateHandler::UpdateNetworkStateProperties(
518 NetworkState
* network
,
519 const base::DictionaryValue
& properties
) {
521 bool network_property_updated
= false;
522 std::string prev_connection_state
= network
->connection_state();
523 bool prev_is_captive_portal
= network
->is_captive_portal();
524 for (base::DictionaryValue::Iterator
iter(properties
); !iter
.IsAtEnd();
526 if (network
->PropertyChanged(iter
.key(), iter
.value()))
527 network_property_updated
= true;
529 network_property_updated
|= network
->InitialPropertiesReceived(properties
);
531 network_list_sorted_
= false;
533 // Notify observers of NetworkState changes.
534 if (network_property_updated
|| network
->update_requested()) {
535 // Signal connection state changed after all properties have been updated.
536 if (ConnectionStateChanged(network
, prev_connection_state
,
537 prev_is_captive_portal
)) {
538 OnNetworkConnectionStateChanged(network
);
540 NET_LOG_EVENT("NetworkPropertiesUpdated", GetLogName(network
));
541 NotifyNetworkPropertiesUpdated(network
);
545 void NetworkStateHandler::UpdateNetworkServiceProperty(
546 const std::string
& service_path
,
547 const std::string
& key
,
548 const base::Value
& value
) {
549 SCOPED_NET_LOG_IF_SLOW();
550 bool changed
= false;
551 NetworkState
* network
= GetModifiableNetworkState(service_path
);
554 std::string prev_connection_state
= network
->connection_state();
555 bool prev_is_captive_portal
= network
->is_captive_portal();
556 std::string prev_profile_path
= network
->profile_path();
557 changed
|= network
->PropertyChanged(key
, value
);
561 if (key
== shill::kStateProperty
|| key
== shill::kVisibleProperty
) {
562 network_list_sorted_
= false;
563 if (ConnectionStateChanged(network
, prev_connection_state
,
564 prev_is_captive_portal
)) {
565 OnNetworkConnectionStateChanged(network
);
566 // If the connection state changes, other properties such as IPConfig
567 // may have changed, so request a full update.
568 RequestUpdateForNetwork(service_path
);
571 std::string value_str
;
572 value
.GetAsString(&value_str
);
573 // Some property changes are noisy and not interesting:
574 // * Wifi SignalStrength
575 // * WifiFrequencyList updates
576 // * Device property changes to "/" (occurs before a service is removed)
577 if (key
!= shill::kSignalStrengthProperty
&&
578 key
!= shill::kWifiFrequencyListProperty
&&
579 (key
!= shill::kDeviceProperty
|| value_str
!= "/")) {
580 std::string log_event
= "NetworkPropertyUpdated";
581 // Trigger a default network update for interesting changes only.
582 if (network
->path() == default_network_path_
) {
583 NotifyDefaultNetworkChanged(network
);
584 log_event
= "Default" + log_event
;
587 std::string detail
= network
->name() + "." + key
;
588 detail
+= " = " + ValueAsString(value
);
589 device_event_log::LogLevel log_level
;
590 if (key
== shill::kErrorProperty
|| key
== shill::kErrorDetailsProperty
) {
591 log_level
= device_event_log::LOG_LEVEL_ERROR
;
593 log_level
= device_event_log::LOG_LEVEL_EVENT
;
595 NET_LOG_LEVEL(log_level
, log_event
, detail
);
599 // All property updates signal 'NetworkPropertiesUpdated'.
600 NotifyNetworkPropertiesUpdated(network
);
602 // If added to a Profile, request a full update so that a NetworkState
604 if (prev_profile_path
.empty() && !network
->profile_path().empty())
605 RequestUpdateForNetwork(service_path
);
608 void NetworkStateHandler::UpdateDeviceProperty(const std::string
& device_path
,
609 const std::string
& key
,
610 const base::Value
& value
) {
611 SCOPED_NET_LOG_IF_SLOW();
612 DeviceState
* device
= GetModifiableDeviceState(device_path
);
615 if (!device
->PropertyChanged(key
, value
))
618 std::string detail
= device
->name() + "." + key
;
619 detail
+= " = " + ValueAsString(value
);
620 NET_LOG_EVENT("DevicePropertyUpdated", detail
);
622 NotifyDeviceListChanged();
623 NotifyDevicePropertiesUpdated(device
);
625 if (key
== shill::kScanningProperty
&& device
->scanning() == false) {
626 NotifyScanCompleted(device
);
628 if (key
== shill::kEapAuthenticationCompletedProperty
) {
629 // Notify a change for each Ethernet service using this device.
630 NetworkStateList ethernet_services
;
631 GetNetworkListByType(NetworkTypePattern::Ethernet(),
632 false /* configured_only */, false /* visible_only */,
633 0 /* no limit */, ðernet_services
);
634 for (NetworkStateList::const_iterator it
= ethernet_services
.begin();
635 it
!= ethernet_services
.end(); ++it
) {
636 const NetworkState
* ethernet_service
= *it
;
637 if (ethernet_service
->update_received() ||
638 ethernet_service
->device_path() != device
->path()) {
641 RequestUpdateForNetwork(ethernet_service
->path());
646 void NetworkStateHandler::UpdateIPConfigProperties(
647 ManagedState::ManagedType type
,
648 const std::string
& path
,
649 const std::string
& ip_config_path
,
650 const base::DictionaryValue
& properties
) {
651 if (type
== ManagedState::MANAGED_TYPE_NETWORK
) {
652 NetworkState
* network
= GetModifiableNetworkState(path
);
655 network
->IPConfigPropertiesChanged(properties
);
656 NotifyNetworkPropertiesUpdated(network
);
657 if (network
->path() == default_network_path_
)
658 NotifyDefaultNetworkChanged(network
);
659 } else if (type
== ManagedState::MANAGED_TYPE_DEVICE
) {
660 DeviceState
* device
= GetModifiableDeviceState(path
);
663 device
->IPConfigPropertiesChanged(ip_config_path
, properties
);
664 NotifyDevicePropertiesUpdated(device
);
665 if (!default_network_path_
.empty()) {
666 const NetworkState
* default_network
=
667 GetNetworkState(default_network_path_
);
668 if (default_network
&& default_network
->device_path() == path
)
669 NotifyDefaultNetworkChanged(default_network
);
674 void NetworkStateHandler::CheckPortalListChanged(
675 const std::string
& check_portal_list
) {
676 check_portal_list_
= check_portal_list
;
679 void NetworkStateHandler::TechnologyListChanged() {
680 // Eventually we would like to replace Technology state with Device state.
681 // For now, treat technology state changes as device list changes.
682 NotifyDeviceListChanged();
685 void NetworkStateHandler::ManagedStateListChanged(
686 ManagedState::ManagedType type
) {
687 SCOPED_NET_LOG_IF_SLOW();
688 if (type
== ManagedState::MANAGED_TYPE_NETWORK
) {
690 UpdateNetworkStats();
691 // Notify observers that the list of networks has changed.
692 NET_LOG_EVENT("NOTIFY:NetworkListChanged",
693 base::StringPrintf("Size:%" PRIuS
, network_list_
.size()));
694 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
695 NetworkListChanged());
696 } else if (type
== ManagedState::MANAGED_TYPE_DEVICE
) {
698 for (ManagedStateList::const_iterator iter
= device_list_
.begin();
699 iter
!= device_list_
.end(); ++iter
) {
700 if (iter
!= device_list_
.begin())
702 devices
+= (*iter
)->name();
704 NET_LOG_EVENT("DeviceList", devices
);
705 NotifyDeviceListChanged();
711 void NetworkStateHandler::SortNetworkList() {
712 // Note: usually active networks will precede inactive networks, however
713 // this may briefly be untrue during state transitions (e.g. a network may
714 // transition to idle before the list is updated).
715 ManagedStateList active
, non_wifi_visible
, wifi_visible
, hidden
, new_networks
;
716 for (ManagedStateList::iterator iter
= network_list_
.begin();
717 iter
!= network_list_
.end(); ++iter
) {
718 NetworkState
* network
= (*iter
)->AsNetworkState();
719 if (!network
->update_received()) {
720 new_networks
.push_back(network
);
723 if (network
->IsConnectedState() || network
->IsConnectingState()) {
724 active
.push_back(network
);
727 if (network
->visible()) {
728 if (NetworkTypePattern::WiFi().MatchesType(network
->type()))
729 wifi_visible
.push_back(network
);
731 non_wifi_visible
.push_back(network
);
733 hidden
.push_back(network
);
736 network_list_
.clear();
737 network_list_
.insert(network_list_
.end(), active
.begin(), active
.end());
738 network_list_
.insert(network_list_
.end(), non_wifi_visible
.begin(),
739 non_wifi_visible
.end());
740 network_list_
.insert(network_list_
.end(), wifi_visible
.begin(),
742 network_list_
.insert(network_list_
.end(), hidden
.begin(), hidden
.end());
743 network_list_
.insert(network_list_
.end(), new_networks
.begin(),
745 network_list_sorted_
= true;
748 void NetworkStateHandler::UpdateNetworkStats() {
749 size_t shared
= 0, unshared
= 0, visible
= 0;
750 for (ManagedStateList::iterator iter
= network_list_
.begin();
751 iter
!= network_list_
.end(); ++iter
) {
752 NetworkState
* network
= (*iter
)->AsNetworkState();
753 if (network
->visible())
755 if (network
->IsInProfile()) {
756 if (network
->IsPrivate())
762 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", visible
);
763 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared
);
764 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared
);
767 void NetworkStateHandler::DefaultNetworkServiceChanged(
768 const std::string
& service_path
) {
769 // Shill uses '/' for empty service path values; check explicitly for that.
770 const char* kEmptyServicePath
= "/";
771 std::string new_service_path
=
772 (service_path
!= kEmptyServicePath
) ? service_path
: "";
773 if (new_service_path
== default_network_path_
)
776 default_network_path_
= service_path
;
777 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_
);
778 const NetworkState
* network
= nullptr;
779 if (!default_network_path_
.empty()) {
780 network
= GetNetworkState(default_network_path_
);
782 // If NetworkState is not available yet, do not notify observers here,
783 // they will be notified when the state is received.
784 NET_LOG(EVENT
) << "Default NetworkState not available: "
785 << default_network_path_
;
789 if (network
&& !network
->IsConnectedState()) {
790 if (network
->IsConnectingState()) {
791 NET_LOG(EVENT
) << "DefaultNetwork is connecting: " << GetLogName(network
)
792 << ": " << network
->connection_state();
794 NET_LOG(ERROR
) << "DefaultNetwork in unexpected state: "
795 << GetLogName(network
) << ": "
796 << network
->connection_state();
798 // Do not notify observers here, the notification will occur when the
799 // connection state changes.
802 NotifyDefaultNetworkChanged(network
);
805 //------------------------------------------------------------------------------
808 void NetworkStateHandler::UpdateGuid(NetworkState
* network
) {
809 std::string specifier
= network
->GetSpecifier();
810 DCHECK(!specifier
.empty());
811 if (!network
->guid().empty()) {
812 // If the network is saved in a profile, remove the entry from the map.
813 // Otherwise ensure that the entry matches the specified GUID. (e.g. in
814 // case a visible network with a specified guid gets configured with a
816 if (network
->IsInProfile())
817 specifier_guid_map_
.erase(specifier
);
819 specifier_guid_map_
[specifier
] = network
->guid();
822 // Ensure that the NetworkState has a valid GUID.
824 SpecifierGuidMap::iterator iter
= specifier_guid_map_
.find(specifier
);
825 if (iter
!= specifier_guid_map_
.end()) {
828 guid
= base::GenerateGUID();
829 specifier_guid_map_
[specifier
] = guid
;
831 network
->SetGuid(guid
);
834 void NetworkStateHandler::NotifyDeviceListChanged() {
835 SCOPED_NET_LOG_IF_SLOW();
836 NET_LOG_DEBUG("NOTIFY:DeviceListChanged",
837 base::StringPrintf("Size:%" PRIuS
, device_list_
.size()));
838 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
839 DeviceListChanged());
842 DeviceState
* NetworkStateHandler::GetModifiableDeviceState(
843 const std::string
& device_path
) const {
844 ManagedState
* managed
= GetModifiableManagedState(&device_list_
, device_path
);
847 return managed
->AsDeviceState();
850 NetworkState
* NetworkStateHandler::GetModifiableNetworkState(
851 const std::string
& service_path
) const {
852 ManagedState
* managed
=
853 GetModifiableManagedState(&network_list_
, service_path
);
856 return managed
->AsNetworkState();
859 ManagedState
* NetworkStateHandler::GetModifiableManagedState(
860 const ManagedStateList
* managed_list
,
861 const std::string
& path
) const {
862 for (ManagedStateList::const_iterator iter
= managed_list
->begin();
863 iter
!= managed_list
->end(); ++iter
) {
864 ManagedState
* managed
= *iter
;
865 if (managed
->path() == path
)
871 NetworkStateHandler::ManagedStateList
* NetworkStateHandler::GetManagedList(
872 ManagedState::ManagedType type
) {
874 case ManagedState::MANAGED_TYPE_NETWORK
:
875 return &network_list_
;
876 case ManagedState::MANAGED_TYPE_DEVICE
:
877 return &device_list_
;
883 void NetworkStateHandler::OnNetworkConnectionStateChanged(
884 NetworkState
* network
) {
885 SCOPED_NET_LOG_IF_SLOW();
887 bool notify_default
= false;
888 if (network
->path() == default_network_path_
) {
889 if (network
->IsConnectedState()) {
890 notify_default
= true;
891 } else if (network
->IsConnectingState()) {
892 // Wait until the network is actually connected to notify that the default
894 NET_LOG(EVENT
) << "Default network is not connected: "
895 << GetLogName(network
)
896 << "State: " << network
->connection_state();
898 NET_LOG(ERROR
) << "Default network in unexpected state: "
899 << GetLogName(network
)
900 << "State: " << network
->connection_state();
901 default_network_path_
.clear();
903 NotifyDefaultNetworkChanged(nullptr);
906 std::string desc
= "NetworkConnectionStateChanged";
908 desc
= "Default" + desc
;
909 NET_LOG(EVENT
) << "NOTIFY: " << desc
<< ": " << GetLogName(network
) << ": "
910 << network
->connection_state();
911 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
912 NetworkConnectionStateChanged(network
));
914 NotifyDefaultNetworkChanged(network
);
917 void NetworkStateHandler::NotifyDefaultNetworkChanged(
918 const NetworkState
* default_network
) {
919 SCOPED_NET_LOG_IF_SLOW();
920 NET_LOG_EVENT("NOTIFY:DefaultNetworkChanged", GetLogName(default_network
));
921 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
922 DefaultNetworkChanged(default_network
));
925 void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
926 const NetworkState
* network
) {
927 SCOPED_NET_LOG_IF_SLOW();
928 NET_LOG_DEBUG("NOTIFY:NetworkPropertiesUpdated", GetLogName(network
));
929 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
930 NetworkPropertiesUpdated(network
));
933 void NetworkStateHandler::NotifyDevicePropertiesUpdated(
934 const DeviceState
* device
) {
935 SCOPED_NET_LOG_IF_SLOW();
936 NET_LOG_DEBUG("NOTIFY:DevicePropertiesUpdated", GetLogName(device
));
937 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
938 DevicePropertiesUpdated(device
));
941 void NetworkStateHandler::NotifyScanCompleted(const DeviceState
* device
) {
942 SCOPED_NET_LOG_IF_SLOW();
943 NET_LOG_DEBUG("NOTIFY:ScanCompleted", GetLogName(device
));
944 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
945 ScanCompleted(device
));
948 std::string
NetworkStateHandler::GetTechnologyForType(
949 const NetworkTypePattern
& type
) const {
950 if (type
.MatchesType(shill::kTypeEthernet
))
951 return shill::kTypeEthernet
;
953 if (type
.MatchesType(shill::kTypeWifi
))
954 return shill::kTypeWifi
;
956 if (type
.Equals(NetworkTypePattern::Wimax()))
957 return shill::kTypeWimax
;
959 // Prefer Wimax over Cellular only if it's available.
960 if (type
.MatchesType(shill::kTypeWimax
) &&
961 shill_property_handler_
->IsTechnologyAvailable(shill::kTypeWimax
)) {
962 return shill::kTypeWimax
;
965 if (type
.MatchesType(shill::kTypeCellular
))
966 return shill::kTypeCellular
;
969 return std::string();
972 ScopedVector
<std::string
> NetworkStateHandler::GetTechnologiesForType(
973 const NetworkTypePattern
& type
) const {
974 ScopedVector
<std::string
> technologies
;
975 if (type
.MatchesType(shill::kTypeEthernet
))
976 technologies
.push_back(new std::string(shill::kTypeEthernet
));
977 if (type
.MatchesType(shill::kTypeWifi
))
978 technologies
.push_back(new std::string(shill::kTypeWifi
));
979 if (type
.MatchesType(shill::kTypeWimax
))
980 technologies
.push_back(new std::string(shill::kTypeWimax
));
981 if (type
.MatchesType(shill::kTypeCellular
))
982 technologies
.push_back(new std::string(shill::kTypeCellular
));
983 if (type
.MatchesType(shill::kTypeBluetooth
))
984 technologies
.push_back(new std::string(shill::kTypeBluetooth
));
985 if (type
.MatchesType(shill::kTypeVPN
))
986 technologies
.push_back(new std::string(shill::kTypeVPN
));
988 CHECK_GT(technologies
.size(), 0ul);
989 return technologies
.Pass();
992 } // namespace chromeos