Less strict CHECK for DeviceCapabilities results.
[chromium-blink-merge.git] / chromeos / network / network_state_handler.cc
blobf3a93395d06a1878bfa3fc881f2eb9aa3cbb2714
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/location.h"
10 #include "base/logging.h"
11 #include "base/metrics/histogram.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/values.h"
16 #include "chromeos/network/device_state.h"
17 #include "chromeos/network/favorite_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 "chromeos/network/shill_property_util.h"
24 #include "third_party/cros_system_api/dbus/service_constants.h"
26 namespace chromeos {
28 namespace {
30 bool ConnectionStateChanged(NetworkState* network,
31 const std::string& prev_connection_state) {
32 return (network->connection_state() != prev_connection_state) &&
33 (network->connection_state() != shill::kStateIdle ||
34 !prev_connection_state.empty());
37 std::string GetManagedStateLogType(const ManagedState* state) {
38 switch (state->managed_type()) {
39 case ManagedState::MANAGED_TYPE_NETWORK:
40 return "Network";
41 case ManagedState::MANAGED_TYPE_FAVORITE:
42 return "Favorite";
43 case ManagedState::MANAGED_TYPE_DEVICE:
44 return "Device";
46 NOTREACHED();
47 return "";
50 std::string GetManagedStateLogName(const ManagedState* state) {
51 if (!state)
52 return "None";
53 return base::StringPrintf("%s (%s)", state->name().c_str(),
54 state->path().c_str());
57 } // namespace
59 const char NetworkStateHandler::kDefaultCheckPortalList[] =
60 "ethernet,wifi,cellular";
62 NetworkStateHandler::NetworkStateHandler() {
65 NetworkStateHandler::~NetworkStateHandler() {
66 STLDeleteContainerPointers(network_list_.begin(), network_list_.end());
67 STLDeleteContainerPointers(favorite_list_.begin(), favorite_list_.end());
68 STLDeleteContainerPointers(device_list_.begin(), device_list_.end());
71 void NetworkStateHandler::InitShillPropertyHandler() {
72 shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
73 shill_property_handler_->Init();
76 // static
77 NetworkStateHandler* NetworkStateHandler::InitializeForTest() {
78 NetworkStateHandler* handler = new NetworkStateHandler();
79 handler->InitShillPropertyHandler();
80 return handler;
83 void NetworkStateHandler::AddObserver(
84 NetworkStateHandlerObserver* observer,
85 const tracked_objects::Location& from_here) {
86 observers_.AddObserver(observer);
87 network_event_log::internal::AddEntry(
88 from_here.file_name(), from_here.line_number(),
89 network_event_log::LOG_LEVEL_DEBUG,
90 "NetworkStateHandler::AddObserver", "");
93 void NetworkStateHandler::RemoveObserver(
94 NetworkStateHandlerObserver* observer,
95 const tracked_objects::Location& from_here) {
96 observers_.RemoveObserver(observer);
97 network_event_log::internal::AddEntry(
98 from_here.file_name(), from_here.line_number(),
99 network_event_log::LOG_LEVEL_DEBUG,
100 "NetworkStateHandler::RemoveObserver", "");
103 void NetworkStateHandler::UpdateManagerProperties() {
104 NET_LOG_USER("UpdateManagerProperties", "");
105 shill_property_handler_->UpdateManagerProperties();
108 NetworkStateHandler::TechnologyState NetworkStateHandler::GetTechnologyState(
109 const NetworkTypePattern& type) const {
110 std::string technology = GetTechnologyForType(type);
111 TechnologyState state;
112 if (shill_property_handler_->IsTechnologyEnabled(technology))
113 state = TECHNOLOGY_ENABLED;
114 else if (shill_property_handler_->IsTechnologyEnabling(technology))
115 state = TECHNOLOGY_ENABLING;
116 else if (shill_property_handler_->IsTechnologyUninitialized(technology))
117 state = TECHNOLOGY_UNINITIALIZED;
118 else if (shill_property_handler_->IsTechnologyAvailable(technology))
119 state = TECHNOLOGY_AVAILABLE;
120 else
121 state = TECHNOLOGY_UNAVAILABLE;
122 VLOG(2) << "GetTechnologyState: " << type.ToDebugString() << " = " << state;
123 return state;
126 void NetworkStateHandler::SetTechnologyEnabled(
127 const NetworkTypePattern& type,
128 bool enabled,
129 const network_handler::ErrorCallback& error_callback) {
130 std::string technology = GetTechnologyForType(type);
131 NET_LOG_USER("SetTechnologyEnabled",
132 base::StringPrintf("%s:%d", technology.c_str(), enabled));
133 shill_property_handler_->SetTechnologyEnabled(
134 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())
143 return NULL;
144 return device;
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())
153 continue;
154 if (device->Matches(type))
155 return device->AsDeviceState();
157 return NULL;
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();
165 DCHECK(device);
166 if (!device->update_received())
167 continue;
168 if (device->Matches(type) && device->scanning())
169 return true;
171 return false;
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())
178 return NULL;
179 return network;
182 const NetworkState* NetworkStateHandler::DefaultNetwork() const {
183 if (network_list_.empty())
184 return NULL;
185 const NetworkState* network = network_list_.front()->AsNetworkState();
186 DCHECK(network);
187 if (!network->update_received() || !network->IsConnectedState())
188 return NULL;
189 return network;
192 const FavoriteState* NetworkStateHandler::DefaultFavoriteNetwork() const {
193 const NetworkState* default_network = DefaultNetwork();
194 if (!default_network)
195 return NULL;
196 const FavoriteState* default_favorite =
197 GetFavoriteState(default_network->path());
198 DCHECK(default_favorite);
199 DCHECK(default_favorite->update_received());
200 return default_favorite;
203 const NetworkState* NetworkStateHandler::ConnectedNetworkByType(
204 const NetworkTypePattern& type) const {
205 for (ManagedStateList::const_iterator iter = network_list_.begin();
206 iter != network_list_.end(); ++iter) {
207 const NetworkState* network = (*iter)->AsNetworkState();
208 DCHECK(network);
209 if (!network->update_received())
210 continue;
211 if (!network->IsConnectedState())
212 break; // Connected networks are listed first.
213 if (network->Matches(type))
214 return network;
216 return NULL;
219 const NetworkState* NetworkStateHandler::ConnectingNetworkByType(
220 const NetworkTypePattern& type) const {
221 for (ManagedStateList::const_iterator iter = network_list_.begin();
222 iter != network_list_.end(); ++iter) {
223 const NetworkState* network = (*iter)->AsNetworkState();
224 DCHECK(network);
225 if (!network->update_received() || network->IsConnectedState())
226 continue;
227 if (!network->IsConnectingState())
228 break; // Connected and connecting networks are listed first.
229 if (network->Matches(type))
230 return network;
232 return NULL;
235 const NetworkState* NetworkStateHandler::FirstNetworkByType(
236 const NetworkTypePattern& type) const {
237 for (ManagedStateList::const_iterator iter = network_list_.begin();
238 iter != network_list_.end(); ++iter) {
239 const NetworkState* network = (*iter)->AsNetworkState();
240 DCHECK(network);
241 if (!network->update_received())
242 continue;
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 device->GetFormattedMacAddress();
262 void NetworkStateHandler::GetNetworkList(NetworkStateList* list) const {
263 GetNetworkListByType(NetworkTypePattern::Default(), list);
266 void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type,
267 NetworkStateList* list) const {
268 DCHECK(list);
269 list->clear();
270 for (ManagedStateList::const_iterator iter = network_list_.begin();
271 iter != network_list_.end(); ++iter) {
272 const NetworkState* network = (*iter)->AsNetworkState();
273 DCHECK(network);
274 if (network->update_received() && network->Matches(type))
275 list->push_back(network);
279 void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const {
280 GetDeviceListByType(NetworkTypePattern::Default(), list);
283 void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type,
284 DeviceStateList* list) const {
285 DCHECK(list);
286 list->clear();
287 for (ManagedStateList::const_iterator iter = device_list_.begin();
288 iter != device_list_.end(); ++iter) {
289 const DeviceState* device = (*iter)->AsDeviceState();
290 DCHECK(device);
291 if (device->update_received() && device->Matches(type))
292 list->push_back(device);
296 void NetworkStateHandler::GetFavoriteList(FavoriteStateList* list) const {
297 GetFavoriteListByType(NetworkTypePattern::Default(), list);
300 void NetworkStateHandler::GetFavoriteListByType(const NetworkTypePattern& type,
301 FavoriteStateList* list) const {
302 DCHECK(list);
303 FavoriteStateList result;
304 list->clear();
305 for (ManagedStateList::const_iterator iter = favorite_list_.begin();
306 iter != favorite_list_.end(); ++iter) {
307 const FavoriteState* favorite = (*iter)->AsFavoriteState();
308 DCHECK(favorite);
309 if (favorite->update_received() && favorite->is_favorite() &&
310 favorite->Matches(type)) {
311 list->push_back(favorite);
316 const FavoriteState* NetworkStateHandler::GetFavoriteState(
317 const std::string& service_path) const {
318 ManagedState* managed =
319 GetModifiableManagedState(&favorite_list_, service_path);
320 if (!managed)
321 return NULL;
322 const FavoriteState* favorite = managed->AsFavoriteState();
323 DCHECK(favorite);
324 if (!favorite->update_received() || !favorite->is_favorite())
325 return NULL;
326 return favorite;
329 void NetworkStateHandler::RequestScan() const {
330 NET_LOG_USER("RequestScan", "");
331 shill_property_handler_->RequestScan();
334 void NetworkStateHandler::WaitForScan(const std::string& type,
335 const base::Closure& callback) {
336 scan_complete_callbacks_[type].push_back(callback);
337 if (!GetScanningByType(NetworkTypePattern::Primitive(type)))
338 RequestScan();
341 void NetworkStateHandler::ConnectToBestWifiNetwork() {
342 NET_LOG_USER("ConnectToBestWifiNetwork", "");
343 WaitForScan(shill::kTypeWifi,
344 base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices,
345 shill_property_handler_->AsWeakPtr()));
348 void NetworkStateHandler::RequestUpdateForNetwork(
349 const std::string& service_path) {
350 NetworkState* network = GetModifiableNetworkState(service_path);
351 if (network)
352 network->set_update_requested(true);
353 NET_LOG_EVENT("RequestUpdate", service_path);
354 shill_property_handler_->RequestProperties(
355 ManagedState::MANAGED_TYPE_NETWORK, service_path);
358 void NetworkStateHandler::RequestUpdateForAllNetworks() {
359 NET_LOG_EVENT("RequestUpdateForAllNetworks", "");
360 for (ManagedStateList::iterator iter = network_list_.begin();
361 iter != network_list_.end(); ++iter) {
362 ManagedState* network = *iter;
363 network->set_update_requested(true);
364 shill_property_handler_->RequestProperties(
365 ManagedState::MANAGED_TYPE_NETWORK, network->path());
369 void NetworkStateHandler::SetCheckPortalList(
370 const std::string& check_portal_list) {
371 NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
372 shill_property_handler_->SetCheckPortalList(check_portal_list);
375 const FavoriteState* NetworkStateHandler::GetEAPForEthernet(
376 const std::string& service_path) const {
377 const NetworkState* network = GetNetworkState(service_path);
378 if (!network) {
379 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path);
380 return NULL;
382 if (network->type() != shill::kTypeEthernet) {
383 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path);
384 return NULL;
386 if (!network->IsConnectedState())
387 return NULL;
389 // The same EAP service is shared for all ethernet services/devices.
390 // However EAP is used/enabled per device and only if the connection was
391 // successfully established.
392 const DeviceState* device = GetDeviceState(network->device_path());
393 if (!device) {
394 NET_LOG_ERROR(
395 "GetEAPForEthernet",
396 base::StringPrintf("Unknown device %s of connected ethernet service %s",
397 network->device_path().c_str(),
398 service_path.c_str()));
399 return NULL;
401 if (!device->eap_authentication_completed())
402 return NULL;
404 FavoriteStateList list;
405 GetFavoriteListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap),
406 &list);
407 if (list.empty()) {
408 NET_LOG_ERROR("GetEAPForEthernet",
409 base::StringPrintf(
410 "Ethernet service %s connected using EAP, but no "
411 "EAP service found.",
412 service_path.c_str()));
413 return NULL;
415 DCHECK(list.size() == 1);
416 return list.front();
419 void NetworkStateHandler::GetNetworkStatePropertiesForTest(
420 base::DictionaryValue* dictionary) const {
421 for (ManagedStateList::const_iterator iter = network_list_.begin();
422 iter != network_list_.end(); ++iter) {
423 base::DictionaryValue* network_dict = new base::DictionaryValue;
424 (*iter)->AsNetworkState()->GetProperties(network_dict);
425 dictionary->SetWithoutPathExpansion((*iter)->path(), network_dict);
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(base::StringPrintf("UpdateManagedList:%d", type),
436 base::StringPrintf("%" PRIuS, entries.GetSize()));
437 // Create a map of existing entries. Assumes all entries in |managed_list|
438 // are unique.
439 std::map<std::string, ManagedState*> 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 std::map<std::string, ManagedState*>::iterator found =
459 managed_map.find(path);
460 ManagedState* managed;
461 if (found == managed_map.end()) {
462 if (list_entries.count(path) != 0) {
463 NET_LOG_ERROR("Duplicate entry in list", path);
464 continue;
466 managed = ManagedState::Create(type, path);
467 managed_list->push_back(managed);
468 } else {
469 managed = found->second;
470 managed_list->push_back(managed);
471 managed_map.erase(found);
473 list_entries.insert(path);
475 // Delete any remaining entries in managed_map.
476 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
479 void NetworkStateHandler::ProfileListChanged() {
480 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
481 for (ManagedStateList::iterator iter = network_list_.begin();
482 iter != network_list_.end(); ++iter) {
483 shill_property_handler_->RequestProperties(
484 ManagedState::MANAGED_TYPE_NETWORK, (*iter)->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);
494 if (!managed) {
495 if (type != ManagedState::MANAGED_TYPE_FAVORITE) {
496 // The network has been removed from the list of visible networks.
497 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path);
498 return;
500 // A Favorite may not have been created yet if it was added later (e.g.
501 // through ConfigureService) since ServiceCompleteList updates are not
502 // emitted. Add and update the state here.
503 managed = new FavoriteState(path);
504 managed_list->push_back(managed);
506 managed->set_update_received();
508 std::string desc = GetManagedStateLogType(managed) + " PropertiesReceived";
509 NET_LOG_DEBUG(desc, GetManagedStateLogName(managed));
511 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
512 UpdateNetworkStateProperties(managed->AsNetworkState(), properties);
513 } else {
514 // Device, Favorite
515 for (base::DictionaryValue::Iterator iter(properties);
516 !iter.IsAtEnd(); iter.Advance()) {
517 managed->PropertyChanged(iter.key(), iter.value());
519 managed->InitialPropertiesReceived(properties);
521 managed->set_update_requested(false);
524 void NetworkStateHandler::UpdateNetworkStateProperties(
525 NetworkState* network,
526 const base::DictionaryValue& properties) {
527 DCHECK(network);
528 bool network_property_updated = false;
529 std::string prev_connection_state = network->connection_state();
530 for (base::DictionaryValue::Iterator iter(properties);
531 !iter.IsAtEnd(); iter.Advance()) {
532 if (network->PropertyChanged(iter.key(), iter.value()))
533 network_property_updated = true;
535 network_property_updated |= network->InitialPropertiesReceived(properties);
536 // Notify observers of NetworkState changes.
537 if (network_property_updated || network->update_requested()) {
538 // Signal connection state changed after all properties have been updated.
539 if (ConnectionStateChanged(network, prev_connection_state))
540 OnNetworkConnectionStateChanged(network);
541 NetworkPropertiesUpdated(network);
545 void NetworkStateHandler::UpdateNetworkServiceProperty(
546 const std::string& service_path,
547 const std::string& key,
548 const base::Value& value) {
549 // Update any associated FavoriteState.
550 ManagedState* favorite =
551 GetModifiableManagedState(&favorite_list_, service_path);
552 bool changed = false;
553 if (favorite)
554 changed |= favorite->PropertyChanged(key, value);
556 // Update the NetworkState.
557 NetworkState* network = GetModifiableNetworkState(service_path);
558 if (!network)
559 return;
560 std::string prev_connection_state = network->connection_state();
561 std::string prev_profile_path = network->profile_path();
562 changed |= network->PropertyChanged(key, value);
563 if (!changed)
564 return;
566 if (key == shill::kStateProperty) {
567 if (ConnectionStateChanged(network, prev_connection_state)) {
568 OnNetworkConnectionStateChanged(network);
569 // If the connection state changes, other properties such as IPConfig
570 // may have changed, so request a full update.
571 RequestUpdateForNetwork(service_path);
573 } else {
574 std::string value_str;
575 value.GetAsString(&value_str);
576 // Some property changes are noisy and not interesting:
577 // * Wifi SignalStrength
578 // * WifiFrequencyList updates
579 // * Device property changes to "/" (occurs before a service is removed)
580 if (key != shill::kSignalStrengthProperty &&
581 key != shill::kWifiFrequencyListProperty &&
582 (key != shill::kDeviceProperty || value_str != "/")) {
583 // Trigger a default network update for interesting changes only.
584 if (network->path() == default_network_path_)
585 OnDefaultNetworkChanged();
586 // Log interesting event.
587 std::string detail = network->name() + "." + key;
588 detail += " = " + network_event_log::ValueAsString(value);
589 network_event_log::LogLevel log_level;
590 if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) {
591 log_level = network_event_log::LOG_LEVEL_ERROR;
592 } else {
593 log_level = network_event_log::LOG_LEVEL_EVENT;
595 NET_LOG_LEVEL(log_level, "NetworkPropertyUpdated", detail);
599 // All property updates signal 'NetworkPropertiesUpdated'.
600 NetworkPropertiesUpdated(network);
602 // If added to a Profile, request a full update so that a FavoriteState
603 // gets created.
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 DeviceState* device = GetModifiableDeviceState(device_path);
612 if (!device)
613 return;
614 if (!device->PropertyChanged(key, value))
615 return;
617 std::string detail = device->name() + "." + key;
618 detail += " = " + network_event_log::ValueAsString(value);
619 NET_LOG_EVENT("DevicePropertyUpdated", detail);
621 NotifyDeviceListChanged();
623 if (key == shill::kScanningProperty && device->scanning() == false)
624 ScanCompleted(device->type());
625 if (key == shill::kEapAuthenticationCompletedProperty) {
626 // Notify a change for each Ethernet service using this device.
627 NetworkStateList ethernet_services;
628 GetNetworkListByType(NetworkTypePattern::Ethernet(), &ethernet_services);
629 for (NetworkStateList::const_iterator it = ethernet_services.begin();
630 it != ethernet_services.end(); ++it) {
631 const NetworkState* ethernet_service = *it;
632 if (ethernet_service->update_received() ||
633 ethernet_service->device_path() != device->path()) {
634 continue;
636 RequestUpdateForNetwork(ethernet_service->path());
641 void NetworkStateHandler::CheckPortalListChanged(
642 const std::string& check_portal_list) {
643 check_portal_list_ = check_portal_list;
646 void NetworkStateHandler::TechnologyListChanged() {
647 // Eventually we would like to replace Technology state with Device state.
648 // For now, treat technology state changes as device list changes.
649 NotifyDeviceListChanged();
652 void NetworkStateHandler::ManagedStateListChanged(
653 ManagedState::ManagedType type) {
654 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
655 // Notify observers that the list of networks has changed.
656 NET_LOG_EVENT("NetworkListChanged",
657 base::StringPrintf("Size:%" PRIuS, network_list_.size()));
658 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
659 NetworkListChanged());
660 // The list order may have changed, so check if the default network changed.
661 if (CheckDefaultNetworkChanged())
662 OnDefaultNetworkChanged();
663 // Update UMA stats.
664 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", network_list_.size());
665 } else if (type == ManagedState::MANAGED_TYPE_FAVORITE) {
666 NET_LOG_DEBUG("FavoriteListChanged",
667 base::StringPrintf("Size:%" PRIuS, favorite_list_.size()));
668 // The FavoriteState list only changes when the NetworkState list changes,
669 // so no need to signal observers here again.
671 // Update UMA stats.
672 size_t shared = 0, unshared = 0;
673 for (ManagedStateList::iterator iter = favorite_list_.begin();
674 iter != favorite_list_.end(); ++iter) {
675 FavoriteState* favorite = (*iter)->AsFavoriteState();
676 if (!favorite->is_favorite())
677 continue;
678 if (favorite->IsPrivate())
679 ++unshared;
680 else
681 ++shared;
683 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared);
684 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared);
685 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
686 NotifyDeviceListChanged();
687 } else {
688 NOTREACHED();
692 //------------------------------------------------------------------------------
693 // Private methods
695 void NetworkStateHandler::NotifyDeviceListChanged() {
696 NET_LOG_DEBUG("NotifyDeviceListChanged",
697 base::StringPrintf("Size:%" PRIuS, device_list_.size()));
698 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
699 DeviceListChanged());
702 DeviceState* NetworkStateHandler::GetModifiableDeviceState(
703 const std::string& device_path) const {
704 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
705 if (!managed)
706 return NULL;
707 return managed->AsDeviceState();
710 NetworkState* NetworkStateHandler::GetModifiableNetworkState(
711 const std::string& service_path) const {
712 ManagedState* managed =
713 GetModifiableManagedState(&network_list_, service_path);
714 if (!managed)
715 return NULL;
716 return managed->AsNetworkState();
719 ManagedState* NetworkStateHandler::GetModifiableManagedState(
720 const ManagedStateList* managed_list,
721 const std::string& path) const {
722 for (ManagedStateList::const_iterator iter = managed_list->begin();
723 iter != managed_list->end(); ++iter) {
724 ManagedState* managed = *iter;
725 if (managed->path() == path)
726 return managed;
728 return NULL;
731 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
732 ManagedState::ManagedType type) {
733 switch (type) {
734 case ManagedState::MANAGED_TYPE_NETWORK:
735 return &network_list_;
736 case ManagedState::MANAGED_TYPE_FAVORITE:
737 return &favorite_list_;
738 case ManagedState::MANAGED_TYPE_DEVICE:
739 return &device_list_;
741 NOTREACHED();
742 return NULL;
745 void NetworkStateHandler::OnNetworkConnectionStateChanged(
746 NetworkState* network) {
747 DCHECK(network);
748 NET_LOG_EVENT("NetworkConnectionStateChanged", base::StringPrintf(
749 "%s:%s", GetManagedStateLogName(network).c_str(),
750 network->connection_state().c_str()));
751 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
752 NetworkConnectionStateChanged(network));
753 if (CheckDefaultNetworkChanged() || network->path() == default_network_path_)
754 OnDefaultNetworkChanged();
757 bool NetworkStateHandler::CheckDefaultNetworkChanged() {
758 std::string new_default_network_path;
759 const NetworkState* new_default_network = DefaultNetwork();
760 if (new_default_network)
761 new_default_network_path = new_default_network->path();
762 if (new_default_network_path == default_network_path_)
763 return false;
764 default_network_path_ = new_default_network_path;
765 return true;
768 void NetworkStateHandler::OnDefaultNetworkChanged() {
769 const NetworkState* default_network = DefaultNetwork();
770 NET_LOG_EVENT("DefaultNetworkChanged",
771 GetManagedStateLogName(default_network));
772 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
773 DefaultNetworkChanged(default_network));
776 void NetworkStateHandler::NetworkPropertiesUpdated(
777 const NetworkState* network) {
778 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
779 NetworkPropertiesUpdated(network));
782 void NetworkStateHandler::ScanCompleted(const std::string& type) {
783 size_t num_callbacks = scan_complete_callbacks_.count(type);
784 NET_LOG_EVENT("ScanCompleted",
785 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks));
786 if (num_callbacks == 0)
787 return;
788 ScanCallbackList& callback_list = scan_complete_callbacks_[type];
789 for (ScanCallbackList::iterator iter = callback_list.begin();
790 iter != callback_list.end(); ++iter) {
791 (*iter).Run();
793 scan_complete_callbacks_.erase(type);
796 std::string NetworkStateHandler::GetTechnologyForType(
797 const NetworkTypePattern& type) const {
798 if (type.MatchesType(shill::kTypeEthernet))
799 return shill::kTypeEthernet;
801 if (type.MatchesType(shill::kTypeWifi))
802 return shill::kTypeWifi;
804 if (type.Equals(NetworkTypePattern::Wimax()))
805 return shill::kTypeWimax;
807 // Prefer Wimax over Cellular only if it's available.
808 if (type.MatchesType(shill::kTypeWimax) &&
809 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
810 return shill::kTypeWimax;
813 if (type.MatchesType(shill::kTypeCellular))
814 return shill::kTypeCellular;
816 NOTREACHED();
817 return std::string();
820 } // namespace chromeos