Replace misc. network and power stub flags with more flexible ones
[chromium-blink-merge.git] / chromeos / network / network_state_handler.cc
blob972b6759ea6e205e4fdb7fd5dc1852b376806878
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 (default_network_path_.empty())
184 return NULL;
185 return GetNetworkState(default_network_path_);
188 const FavoriteState* NetworkStateHandler::DefaultFavoriteNetwork() const {
189 const NetworkState* default_network = DefaultNetwork();
190 if (!default_network)
191 return NULL;
192 const FavoriteState* default_favorite =
193 GetFavoriteState(default_network->path());
194 DCHECK(default_network->type() != shill::kTypeWifi ||
195 default_favorite) << "No favorite for: " << default_network->path();
196 DCHECK(!default_favorite || default_favorite->update_received())
197 << "No update received for: " << default_network->path();
198 return default_favorite;
201 const NetworkState* NetworkStateHandler::ConnectedNetworkByType(
202 const NetworkTypePattern& type) const {
203 for (ManagedStateList::const_iterator iter = network_list_.begin();
204 iter != network_list_.end(); ++iter) {
205 const NetworkState* network = (*iter)->AsNetworkState();
206 DCHECK(network);
207 if (!network->update_received())
208 continue;
209 if (!network->IsConnectedState())
210 break; // Connected networks are listed first.
211 if (network->Matches(type))
212 return network;
214 return NULL;
217 const NetworkState* NetworkStateHandler::ConnectingNetworkByType(
218 const NetworkTypePattern& type) const {
219 for (ManagedStateList::const_iterator iter = network_list_.begin();
220 iter != network_list_.end(); ++iter) {
221 const NetworkState* network = (*iter)->AsNetworkState();
222 DCHECK(network);
223 if (!network->update_received() || network->IsConnectedState())
224 continue;
225 if (!network->IsConnectingState())
226 break; // Connected and connecting networks are listed first.
227 if (network->Matches(type))
228 return network;
230 return NULL;
233 const NetworkState* NetworkStateHandler::FirstNetworkByType(
234 const NetworkTypePattern& type) const {
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->Matches(type))
242 return network;
244 return NULL;
247 std::string NetworkStateHandler::FormattedHardwareAddressForType(
248 const NetworkTypePattern& type) const {
249 const DeviceState* device = NULL;
250 const NetworkState* network = ConnectedNetworkByType(type);
251 if (network)
252 device = GetDeviceState(network->device_path());
253 else
254 device = GetDeviceStateByType(type);
255 if (!device)
256 return std::string();
257 return device->GetFormattedMacAddress();
260 void NetworkStateHandler::GetNetworkList(NetworkStateList* list) const {
261 GetNetworkListByType(NetworkTypePattern::Default(), list);
264 void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type,
265 NetworkStateList* list) const {
266 DCHECK(list);
267 list->clear();
268 for (ManagedStateList::const_iterator iter = network_list_.begin();
269 iter != network_list_.end(); ++iter) {
270 const NetworkState* network = (*iter)->AsNetworkState();
271 DCHECK(network);
272 if (network->update_received() && network->Matches(type))
273 list->push_back(network);
277 void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const {
278 GetDeviceListByType(NetworkTypePattern::Default(), list);
281 void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type,
282 DeviceStateList* list) const {
283 DCHECK(list);
284 list->clear();
285 for (ManagedStateList::const_iterator iter = device_list_.begin();
286 iter != device_list_.end(); ++iter) {
287 const DeviceState* device = (*iter)->AsDeviceState();
288 DCHECK(device);
289 if (device->update_received() && device->Matches(type))
290 list->push_back(device);
294 void NetworkStateHandler::GetFavoriteList(FavoriteStateList* list) const {
295 GetFavoriteListByType(NetworkTypePattern::Default(), list);
298 void NetworkStateHandler::GetFavoriteListByType(const NetworkTypePattern& type,
299 FavoriteStateList* list) const {
300 DCHECK(list);
301 FavoriteStateList result;
302 list->clear();
303 for (ManagedStateList::const_iterator iter = favorite_list_.begin();
304 iter != favorite_list_.end(); ++iter) {
305 const FavoriteState* favorite = (*iter)->AsFavoriteState();
306 DCHECK(favorite);
307 if (favorite->update_received() && favorite->is_favorite() &&
308 favorite->Matches(type)) {
309 list->push_back(favorite);
314 const FavoriteState* NetworkStateHandler::GetFavoriteState(
315 const std::string& service_path) const {
316 ManagedState* managed =
317 GetModifiableManagedState(&favorite_list_, service_path);
318 if (!managed)
319 return NULL;
320 const FavoriteState* favorite = managed->AsFavoriteState();
321 DCHECK(favorite);
322 if (!favorite->update_received() || !favorite->is_favorite())
323 return NULL;
324 return favorite;
327 void NetworkStateHandler::RequestScan() const {
328 NET_LOG_USER("RequestScan", "");
329 shill_property_handler_->RequestScan();
332 void NetworkStateHandler::WaitForScan(const std::string& type,
333 const base::Closure& callback) {
334 scan_complete_callbacks_[type].push_back(callback);
335 if (!GetScanningByType(NetworkTypePattern::Primitive(type)))
336 RequestScan();
339 void NetworkStateHandler::ConnectToBestWifiNetwork() {
340 NET_LOG_USER("ConnectToBestWifiNetwork", "");
341 WaitForScan(shill::kTypeWifi,
342 base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices,
343 shill_property_handler_->AsWeakPtr()));
346 void NetworkStateHandler::RequestUpdateForNetwork(
347 const std::string& service_path) {
348 NetworkState* network = GetModifiableNetworkState(service_path);
349 if (network)
350 network->set_update_requested(true);
351 NET_LOG_EVENT("RequestUpdate", service_path);
352 shill_property_handler_->RequestProperties(
353 ManagedState::MANAGED_TYPE_NETWORK, service_path);
356 void NetworkStateHandler::RequestUpdateForAllNetworks() {
357 NET_LOG_EVENT("RequestUpdateForAllNetworks", "");
358 for (ManagedStateList::iterator iter = network_list_.begin();
359 iter != network_list_.end(); ++iter) {
360 ManagedState* network = *iter;
361 network->set_update_requested(true);
362 shill_property_handler_->RequestProperties(
363 ManagedState::MANAGED_TYPE_NETWORK, network->path());
367 void NetworkStateHandler::SetCheckPortalList(
368 const std::string& check_portal_list) {
369 NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
370 shill_property_handler_->SetCheckPortalList(check_portal_list);
373 const FavoriteState* NetworkStateHandler::GetEAPForEthernet(
374 const std::string& service_path) const {
375 const NetworkState* network = GetNetworkState(service_path);
376 if (!network) {
377 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path);
378 return NULL;
380 if (network->type() != shill::kTypeEthernet) {
381 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path);
382 return NULL;
384 if (!network->IsConnectedState())
385 return NULL;
387 // The same EAP service is shared for all ethernet services/devices.
388 // However EAP is used/enabled per device and only if the connection was
389 // successfully established.
390 const DeviceState* device = GetDeviceState(network->device_path());
391 if (!device) {
392 NET_LOG_ERROR(
393 "GetEAPForEthernet",
394 base::StringPrintf("Unknown device %s of connected ethernet service %s",
395 network->device_path().c_str(),
396 service_path.c_str()));
397 return NULL;
399 if (!device->eap_authentication_completed())
400 return NULL;
402 FavoriteStateList list;
403 GetFavoriteListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap),
404 &list);
405 if (list.empty()) {
406 NET_LOG_ERROR("GetEAPForEthernet",
407 base::StringPrintf(
408 "Ethernet service %s connected using EAP, but no "
409 "EAP service found.",
410 service_path.c_str()));
411 return NULL;
413 DCHECK(list.size() == 1);
414 return list.front();
417 void NetworkStateHandler::GetNetworkStatePropertiesForTest(
418 base::DictionaryValue* dictionary) const {
419 for (ManagedStateList::const_iterator iter = network_list_.begin();
420 iter != network_list_.end(); ++iter) {
421 base::DictionaryValue* network_dict = new base::DictionaryValue;
422 (*iter)->AsNetworkState()->GetProperties(network_dict);
423 dictionary->SetWithoutPathExpansion((*iter)->path(), network_dict);
427 //------------------------------------------------------------------------------
428 // ShillPropertyHandler::Delegate overrides
430 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type,
431 const base::ListValue& entries) {
432 ManagedStateList* managed_list = GetManagedList(type);
433 NET_LOG_DEBUG(base::StringPrintf("UpdateManagedList:%d", type),
434 base::StringPrintf("%" PRIuS, entries.GetSize()));
435 // Create a map of existing entries. Assumes all entries in |managed_list|
436 // are unique.
437 std::map<std::string, ManagedState*> managed_map;
438 for (ManagedStateList::iterator iter = managed_list->begin();
439 iter != managed_list->end(); ++iter) {
440 ManagedState* managed = *iter;
441 DCHECK(!ContainsKey(managed_map, managed->path()));
442 managed_map[managed->path()] = managed;
444 // Clear the list (pointers are temporarily owned by managed_map).
445 managed_list->clear();
446 // Updates managed_list and request updates for new entries.
447 std::set<std::string> list_entries;
448 for (base::ListValue::const_iterator iter = entries.begin();
449 iter != entries.end(); ++iter) {
450 std::string path;
451 (*iter)->GetAsString(&path);
452 if (path.empty() || path == shill::kFlimflamServicePath) {
453 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path);
454 continue;
456 std::map<std::string, ManagedState*>::iterator found =
457 managed_map.find(path);
458 ManagedState* managed;
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 managed = ManagedState::Create(type, path);
465 managed_list->push_back(managed);
466 } else {
467 managed = found->second;
468 managed_list->push_back(managed);
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 shill_property_handler_->RequestProperties(
482 ManagedState::MANAGED_TYPE_NETWORK, (*iter)->path());
486 void NetworkStateHandler::UpdateManagedStateProperties(
487 ManagedState::ManagedType type,
488 const std::string& path,
489 const base::DictionaryValue& properties) {
490 ManagedStateList* managed_list = GetManagedList(type);
491 ManagedState* managed = GetModifiableManagedState(managed_list, path);
492 if (!managed) {
493 if (type != ManagedState::MANAGED_TYPE_FAVORITE) {
494 // The network has been removed from the list of visible networks.
495 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path);
496 return;
498 // A Favorite may not have been created yet if it was added later (e.g.
499 // through ConfigureService) since ServiceCompleteList updates are not
500 // emitted. Add and update the state here.
501 managed = new FavoriteState(path);
502 managed_list->push_back(managed);
504 managed->set_update_received();
506 std::string desc = GetManagedStateLogType(managed) + " PropertiesReceived";
507 NET_LOG_DEBUG(desc, GetManagedStateLogName(managed));
509 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
510 UpdateNetworkStateProperties(managed->AsNetworkState(), properties);
511 } else {
512 // Device, Favorite
513 for (base::DictionaryValue::Iterator iter(properties);
514 !iter.IsAtEnd(); iter.Advance()) {
515 managed->PropertyChanged(iter.key(), iter.value());
517 managed->InitialPropertiesReceived(properties);
519 managed->set_update_requested(false);
522 void NetworkStateHandler::UpdateNetworkStateProperties(
523 NetworkState* network,
524 const base::DictionaryValue& properties) {
525 DCHECK(network);
526 bool network_property_updated = false;
527 std::string prev_connection_state = network->connection_state();
528 for (base::DictionaryValue::Iterator iter(properties);
529 !iter.IsAtEnd(); iter.Advance()) {
530 if (network->PropertyChanged(iter.key(), iter.value()))
531 network_property_updated = true;
533 network_property_updated |= network->InitialPropertiesReceived(properties);
534 // Notify observers of NetworkState changes.
535 if (network_property_updated || network->update_requested()) {
536 // Signal connection state changed after all properties have been updated.
537 if (ConnectionStateChanged(network, prev_connection_state))
538 OnNetworkConnectionStateChanged(network);
539 NET_LOG_EVENT("NetworkPropertiesUpdated", GetManagedStateLogName(network));
540 NotifyNetworkPropertiesUpdated(network);
544 void NetworkStateHandler::UpdateNetworkServiceProperty(
545 const std::string& service_path,
546 const std::string& key,
547 const base::Value& value) {
548 // Update any associated FavoriteState.
549 ManagedState* favorite =
550 GetModifiableManagedState(&favorite_list_, service_path);
551 bool changed = false;
552 if (favorite)
553 changed |= favorite->PropertyChanged(key, value);
555 // Update the NetworkState.
556 NetworkState* network = GetModifiableNetworkState(service_path);
557 if (!network)
558 return;
559 std::string prev_connection_state = network->connection_state();
560 std::string prev_profile_path = network->profile_path();
561 changed |= network->PropertyChanged(key, value);
562 if (!changed)
563 return;
565 if (key == shill::kStateProperty) {
566 if (ConnectionStateChanged(network, prev_connection_state)) {
567 OnNetworkConnectionStateChanged(network);
568 // If the connection state changes, other properties such as IPConfig
569 // may have changed, so request a full update.
570 RequestUpdateForNetwork(service_path);
572 } else {
573 std::string value_str;
574 value.GetAsString(&value_str);
575 // Some property changes are noisy and not interesting:
576 // * Wifi SignalStrength
577 // * WifiFrequencyList updates
578 // * Device property changes to "/" (occurs before a service is removed)
579 if (key != shill::kSignalStrengthProperty &&
580 key != shill::kWifiFrequencyListProperty &&
581 (key != shill::kDeviceProperty || value_str != "/")) {
582 std::string log_event = "NetworkPropertyUpdated";
583 // Trigger a default network update for interesting changes only.
584 if (network->path() == default_network_path_) {
585 NotifyDefaultNetworkChanged(network);
586 log_event = "Default" + log_event;
588 // Log event.
589 std::string detail = network->name() + "." + key;
590 detail += " = " + network_event_log::ValueAsString(value);
591 network_event_log::LogLevel log_level;
592 if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) {
593 log_level = network_event_log::LOG_LEVEL_ERROR;
594 } else {
595 log_level = network_event_log::LOG_LEVEL_EVENT;
597 NET_LOG_LEVEL(log_level, log_event, detail);
601 // All property updates signal 'NetworkPropertiesUpdated'.
602 NotifyNetworkPropertiesUpdated(network);
604 // If added to a Profile, request a full update so that a FavoriteState
605 // gets created.
606 if (prev_profile_path.empty() && !network->profile_path().empty())
607 RequestUpdateForNetwork(service_path);
610 void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path,
611 const std::string& key,
612 const base::Value& value) {
613 DeviceState* device = GetModifiableDeviceState(device_path);
614 if (!device)
615 return;
616 if (!device->PropertyChanged(key, value))
617 return;
619 std::string detail = device->name() + "." + key;
620 detail += " = " + network_event_log::ValueAsString(value);
621 NET_LOG_EVENT("DevicePropertyUpdated", detail);
623 NotifyDeviceListChanged();
625 if (key == shill::kScanningProperty && device->scanning() == false)
626 ScanCompleted(device->type());
627 if (key == shill::kEapAuthenticationCompletedProperty) {
628 // Notify a change for each Ethernet service using this device.
629 NetworkStateList ethernet_services;
630 GetNetworkListByType(NetworkTypePattern::Ethernet(), &ethernet_services);
631 for (NetworkStateList::const_iterator it = ethernet_services.begin();
632 it != ethernet_services.end(); ++it) {
633 const NetworkState* ethernet_service = *it;
634 if (ethernet_service->update_received() ||
635 ethernet_service->device_path() != device->path()) {
636 continue;
638 RequestUpdateForNetwork(ethernet_service->path());
643 void NetworkStateHandler::CheckPortalListChanged(
644 const std::string& check_portal_list) {
645 check_portal_list_ = check_portal_list;
648 void NetworkStateHandler::TechnologyListChanged() {
649 // Eventually we would like to replace Technology state with Device state.
650 // For now, treat technology state changes as device list changes.
651 NotifyDeviceListChanged();
654 void NetworkStateHandler::ManagedStateListChanged(
655 ManagedState::ManagedType type) {
656 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
657 // Notify observers that the list of networks has changed.
658 NET_LOG_EVENT("NetworkListChanged",
659 base::StringPrintf("Size:%" PRIuS, network_list_.size()));
660 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
661 NetworkListChanged());
662 // Update UMA stats.
663 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", network_list_.size());
664 } else if (type == ManagedState::MANAGED_TYPE_FAVORITE) {
665 NET_LOG_DEBUG("FavoriteListChanged",
666 base::StringPrintf("Size:%" PRIuS, favorite_list_.size()));
667 // The FavoriteState list only changes when the NetworkState list changes,
668 // so no need to signal observers here again.
670 // Update UMA stats.
671 size_t shared = 0, unshared = 0;
672 for (ManagedStateList::iterator iter = favorite_list_.begin();
673 iter != favorite_list_.end(); ++iter) {
674 FavoriteState* favorite = (*iter)->AsFavoriteState();
675 if (!favorite->is_favorite())
676 continue;
677 if (favorite->IsPrivate())
678 ++unshared;
679 else
680 ++shared;
682 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared);
683 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared);
684 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
685 NotifyDeviceListChanged();
686 } else {
687 NOTREACHED();
691 void NetworkStateHandler::DefaultNetworkServiceChanged(
692 const std::string& service_path) {
693 // Shill uses '/' for empty service path values; check explicitly for that.
694 const char* kEmptyServicePath = "/";
695 if (service_path == kEmptyServicePath)
696 default_network_path_.clear();
697 else
698 default_network_path_ = service_path;
699 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_);
700 const NetworkState* network = NULL;
701 if (!default_network_path_.empty()) {
702 network = GetNetworkState(default_network_path_);
703 if (!network) {
704 // If NetworkState is not available yet, do not notify observers here,
705 // they will be notified when the state is received.
706 NET_LOG_DEBUG("Default NetworkState not available",
707 default_network_path_);
708 return;
711 if (network && !network->IsConnectedState()) {
712 NET_LOG_ERROR(
713 "DefaultNetwork is not connected: " + network->connection_state(),
714 network->path());
716 NotifyDefaultNetworkChanged(network);
719 //------------------------------------------------------------------------------
720 // Private methods
722 void NetworkStateHandler::NotifyDeviceListChanged() {
723 NET_LOG_DEBUG("NotifyDeviceListChanged",
724 base::StringPrintf("Size:%" PRIuS, device_list_.size()));
725 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
726 DeviceListChanged());
729 DeviceState* NetworkStateHandler::GetModifiableDeviceState(
730 const std::string& device_path) const {
731 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
732 if (!managed)
733 return NULL;
734 return managed->AsDeviceState();
737 NetworkState* NetworkStateHandler::GetModifiableNetworkState(
738 const std::string& service_path) const {
739 ManagedState* managed =
740 GetModifiableManagedState(&network_list_, service_path);
741 if (!managed)
742 return NULL;
743 return managed->AsNetworkState();
746 ManagedState* NetworkStateHandler::GetModifiableManagedState(
747 const ManagedStateList* managed_list,
748 const std::string& path) const {
749 for (ManagedStateList::const_iterator iter = managed_list->begin();
750 iter != managed_list->end(); ++iter) {
751 ManagedState* managed = *iter;
752 if (managed->path() == path)
753 return managed;
755 return NULL;
758 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
759 ManagedState::ManagedType type) {
760 switch (type) {
761 case ManagedState::MANAGED_TYPE_NETWORK:
762 return &network_list_;
763 case ManagedState::MANAGED_TYPE_FAVORITE:
764 return &favorite_list_;
765 case ManagedState::MANAGED_TYPE_DEVICE:
766 return &device_list_;
768 NOTREACHED();
769 return NULL;
772 void NetworkStateHandler::OnNetworkConnectionStateChanged(
773 NetworkState* network) {
774 DCHECK(network);
775 std::string event = "NetworkConnectionStateChanged";
776 if (network->path() == default_network_path_) {
777 event = "Default" + event;
778 if (!network->IsConnectedState()) {
779 NET_LOG_ERROR(
780 "DefaultNetwork is not connected: " + network->connection_state(),
781 network->path());
784 NET_LOG_EVENT(event + ": " + network->connection_state(),
785 GetManagedStateLogName(network));
786 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
787 NetworkConnectionStateChanged(network));
788 if (network->path() == default_network_path_)
789 NotifyDefaultNetworkChanged(network);
792 void NetworkStateHandler::NotifyDefaultNetworkChanged(
793 const NetworkState* default_network) {
794 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
795 DefaultNetworkChanged(default_network));
798 void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
799 const NetworkState* network) {
800 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
801 NetworkPropertiesUpdated(network));
804 void NetworkStateHandler::ScanCompleted(const std::string& type) {
805 size_t num_callbacks = scan_complete_callbacks_.count(type);
806 NET_LOG_EVENT("ScanCompleted",
807 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks));
808 if (num_callbacks == 0)
809 return;
810 ScanCallbackList& callback_list = scan_complete_callbacks_[type];
811 for (ScanCallbackList::iterator iter = callback_list.begin();
812 iter != callback_list.end(); ++iter) {
813 (*iter).Run();
815 scan_complete_callbacks_.erase(type);
818 std::string NetworkStateHandler::GetTechnologyForType(
819 const NetworkTypePattern& type) const {
820 if (type.MatchesType(shill::kTypeEthernet))
821 return shill::kTypeEthernet;
823 if (type.MatchesType(shill::kTypeWifi))
824 return shill::kTypeWifi;
826 if (type.Equals(NetworkTypePattern::Wimax()))
827 return shill::kTypeWimax;
829 // Prefer Wimax over Cellular only if it's available.
830 if (type.MatchesType(shill::kTypeWimax) &&
831 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
832 return shill::kTypeWimax;
835 if (type.MatchesType(shill::kTypeCellular))
836 return shill::kTypeCellular;
838 NOTREACHED();
839 return std::string();
842 } // namespace chromeos