Don't schedule more invokeFunctors than necessary.
[chromium-blink-merge.git] / chromeos / network / network_state_handler.cc
bloba4562b054d16c48b9646d125983a648ca0a2e70a
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"
7 #include "base/bind.h"
8 #include "base/format_macros.h"
9 #include "base/guid.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/managed_state.h"
21 #include "chromeos/network/network_event_log.h"
22 #include "chromeos/network/network_state.h"
23 #include "chromeos/network/network_state_handler_observer.h"
24 #include "chromeos/network/shill_property_handler.h"
25 #include "third_party/cros_system_api/dbus/service_constants.h"
27 namespace chromeos {
29 namespace {
31 bool ConnectionStateChanged(NetworkState* network,
32 const std::string& prev_connection_state) {
33 return (network->connection_state() != prev_connection_state) &&
34 (network->connection_state() != shill::kStateIdle ||
35 !prev_connection_state.empty());
38 std::string GetManagedStateLogType(const ManagedState* state) {
39 switch (state->managed_type()) {
40 case ManagedState::MANAGED_TYPE_NETWORK:
41 return "Network";
42 case ManagedState::MANAGED_TYPE_DEVICE:
43 return "Device";
45 NOTREACHED();
46 return "";
49 std::string GetLogName(const ManagedState* state) {
50 if (!state)
51 return "None";
52 return base::StringPrintf("%s (%s)", state->name().c_str(),
53 state->path().c_str());
56 std::string ValueAsString(const base::Value& value) {
57 std::string vstr;
58 base::JSONWriter::WriteWithOptions(
59 &value, base::JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &vstr);
60 return vstr.empty() ? "''" : vstr;
63 } // namespace
65 const char NetworkStateHandler::kDefaultCheckPortalList[] =
66 "ethernet,wifi,cellular";
68 NetworkStateHandler::NetworkStateHandler()
69 : network_list_sorted_(false) {
72 NetworkStateHandler::~NetworkStateHandler() {
73 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, IsShuttingDown());
74 STLDeleteContainerPointers(network_list_.begin(), network_list_.end());
75 STLDeleteContainerPointers(device_list_.begin(), device_list_.end());
78 void NetworkStateHandler::InitShillPropertyHandler() {
79 shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
80 shill_property_handler_->Init();
83 // static
84 NetworkStateHandler* NetworkStateHandler::InitializeForTest() {
85 NetworkStateHandler* handler = new NetworkStateHandler();
86 handler->InitShillPropertyHandler();
87 return handler;
90 void NetworkStateHandler::AddObserver(
91 NetworkStateHandlerObserver* observer,
92 const tracked_objects::Location& from_here) {
93 observers_.AddObserver(observer);
94 device_event_log::AddEntry(from_here.file_name(), from_here.line_number(),
95 device_event_log::LOG_TYPE_NETWORK,
96 device_event_log::LOG_LEVEL_DEBUG,
97 "NetworkStateHandler::AddObserver");
100 void NetworkStateHandler::RemoveObserver(
101 NetworkStateHandlerObserver* observer,
102 const tracked_objects::Location& from_here) {
103 observers_.RemoveObserver(observer);
104 device_event_log::AddEntry(from_here.file_name(), from_here.line_number(),
105 device_event_log::LOG_TYPE_NETWORK,
106 device_event_log::LOG_LEVEL_DEBUG,
107 "NetworkStateHandler::RemoveObserver");
110 NetworkStateHandler::TechnologyState NetworkStateHandler::GetTechnologyState(
111 const NetworkTypePattern& type) const {
112 std::string technology = GetTechnologyForType(type);
113 TechnologyState state;
114 if (shill_property_handler_->IsTechnologyEnabled(technology))
115 state = TECHNOLOGY_ENABLED;
116 else if (shill_property_handler_->IsTechnologyEnabling(technology))
117 state = TECHNOLOGY_ENABLING;
118 else if (shill_property_handler_->IsTechnologyUninitialized(technology))
119 state = TECHNOLOGY_UNINITIALIZED;
120 else if (shill_property_handler_->IsTechnologyAvailable(technology))
121 state = TECHNOLOGY_AVAILABLE;
122 else
123 state = TECHNOLOGY_UNAVAILABLE;
124 VLOG(2) << "GetTechnologyState: " << type.ToDebugString() << " = " << state;
125 return state;
128 void NetworkStateHandler::SetTechnologyEnabled(
129 const NetworkTypePattern& type,
130 bool enabled,
131 const network_handler::ErrorCallback& error_callback) {
132 ScopedVector<std::string> technologies = GetTechnologiesForType(type);
133 for (ScopedVector<std::string>::iterator it = technologies.begin();
134 it != technologies.end(); ++it) {
135 std::string* technology = *it;
136 DCHECK(technology);
137 if (!shill_property_handler_->IsTechnologyAvailable(*technology))
138 continue;
139 NET_LOG_USER("SetTechnologyEnabled",
140 base::StringPrintf("%s:%d", technology->c_str(), enabled));
141 shill_property_handler_->SetTechnologyEnabled(
142 *technology, enabled, error_callback);
144 // Signal Device/Technology state changed.
145 NotifyDeviceListChanged();
148 const DeviceState* NetworkStateHandler::GetDeviceState(
149 const std::string& device_path) const {
150 const DeviceState* device = GetModifiableDeviceState(device_path);
151 if (device && !device->update_received())
152 return NULL;
153 return device;
156 const DeviceState* NetworkStateHandler::GetDeviceStateByType(
157 const NetworkTypePattern& type) const {
158 for (ManagedStateList::const_iterator iter = device_list_.begin();
159 iter != device_list_.end(); ++iter) {
160 ManagedState* device = *iter;
161 if (!device->update_received())
162 continue;
163 if (device->Matches(type))
164 return device->AsDeviceState();
166 return NULL;
169 bool NetworkStateHandler::GetScanningByType(
170 const NetworkTypePattern& type) const {
171 for (ManagedStateList::const_iterator iter = device_list_.begin();
172 iter != device_list_.end(); ++iter) {
173 const DeviceState* device = (*iter)->AsDeviceState();
174 DCHECK(device);
175 if (!device->update_received())
176 continue;
177 if (device->Matches(type) && device->scanning())
178 return true;
180 return false;
183 const NetworkState* NetworkStateHandler::GetNetworkState(
184 const std::string& service_path) const {
185 const NetworkState* network = GetModifiableNetworkState(service_path);
186 if (network && !network->update_received())
187 return NULL;
188 return network;
191 const NetworkState* NetworkStateHandler::DefaultNetwork() const {
192 if (default_network_path_.empty())
193 return NULL;
194 return GetNetworkState(default_network_path_);
197 const NetworkState* NetworkStateHandler::ConnectedNetworkByType(
198 const NetworkTypePattern& type) const {
199 // Active networks are always listed first by Shill so no need to sort.
200 for (ManagedStateList::const_iterator iter = network_list_.begin();
201 iter != network_list_.end(); ++iter) {
202 const NetworkState* network = (*iter)->AsNetworkState();
203 DCHECK(network);
204 if (!network->update_received())
205 continue;
206 if (!network->IsConnectedState())
207 break; // Connected networks are listed first.
208 if (network->Matches(type))
209 return network;
211 return NULL;
214 const NetworkState* NetworkStateHandler::ConnectingNetworkByType(
215 const NetworkTypePattern& type) const {
216 // Active networks are always listed first by Shill so no need to sort.
217 for (ManagedStateList::const_iterator iter = network_list_.begin();
218 iter != network_list_.end(); ++iter) {
219 const NetworkState* network = (*iter)->AsNetworkState();
220 DCHECK(network);
221 if (!network->update_received() || network->IsConnectedState())
222 continue;
223 if (!network->IsConnectingState())
224 break; // Connected and connecting networks are listed first.
225 if (network->Matches(type))
226 return network;
228 return NULL;
231 const NetworkState* NetworkStateHandler::FirstNetworkByType(
232 const NetworkTypePattern& type) {
233 if (!network_list_sorted_)
234 SortNetworkList(); // Sort to ensure visible networks are listed first.
235 for (ManagedStateList::const_iterator iter = network_list_.begin();
236 iter != network_list_.end(); ++iter) {
237 const NetworkState* network = (*iter)->AsNetworkState();
238 DCHECK(network);
239 if (!network->update_received())
240 continue;
241 if (!network->visible())
242 break;
243 if (network->Matches(type))
244 return network;
246 return NULL;
249 std::string NetworkStateHandler::FormattedHardwareAddressForType(
250 const NetworkTypePattern& type) const {
251 const DeviceState* device = NULL;
252 const NetworkState* network = ConnectedNetworkByType(type);
253 if (network)
254 device = GetDeviceState(network->device_path());
255 else
256 device = GetDeviceStateByType(type);
257 if (!device)
258 return std::string();
259 return network_util::FormattedMacAddress(device->mac_address());
262 void NetworkStateHandler::GetVisibleNetworkListByType(
263 const NetworkTypePattern& type,
264 NetworkStateList* list) {
265 GetNetworkListByType(type,
266 false /* configured_only */,
267 true /* visible_only */,
268 0 /* no limit */,
269 list);
272 void NetworkStateHandler::GetVisibleNetworkList(NetworkStateList* list) {
273 GetVisibleNetworkListByType(NetworkTypePattern::Default(), list);
276 void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type,
277 bool configured_only,
278 bool visible_only,
279 int limit,
280 NetworkStateList* list) {
281 DCHECK(list);
282 list->clear();
283 int count = 0;
284 // Sort the network list if necessary.
285 if (!network_list_sorted_)
286 SortNetworkList();
287 for (ManagedStateList::const_iterator iter = network_list_.begin();
288 iter != network_list_.end(); ++iter) {
289 const NetworkState* network = (*iter)->AsNetworkState();
290 DCHECK(network);
291 if (!network->update_received() || !network->Matches(type))
292 continue;
293 if (configured_only && !network->IsInProfile())
294 continue;
295 if (visible_only && !network->visible())
296 continue;
297 list->push_back(network);
298 if (limit > 0 && ++count >= limit)
299 break;
303 const NetworkState* NetworkStateHandler::GetNetworkStateFromServicePath(
304 const std::string& service_path,
305 bool configured_only) const {
306 ManagedState* managed =
307 GetModifiableManagedState(&network_list_, service_path);
308 if (!managed)
309 return NULL;
310 const NetworkState* network = managed->AsNetworkState();
311 DCHECK(network);
312 if (!network->update_received() ||
313 (configured_only && !network->IsInProfile())) {
314 return NULL;
316 return network;
319 const NetworkState* NetworkStateHandler::GetNetworkStateFromGuid(
320 const std::string& guid) const {
321 DCHECK(!guid.empty());
322 for (ManagedStateList::const_iterator iter = network_list_.begin();
323 iter != network_list_.end(); ++iter) {
324 const NetworkState* network = (*iter)->AsNetworkState();
325 if (network->guid() == guid)
326 return network;
328 return NULL;
331 void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const {
332 GetDeviceListByType(NetworkTypePattern::Default(), list);
335 void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type,
336 DeviceStateList* list) const {
337 DCHECK(list);
338 list->clear();
339 for (ManagedStateList::const_iterator iter = device_list_.begin();
340 iter != device_list_.end(); ++iter) {
341 const DeviceState* device = (*iter)->AsDeviceState();
342 DCHECK(device);
343 if (device->update_received() && device->Matches(type))
344 list->push_back(device);
348 void NetworkStateHandler::RequestScan() const {
349 NET_LOG_USER("RequestScan", "");
350 shill_property_handler_->RequestScan();
353 void NetworkStateHandler::RequestUpdateForNetwork(
354 const std::string& service_path) {
355 NetworkState* network = GetModifiableNetworkState(service_path);
356 if (network)
357 network->set_update_requested(true);
358 NET_LOG_EVENT("RequestUpdate", service_path);
359 shill_property_handler_->RequestProperties(
360 ManagedState::MANAGED_TYPE_NETWORK, service_path);
363 void NetworkStateHandler::ClearLastErrorForNetwork(
364 const std::string& service_path) {
365 NetworkState* network = GetModifiableNetworkState(service_path);
366 if (network)
367 network->clear_last_error();
370 void NetworkStateHandler::SetCheckPortalList(
371 const std::string& check_portal_list) {
372 NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
373 shill_property_handler_->SetCheckPortalList(check_portal_list);
376 void NetworkStateHandler::SetWakeOnLanEnabled(bool enabled) {
377 NET_LOG_EVENT("SetWakeOnLanEnabled",
378 base::StringPrintf("%s", enabled ? "true" : "false"));
379 shill_property_handler_->SetWakeOnLanEnabled(enabled);
382 const NetworkState* NetworkStateHandler::GetEAPForEthernet(
383 const std::string& service_path) {
384 const NetworkState* network = GetNetworkState(service_path);
385 if (!network) {
386 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path);
387 return NULL;
389 if (network->type() != shill::kTypeEthernet) {
390 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path);
391 return NULL;
393 if (!network->IsConnectedState())
394 return NULL;
396 // The same EAP service is shared for all ethernet services/devices.
397 // However EAP is used/enabled per device and only if the connection was
398 // successfully established.
399 const DeviceState* device = GetDeviceState(network->device_path());
400 if (!device) {
401 NET_LOG_ERROR(
402 "GetEAPForEthernet",
403 base::StringPrintf("Unknown device %s of connected ethernet service %s",
404 network->device_path().c_str(),
405 service_path.c_str()));
406 return NULL;
408 if (!device->eap_authentication_completed())
409 return NULL;
411 NetworkStateList list;
412 GetNetworkListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap),
413 true /* configured_only */,
414 false /* visible_only */,
415 1 /* limit */,
416 &list);
417 if (list.empty()) {
418 NET_LOG_ERROR("GetEAPForEthernet",
419 base::StringPrintf(
420 "Ethernet service %s connected using EAP, but no "
421 "EAP service found.",
422 service_path.c_str()));
423 return NULL;
425 return list.front();
428 //------------------------------------------------------------------------------
429 // ShillPropertyHandler::Delegate overrides
431 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type,
432 const base::ListValue& entries) {
433 ManagedStateList* managed_list = GetManagedList(type);
434 NET_LOG_DEBUG("UpdateManagedList: " + ManagedState::TypeToString(type),
435 base::StringPrintf("%" PRIuS, entries.GetSize()));
436 // Create a map of existing entries. Assumes all entries in |managed_list|
437 // are unique.
438 typedef std::map<std::string, ManagedState*> ManagedMap;
439 ManagedMap managed_map;
440 for (ManagedStateList::iterator iter = managed_list->begin();
441 iter != managed_list->end(); ++iter) {
442 ManagedState* managed = *iter;
443 DCHECK(!ContainsKey(managed_map, managed->path()));
444 managed_map[managed->path()] = managed;
446 // Clear the list (pointers are temporarily owned by managed_map).
447 managed_list->clear();
448 // Updates managed_list and request updates for new entries.
449 std::set<std::string> list_entries;
450 for (base::ListValue::const_iterator iter = entries.begin();
451 iter != entries.end(); ++iter) {
452 std::string path;
453 (*iter)->GetAsString(&path);
454 if (path.empty() || path == shill::kFlimflamServicePath) {
455 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path);
456 continue;
458 ManagedMap::iterator found = managed_map.find(path);
459 if (found == managed_map.end()) {
460 if (list_entries.count(path) != 0) {
461 NET_LOG_ERROR("Duplicate entry in list", path);
462 continue;
464 ManagedState* managed = ManagedState::Create(type, path);
465 managed_list->push_back(managed);
466 } else {
467 managed_list->push_back(found->second);
468 managed_map.erase(found);
470 list_entries.insert(path);
472 // Delete any remaining entries in managed_map.
473 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
476 void NetworkStateHandler::ProfileListChanged() {
477 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
478 for (ManagedStateList::iterator iter = network_list_.begin();
479 iter != network_list_.end(); ++iter) {
480 NetworkState* network = (*iter)->AsNetworkState();
481 DCHECK(network);
482 shill_property_handler_->RequestProperties(
483 ManagedState::MANAGED_TYPE_NETWORK, network->path());
487 void NetworkStateHandler::UpdateManagedStateProperties(
488 ManagedState::ManagedType type,
489 const std::string& path,
490 const base::DictionaryValue& properties) {
491 ManagedStateList* managed_list = GetManagedList(type);
492 ManagedState* managed = GetModifiableManagedState(managed_list, path);
493 if (!managed) {
494 // The network has been removed from the list of networks.
495 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path);
496 return;
498 managed->set_update_received();
500 std::string desc = GetManagedStateLogType(managed) + " Properties Received";
501 NET_LOG_DEBUG(desc, GetLogName(managed));
503 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
504 UpdateNetworkStateProperties(managed->AsNetworkState(), properties);
505 } else {
506 // Device
507 for (base::DictionaryValue::Iterator iter(properties);
508 !iter.IsAtEnd(); iter.Advance()) {
509 managed->PropertyChanged(iter.key(), iter.value());
511 managed->InitialPropertiesReceived(properties);
513 managed->set_update_requested(false);
516 void NetworkStateHandler::UpdateNetworkStateProperties(
517 NetworkState* network,
518 const base::DictionaryValue& properties) {
519 DCHECK(network);
520 bool network_property_updated = false;
521 std::string prev_connection_state = network->connection_state();
522 for (base::DictionaryValue::Iterator iter(properties);
523 !iter.IsAtEnd(); iter.Advance()) {
524 if (network->PropertyChanged(iter.key(), iter.value()))
525 network_property_updated = true;
527 network_property_updated |= network->InitialPropertiesReceived(properties);
528 UpdateGuid(network);
529 network_list_sorted_ = false;
531 // Notify observers of NetworkState changes.
532 if (network_property_updated || network->update_requested()) {
533 // Signal connection state changed after all properties have been updated.
534 if (ConnectionStateChanged(network, prev_connection_state))
535 OnNetworkConnectionStateChanged(network);
536 NET_LOG_EVENT("NetworkPropertiesUpdated", GetLogName(network));
537 NotifyNetworkPropertiesUpdated(network);
541 void NetworkStateHandler::UpdateNetworkServiceProperty(
542 const std::string& service_path,
543 const std::string& key,
544 const base::Value& value) {
545 bool changed = false;
546 NetworkState* network = GetModifiableNetworkState(service_path);
547 if (!network)
548 return;
549 std::string prev_connection_state = network->connection_state();
550 std::string prev_profile_path = network->profile_path();
551 changed |= network->PropertyChanged(key, value);
552 if (!changed)
553 return;
555 if (key == shill::kStateProperty || key == shill::kVisibleProperty) {
556 network_list_sorted_ = false;
557 if (ConnectionStateChanged(network, prev_connection_state)) {
558 OnNetworkConnectionStateChanged(network);
559 // If the connection state changes, other properties such as IPConfig
560 // may have changed, so request a full update.
561 RequestUpdateForNetwork(service_path);
563 } else {
564 std::string value_str;
565 value.GetAsString(&value_str);
566 // Some property changes are noisy and not interesting:
567 // * Wifi SignalStrength
568 // * WifiFrequencyList updates
569 // * Device property changes to "/" (occurs before a service is removed)
570 if (key != shill::kSignalStrengthProperty &&
571 key != shill::kWifiFrequencyListProperty &&
572 (key != shill::kDeviceProperty || value_str != "/")) {
573 std::string log_event = "NetworkPropertyUpdated";
574 // Trigger a default network update for interesting changes only.
575 if (network->path() == default_network_path_) {
576 NotifyDefaultNetworkChanged(network);
577 log_event = "Default" + log_event;
579 // Log event.
580 std::string detail = network->name() + "." + key;
581 detail += " = " + ValueAsString(value);
582 device_event_log::LogLevel log_level;
583 if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) {
584 log_level = device_event_log::LOG_LEVEL_ERROR;
585 } else {
586 log_level = device_event_log::LOG_LEVEL_EVENT;
588 NET_LOG_LEVEL(log_level, log_event, detail);
592 // All property updates signal 'NetworkPropertiesUpdated'.
593 NotifyNetworkPropertiesUpdated(network);
595 // If added to a Profile, request a full update so that a NetworkState
596 // gets created.
597 if (prev_profile_path.empty() && !network->profile_path().empty())
598 RequestUpdateForNetwork(service_path);
601 void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path,
602 const std::string& key,
603 const base::Value& value) {
604 DeviceState* device = GetModifiableDeviceState(device_path);
605 if (!device)
606 return;
607 if (!device->PropertyChanged(key, value))
608 return;
610 std::string detail = device->name() + "." + key;
611 detail += " = " + ValueAsString(value);
612 NET_LOG_EVENT("DevicePropertyUpdated", detail);
614 NotifyDeviceListChanged();
615 NotifyDevicePropertiesUpdated(device);
617 if (key == shill::kScanningProperty && device->scanning() == false) {
618 NotifyScanCompleted(device);
620 if (key == shill::kEapAuthenticationCompletedProperty) {
621 // Notify a change for each Ethernet service using this device.
622 NetworkStateList ethernet_services;
623 GetNetworkListByType(NetworkTypePattern::Ethernet(),
624 false /* configured_only */,
625 false /* visible_only */,
626 0 /* no limit */,
627 &ethernet_services);
628 for (NetworkStateList::const_iterator it = ethernet_services.begin();
629 it != ethernet_services.end(); ++it) {
630 const NetworkState* ethernet_service = *it;
631 if (ethernet_service->update_received() ||
632 ethernet_service->device_path() != device->path()) {
633 continue;
635 RequestUpdateForNetwork(ethernet_service->path());
640 void NetworkStateHandler::UpdateIPConfigProperties(
641 ManagedState::ManagedType type,
642 const std::string& path,
643 const std::string& ip_config_path,
644 const base::DictionaryValue& properties) {
645 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
646 NetworkState* network = GetModifiableNetworkState(path);
647 if (!network)
648 return;
649 network->IPConfigPropertiesChanged(properties);
650 NotifyNetworkPropertiesUpdated(network);
651 if (network->path() == default_network_path_)
652 NotifyDefaultNetworkChanged(network);
653 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
654 DeviceState* device = GetModifiableDeviceState(path);
655 if (!device)
656 return;
657 device->IPConfigPropertiesChanged(ip_config_path, properties);
658 NotifyDevicePropertiesUpdated(device);
659 if (!default_network_path_.empty()) {
660 const NetworkState* default_network =
661 GetNetworkState(default_network_path_);
662 if (default_network && default_network->device_path() == path)
663 NotifyDefaultNetworkChanged(default_network);
668 void NetworkStateHandler::CheckPortalListChanged(
669 const std::string& check_portal_list) {
670 check_portal_list_ = check_portal_list;
673 void NetworkStateHandler::TechnologyListChanged() {
674 // Eventually we would like to replace Technology state with Device state.
675 // For now, treat technology state changes as device list changes.
676 NotifyDeviceListChanged();
679 void NetworkStateHandler::ManagedStateListChanged(
680 ManagedState::ManagedType type) {
681 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
682 SortNetworkList();
683 UpdateNetworkStats();
684 // Notify observers that the list of networks has changed.
685 NET_LOG_EVENT("NOTIFY:NetworkListChanged",
686 base::StringPrintf("Size:%" PRIuS, network_list_.size()));
687 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
688 NetworkListChanged());
689 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
690 std::string devices;
691 for (ManagedStateList::const_iterator iter = device_list_.begin();
692 iter != device_list_.end(); ++iter) {
693 if (iter != device_list_.begin())
694 devices += ", ";
695 devices += (*iter)->name();
697 NET_LOG_EVENT("DeviceList", devices);
698 NotifyDeviceListChanged();
699 } else {
700 NOTREACHED();
704 void NetworkStateHandler::SortNetworkList() {
705 // Note: usually active networks will precede inactive networks, however
706 // this may briefly be untrue during state transitions (e.g. a network may
707 // transition to idle before the list is updated).
708 ManagedStateList active, non_wifi_visible, wifi_visible, hidden, new_networks;
709 for (ManagedStateList::iterator iter = network_list_.begin();
710 iter != network_list_.end(); ++iter) {
711 NetworkState* network = (*iter)->AsNetworkState();
712 if (!network->update_received()) {
713 new_networks.push_back(network);
714 continue;
716 if (network->IsConnectedState() || network->IsConnectingState()) {
717 active.push_back(network);
718 continue;
720 if (network->visible()) {
721 if (NetworkTypePattern::WiFi().MatchesType(network->type()))
722 wifi_visible.push_back(network);
723 else
724 non_wifi_visible.push_back(network);
725 } else {
726 hidden.push_back(network);
729 network_list_.clear();
730 network_list_.insert(network_list_.end(), active.begin(), active.end());
731 network_list_.insert(
732 network_list_.end(), non_wifi_visible.begin(), non_wifi_visible.end());
733 network_list_.insert(
734 network_list_.end(), wifi_visible.begin(), wifi_visible.end());
735 network_list_.insert(network_list_.end(), hidden.begin(), hidden.end());
736 network_list_.insert(
737 network_list_.end(), new_networks.begin(), new_networks.end());
738 network_list_sorted_ = true;
741 void NetworkStateHandler::UpdateNetworkStats() {
742 size_t shared = 0, unshared = 0, visible = 0;
743 for (ManagedStateList::iterator iter = network_list_.begin();
744 iter != network_list_.end(); ++iter) {
745 NetworkState* network = (*iter)->AsNetworkState();
746 if (network->visible())
747 ++visible;
748 if (network->IsInProfile()) {
749 if (network->IsPrivate())
750 ++unshared;
751 else
752 ++shared;
755 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", visible);
756 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared);
757 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared);
760 void NetworkStateHandler::DefaultNetworkServiceChanged(
761 const std::string& service_path) {
762 // Shill uses '/' for empty service path values; check explicitly for that.
763 const char* kEmptyServicePath = "/";
764 std::string new_service_path =
765 (service_path != kEmptyServicePath) ? service_path : "";
766 if (new_service_path == default_network_path_)
767 return;
769 default_network_path_ = service_path;
770 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_);
771 const NetworkState* network = NULL;
772 if (!default_network_path_.empty()) {
773 network = GetNetworkState(default_network_path_);
774 if (!network) {
775 // If NetworkState is not available yet, do not notify observers here,
776 // they will be notified when the state is received.
777 NET_LOG_DEBUG("Default NetworkState not available",
778 default_network_path_);
779 return;
782 if (network && !network->IsConnectedState()) {
783 NET_LOG_ERROR(
784 "DefaultNetwork is not connected: " + network->connection_state(),
785 network->path());
787 NotifyDefaultNetworkChanged(network);
790 //------------------------------------------------------------------------------
791 // Private methods
793 void NetworkStateHandler::UpdateGuid(NetworkState* network) {
794 std::string specifier = network->GetSpecifier();
795 DCHECK(!specifier.empty());
796 if (!network->guid().empty()) {
797 // If the network is saved in a profile, remove the entry from the map.
798 // Otherwise ensure that the entry matches the specified GUID. (e.g. in
799 // case a visible network with a specified guid gets configured with a
800 // new guid).
801 if (network->IsInProfile())
802 specifier_guid_map_.erase(specifier);
803 else
804 specifier_guid_map_[specifier] = network->guid();
805 return;
807 // Ensure that the NetworkState has a valid GUID.
808 std::string guid;
809 SpecifierGuidMap::iterator iter = specifier_guid_map_.find(specifier);
810 if (iter != specifier_guid_map_.end()) {
811 guid = iter->second;
812 } else {
813 guid = base::GenerateGUID();
814 specifier_guid_map_[specifier] = guid;
816 network->SetGuid(guid);
819 void NetworkStateHandler::NotifyDeviceListChanged() {
820 NET_LOG_DEBUG("NOTIFY:DeviceListChanged",
821 base::StringPrintf("Size:%" PRIuS, device_list_.size()));
822 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
823 DeviceListChanged());
826 DeviceState* NetworkStateHandler::GetModifiableDeviceState(
827 const std::string& device_path) const {
828 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
829 if (!managed)
830 return NULL;
831 return managed->AsDeviceState();
834 NetworkState* NetworkStateHandler::GetModifiableNetworkState(
835 const std::string& service_path) const {
836 ManagedState* managed =
837 GetModifiableManagedState(&network_list_, service_path);
838 if (!managed)
839 return NULL;
840 return managed->AsNetworkState();
843 ManagedState* NetworkStateHandler::GetModifiableManagedState(
844 const ManagedStateList* managed_list,
845 const std::string& path) const {
846 for (ManagedStateList::const_iterator iter = managed_list->begin();
847 iter != managed_list->end(); ++iter) {
848 ManagedState* managed = *iter;
849 if (managed->path() == path)
850 return managed;
852 return NULL;
855 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
856 ManagedState::ManagedType type) {
857 switch (type) {
858 case ManagedState::MANAGED_TYPE_NETWORK:
859 return &network_list_;
860 case ManagedState::MANAGED_TYPE_DEVICE:
861 return &device_list_;
863 NOTREACHED();
864 return NULL;
867 void NetworkStateHandler::OnNetworkConnectionStateChanged(
868 NetworkState* network) {
869 DCHECK(network);
870 std::string event = "NetworkConnectionStateChanged";
871 if (network->path() == default_network_path_) {
872 event = "Default" + event;
873 if (!network->IsConnectedState()) {
874 NET_LOG_EVENT(
875 "DefaultNetwork is not connected: " + network->connection_state(),
876 network->path());
877 default_network_path_.clear();
878 SortNetworkList();
879 NotifyDefaultNetworkChanged(NULL);
882 NET_LOG_EVENT("NOTIFY:" + event + ": " + network->connection_state(),
883 GetLogName(network));
884 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
885 NetworkConnectionStateChanged(network));
886 if (network->path() == default_network_path_)
887 NotifyDefaultNetworkChanged(network);
890 void NetworkStateHandler::NotifyDefaultNetworkChanged(
891 const NetworkState* default_network) {
892 NET_LOG_EVENT("NOTIFY:DefaultNetworkChanged", GetLogName(default_network));
893 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
894 DefaultNetworkChanged(default_network));
897 void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
898 const NetworkState* network) {
899 NET_LOG_DEBUG("NOTIFY:NetworkPropertiesUpdated", GetLogName(network));
900 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
901 NetworkPropertiesUpdated(network));
904 void NetworkStateHandler::NotifyDevicePropertiesUpdated(
905 const DeviceState* device) {
906 NET_LOG_DEBUG("NOTIFY:DevicePropertiesUpdated", GetLogName(device));
907 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
908 DevicePropertiesUpdated(device));
911 void NetworkStateHandler::NotifyScanCompleted(const DeviceState* device) {
912 NET_LOG_DEBUG("NOTIFY:ScanCompleted", GetLogName(device));
913 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
914 ScanCompleted(device));
917 std::string NetworkStateHandler::GetTechnologyForType(
918 const NetworkTypePattern& type) const {
919 if (type.MatchesType(shill::kTypeEthernet))
920 return shill::kTypeEthernet;
922 if (type.MatchesType(shill::kTypeWifi))
923 return shill::kTypeWifi;
925 if (type.Equals(NetworkTypePattern::Wimax()))
926 return shill::kTypeWimax;
928 // Prefer Wimax over Cellular only if it's available.
929 if (type.MatchesType(shill::kTypeWimax) &&
930 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
931 return shill::kTypeWimax;
934 if (type.MatchesType(shill::kTypeCellular))
935 return shill::kTypeCellular;
937 NOTREACHED();
938 return std::string();
941 ScopedVector<std::string> NetworkStateHandler::GetTechnologiesForType(
942 const NetworkTypePattern& type) const {
943 ScopedVector<std::string> technologies;
944 if (type.MatchesType(shill::kTypeEthernet))
945 technologies.push_back(new std::string(shill::kTypeEthernet));
946 if (type.MatchesType(shill::kTypeWifi))
947 technologies.push_back(new std::string(shill::kTypeWifi));
948 if (type.MatchesType(shill::kTypeWimax))
949 technologies.push_back(new std::string(shill::kTypeWimax));
950 if (type.MatchesType(shill::kTypeCellular))
951 technologies.push_back(new std::string(shill::kTypeCellular));
952 if (type.MatchesType(shill::kTypeBluetooth))
953 technologies.push_back(new std::string(shill::kTypeBluetooth));
954 if (type.MatchesType(shill::kTypeVPN))
955 technologies.push_back(new std::string(shill::kTypeVPN));
957 CHECK_GT(technologies.size(), 0ul);
958 return technologies.Pass();
961 } // namespace chromeos