Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / chromeos / network / network_state_handler.cc
blobbbfa6ce7df971f6a33925e6a11ee7f54317475bb
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/location.h"
11 #include "base/logging.h"
12 #include "base/metrics/histogram.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/values.h"
17 #include "chromeos/network/device_state.h"
18 #include "chromeos/network/managed_state.h"
19 #include "chromeos/network/network_event_log.h"
20 #include "chromeos/network/network_state.h"
21 #include "chromeos/network/network_state_handler_observer.h"
22 #include "chromeos/network/shill_property_handler.h"
23 #include "third_party/cros_system_api/dbus/service_constants.h"
25 namespace chromeos {
27 namespace {
29 bool ConnectionStateChanged(NetworkState* network,
30 const std::string& prev_connection_state) {
31 return (network->connection_state() != prev_connection_state) &&
32 (network->connection_state() != shill::kStateIdle ||
33 !prev_connection_state.empty());
36 std::string GetManagedStateLogType(const ManagedState* state) {
37 switch (state->managed_type()) {
38 case ManagedState::MANAGED_TYPE_NETWORK:
39 return "Network";
40 case ManagedState::MANAGED_TYPE_DEVICE:
41 return "Device";
43 NOTREACHED();
44 return "";
47 std::string GetLogName(const ManagedState* state) {
48 if (!state)
49 return "None";
50 return base::StringPrintf("%s (%s)", state->name().c_str(),
51 state->path().c_str());
54 } // namespace
56 const char NetworkStateHandler::kDefaultCheckPortalList[] =
57 "ethernet,wifi,cellular";
59 NetworkStateHandler::NetworkStateHandler()
60 : network_list_sorted_(false) {
63 NetworkStateHandler::~NetworkStateHandler() {
64 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, IsShuttingDown());
65 STLDeleteContainerPointers(network_list_.begin(), network_list_.end());
66 STLDeleteContainerPointers(device_list_.begin(), device_list_.end());
69 void NetworkStateHandler::InitShillPropertyHandler() {
70 shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
71 shill_property_handler_->Init();
74 // static
75 NetworkStateHandler* NetworkStateHandler::InitializeForTest() {
76 NetworkStateHandler* handler = new NetworkStateHandler();
77 handler->InitShillPropertyHandler();
78 return handler;
81 void NetworkStateHandler::AddObserver(
82 NetworkStateHandlerObserver* observer,
83 const tracked_objects::Location& from_here) {
84 observers_.AddObserver(observer);
85 network_event_log::internal::AddEntry(
86 from_here.file_name(), from_here.line_number(),
87 network_event_log::LOG_LEVEL_DEBUG,
88 "NetworkStateHandler::AddObserver", "");
91 void NetworkStateHandler::RemoveObserver(
92 NetworkStateHandlerObserver* observer,
93 const tracked_objects::Location& from_here) {
94 observers_.RemoveObserver(observer);
95 network_event_log::internal::AddEntry(
96 from_here.file_name(), from_here.line_number(),
97 network_event_log::LOG_LEVEL_DEBUG,
98 "NetworkStateHandler::RemoveObserver", "");
101 NetworkStateHandler::TechnologyState NetworkStateHandler::GetTechnologyState(
102 const NetworkTypePattern& type) const {
103 std::string technology = GetTechnologyForType(type);
104 TechnologyState state;
105 if (shill_property_handler_->IsTechnologyEnabled(technology))
106 state = TECHNOLOGY_ENABLED;
107 else if (shill_property_handler_->IsTechnologyEnabling(technology))
108 state = TECHNOLOGY_ENABLING;
109 else if (shill_property_handler_->IsTechnologyUninitialized(technology))
110 state = TECHNOLOGY_UNINITIALIZED;
111 else if (shill_property_handler_->IsTechnologyAvailable(technology))
112 state = TECHNOLOGY_AVAILABLE;
113 else
114 state = TECHNOLOGY_UNAVAILABLE;
115 VLOG(2) << "GetTechnologyState: " << type.ToDebugString() << " = " << state;
116 return state;
119 void NetworkStateHandler::SetTechnologyEnabled(
120 const NetworkTypePattern& type,
121 bool enabled,
122 const network_handler::ErrorCallback& error_callback) {
123 ScopedVector<std::string> technologies = GetTechnologiesForType(type);
124 for (ScopedVector<std::string>::iterator it = technologies.begin();
125 it != technologies.end(); ++it) {
126 std::string* technology = *it;
127 DCHECK(technology);
128 if (!shill_property_handler_->IsTechnologyAvailable(*technology))
129 continue;
130 NET_LOG_USER("SetTechnologyEnabled",
131 base::StringPrintf("%s:%d", technology->c_str(), enabled));
132 shill_property_handler_->SetTechnologyEnabled(
133 *technology, enabled, error_callback);
135 // Signal Device/Technology state changed.
136 NotifyDeviceListChanged();
139 const DeviceState* NetworkStateHandler::GetDeviceState(
140 const std::string& device_path) const {
141 const DeviceState* device = GetModifiableDeviceState(device_path);
142 if (device && !device->update_received())
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 NetworkState* NetworkStateHandler::ConnectedNetworkByType(
189 const NetworkTypePattern& type) const {
190 // Active networks are always listed first by Shill so no need to sort.
191 for (ManagedStateList::const_iterator iter = network_list_.begin();
192 iter != network_list_.end(); ++iter) {
193 const NetworkState* network = (*iter)->AsNetworkState();
194 DCHECK(network);
195 if (!network->update_received())
196 continue;
197 if (!network->IsConnectedState())
198 break; // Connected networks are listed first.
199 if (network->Matches(type))
200 return network;
202 return NULL;
205 const NetworkState* NetworkStateHandler::ConnectingNetworkByType(
206 const NetworkTypePattern& type) const {
207 // Active networks are always listed first by Shill so no need to sort.
208 for (ManagedStateList::const_iterator iter = network_list_.begin();
209 iter != network_list_.end(); ++iter) {
210 const NetworkState* network = (*iter)->AsNetworkState();
211 DCHECK(network);
212 if (!network->update_received() || network->IsConnectedState())
213 continue;
214 if (!network->IsConnectingState())
215 break; // Connected and connecting networks are listed first.
216 if (network->Matches(type))
217 return network;
219 return NULL;
222 const NetworkState* NetworkStateHandler::FirstNetworkByType(
223 const NetworkTypePattern& type) {
224 if (!network_list_sorted_)
225 SortNetworkList(); // Sort to ensure visible networks are listed first.
226 for (ManagedStateList::const_iterator iter = network_list_.begin();
227 iter != network_list_.end(); ++iter) {
228 const NetworkState* network = (*iter)->AsNetworkState();
229 DCHECK(network);
230 if (!network->update_received())
231 continue;
232 if (!network->visible())
233 break;
234 if (network->Matches(type))
235 return network;
237 return NULL;
240 std::string NetworkStateHandler::FormattedHardwareAddressForType(
241 const NetworkTypePattern& type) const {
242 const DeviceState* device = NULL;
243 const NetworkState* network = ConnectedNetworkByType(type);
244 if (network)
245 device = GetDeviceState(network->device_path());
246 else
247 device = GetDeviceStateByType(type);
248 if (!device)
249 return std::string();
250 return network_util::FormattedMacAddress(device->mac_address());
253 void NetworkStateHandler::GetVisibleNetworkListByType(
254 const NetworkTypePattern& type,
255 NetworkStateList* list) {
256 GetNetworkListByType(type,
257 false /* configured_only */,
258 true /* visible_only */,
259 0 /* no limit */,
260 list);
263 void NetworkStateHandler::GetVisibleNetworkList(NetworkStateList* list) {
264 GetVisibleNetworkListByType(NetworkTypePattern::Default(), list);
267 void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type,
268 bool configured_only,
269 bool visible_only,
270 int limit,
271 NetworkStateList* list) {
272 DCHECK(list);
273 list->clear();
274 int count = 0;
275 // Sort the network list if necessary.
276 if (!network_list_sorted_)
277 SortNetworkList();
278 for (ManagedStateList::const_iterator iter = network_list_.begin();
279 iter != network_list_.end(); ++iter) {
280 const NetworkState* network = (*iter)->AsNetworkState();
281 DCHECK(network);
282 if (!network->update_received() || !network->Matches(type))
283 continue;
284 if (configured_only && !network->IsInProfile())
285 continue;
286 if (visible_only && !network->visible())
287 continue;
288 list->push_back(network);
289 if (limit > 0 && ++count >= limit)
290 break;
294 const NetworkState* NetworkStateHandler::GetNetworkStateFromServicePath(
295 const std::string& service_path,
296 bool configured_only) const {
297 ManagedState* managed =
298 GetModifiableManagedState(&network_list_, service_path);
299 if (!managed)
300 return NULL;
301 const NetworkState* network = managed->AsNetworkState();
302 DCHECK(network);
303 if (!network->update_received() ||
304 (configured_only && !network->IsInProfile())) {
305 return NULL;
307 return network;
310 const NetworkState* NetworkStateHandler::GetNetworkStateFromGuid(
311 const std::string& guid) const {
312 DCHECK(!guid.empty());
313 for (ManagedStateList::const_iterator iter = network_list_.begin();
314 iter != network_list_.end(); ++iter) {
315 const NetworkState* network = (*iter)->AsNetworkState();
316 if (network->guid() == guid)
317 return network;
319 return NULL;
322 void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const {
323 GetDeviceListByType(NetworkTypePattern::Default(), list);
326 void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type,
327 DeviceStateList* list) const {
328 DCHECK(list);
329 list->clear();
330 for (ManagedStateList::const_iterator iter = device_list_.begin();
331 iter != device_list_.end(); ++iter) {
332 const DeviceState* device = (*iter)->AsDeviceState();
333 DCHECK(device);
334 if (device->update_received() && device->Matches(type))
335 list->push_back(device);
339 void NetworkStateHandler::RequestScan() const {
340 NET_LOG_USER("RequestScan", "");
341 shill_property_handler_->RequestScan();
344 void NetworkStateHandler::RequestUpdateForNetwork(
345 const std::string& service_path) {
346 NetworkState* network = GetModifiableNetworkState(service_path);
347 if (network)
348 network->set_update_requested(true);
349 NET_LOG_EVENT("RequestUpdate", service_path);
350 shill_property_handler_->RequestProperties(
351 ManagedState::MANAGED_TYPE_NETWORK, service_path);
354 void NetworkStateHandler::ClearLastErrorForNetwork(
355 const std::string& service_path) {
356 NetworkState* network = GetModifiableNetworkState(service_path);
357 if (network)
358 network->clear_last_error();
361 void NetworkStateHandler::SetCheckPortalList(
362 const std::string& check_portal_list) {
363 NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
364 shill_property_handler_->SetCheckPortalList(check_portal_list);
367 void NetworkStateHandler::SetWakeOnLanEnabled(bool enabled) {
368 NET_LOG_EVENT("SetWakeOnLanEnabled",
369 base::StringPrintf("%s", enabled ? "true" : "false"));
370 shill_property_handler_->SetWakeOnLanEnabled(enabled);
373 const NetworkState* NetworkStateHandler::GetEAPForEthernet(
374 const std::string& service_path) {
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 NetworkStateList list;
403 GetNetworkListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap),
404 true /* configured_only */,
405 false /* visible_only */,
406 1 /* limit */,
407 &list);
408 if (list.empty()) {
409 NET_LOG_ERROR("GetEAPForEthernet",
410 base::StringPrintf(
411 "Ethernet service %s connected using EAP, but no "
412 "EAP service found.",
413 service_path.c_str()));
414 return NULL;
416 return list.front();
419 //------------------------------------------------------------------------------
420 // ShillPropertyHandler::Delegate overrides
422 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type,
423 const base::ListValue& entries) {
424 ManagedStateList* managed_list = GetManagedList(type);
425 NET_LOG_DEBUG("UpdateManagedList: " + ManagedState::TypeToString(type),
426 base::StringPrintf("%" PRIuS, entries.GetSize()));
427 // Create a map of existing entries. Assumes all entries in |managed_list|
428 // are unique.
429 typedef std::map<std::string, ManagedState*> ManagedMap;
430 ManagedMap managed_map;
431 for (ManagedStateList::iterator iter = managed_list->begin();
432 iter != managed_list->end(); ++iter) {
433 ManagedState* managed = *iter;
434 DCHECK(!ContainsKey(managed_map, managed->path()));
435 managed_map[managed->path()] = managed;
437 // Clear the list (pointers are temporarily owned by managed_map).
438 managed_list->clear();
439 // Updates managed_list and request updates for new entries.
440 std::set<std::string> list_entries;
441 for (base::ListValue::const_iterator iter = entries.begin();
442 iter != entries.end(); ++iter) {
443 std::string path;
444 (*iter)->GetAsString(&path);
445 if (path.empty() || path == shill::kFlimflamServicePath) {
446 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path);
447 continue;
449 ManagedMap::iterator found = managed_map.find(path);
450 if (found == managed_map.end()) {
451 if (list_entries.count(path) != 0) {
452 NET_LOG_ERROR("Duplicate entry in list", path);
453 continue;
455 ManagedState* managed = ManagedState::Create(type, path);
456 managed_list->push_back(managed);
457 } else {
458 managed_list->push_back(found->second);
459 managed_map.erase(found);
461 list_entries.insert(path);
463 // Delete any remaining entries in managed_map.
464 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
467 void NetworkStateHandler::ProfileListChanged() {
468 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
469 for (ManagedStateList::iterator iter = network_list_.begin();
470 iter != network_list_.end(); ++iter) {
471 NetworkState* network = (*iter)->AsNetworkState();
472 DCHECK(network);
473 shill_property_handler_->RequestProperties(
474 ManagedState::MANAGED_TYPE_NETWORK, network->path());
478 void NetworkStateHandler::UpdateManagedStateProperties(
479 ManagedState::ManagedType type,
480 const std::string& path,
481 const base::DictionaryValue& properties) {
482 ManagedStateList* managed_list = GetManagedList(type);
483 ManagedState* managed = GetModifiableManagedState(managed_list, path);
484 if (!managed) {
485 // The network has been removed from the list of networks.
486 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path);
487 return;
489 managed->set_update_received();
491 std::string desc = GetManagedStateLogType(managed) + " Properties Received";
492 NET_LOG_DEBUG(desc, GetLogName(managed));
494 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
495 UpdateNetworkStateProperties(managed->AsNetworkState(), properties);
496 } else {
497 // Device
498 for (base::DictionaryValue::Iterator iter(properties);
499 !iter.IsAtEnd(); iter.Advance()) {
500 managed->PropertyChanged(iter.key(), iter.value());
502 managed->InitialPropertiesReceived(properties);
504 managed->set_update_requested(false);
507 void NetworkStateHandler::UpdateNetworkStateProperties(
508 NetworkState* network,
509 const base::DictionaryValue& properties) {
510 DCHECK(network);
511 bool network_property_updated = false;
512 std::string prev_connection_state = network->connection_state();
513 for (base::DictionaryValue::Iterator iter(properties);
514 !iter.IsAtEnd(); iter.Advance()) {
515 if (network->PropertyChanged(iter.key(), iter.value()))
516 network_property_updated = true;
518 network_property_updated |= network->InitialPropertiesReceived(properties);
519 UpdateGuid(network);
520 network_list_sorted_ = false;
522 // Notify observers of NetworkState changes.
523 if (network_property_updated || network->update_requested()) {
524 // Signal connection state changed after all properties have been updated.
525 if (ConnectionStateChanged(network, prev_connection_state))
526 OnNetworkConnectionStateChanged(network);
527 NET_LOG_EVENT("NetworkPropertiesUpdated", GetLogName(network));
528 NotifyNetworkPropertiesUpdated(network);
532 void NetworkStateHandler::UpdateNetworkServiceProperty(
533 const std::string& service_path,
534 const std::string& key,
535 const base::Value& value) {
536 bool changed = false;
537 NetworkState* network = GetModifiableNetworkState(service_path);
538 if (!network)
539 return;
540 std::string prev_connection_state = network->connection_state();
541 std::string prev_profile_path = network->profile_path();
542 changed |= network->PropertyChanged(key, value);
543 if (!changed)
544 return;
546 if (key == shill::kStateProperty || key == shill::kVisibleProperty) {
547 network_list_sorted_ = false;
548 if (ConnectionStateChanged(network, prev_connection_state)) {
549 OnNetworkConnectionStateChanged(network);
550 // If the connection state changes, other properties such as IPConfig
551 // may have changed, so request a full update.
552 RequestUpdateForNetwork(service_path);
554 } else {
555 std::string value_str;
556 value.GetAsString(&value_str);
557 // Some property changes are noisy and not interesting:
558 // * Wifi SignalStrength
559 // * WifiFrequencyList updates
560 // * Device property changes to "/" (occurs before a service is removed)
561 if (key != shill::kSignalStrengthProperty &&
562 key != shill::kWifiFrequencyListProperty &&
563 (key != shill::kDeviceProperty || value_str != "/")) {
564 std::string log_event = "NetworkPropertyUpdated";
565 // Trigger a default network update for interesting changes only.
566 if (network->path() == default_network_path_) {
567 NotifyDefaultNetworkChanged(network);
568 log_event = "Default" + log_event;
570 // Log event.
571 std::string detail = network->name() + "." + key;
572 detail += " = " + network_event_log::ValueAsString(value);
573 network_event_log::LogLevel log_level;
574 if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) {
575 log_level = network_event_log::LOG_LEVEL_ERROR;
576 } else {
577 log_level = network_event_log::LOG_LEVEL_EVENT;
579 NET_LOG_LEVEL(log_level, log_event, detail);
583 // All property updates signal 'NetworkPropertiesUpdated'.
584 NotifyNetworkPropertiesUpdated(network);
586 // If added to a Profile, request a full update so that a NetworkState
587 // gets created.
588 if (prev_profile_path.empty() && !network->profile_path().empty())
589 RequestUpdateForNetwork(service_path);
592 void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path,
593 const std::string& key,
594 const base::Value& value) {
595 DeviceState* device = GetModifiableDeviceState(device_path);
596 if (!device)
597 return;
598 if (!device->PropertyChanged(key, value))
599 return;
601 std::string detail = device->name() + "." + key;
602 detail += " = " + network_event_log::ValueAsString(value);
603 NET_LOG_EVENT("DevicePropertyUpdated", detail);
605 NotifyDeviceListChanged();
606 NotifyDevicePropertiesUpdated(device);
608 if (key == shill::kScanningProperty && device->scanning() == false) {
609 NotifyScanCompleted(device);
611 if (key == shill::kEapAuthenticationCompletedProperty) {
612 // Notify a change for each Ethernet service using this device.
613 NetworkStateList ethernet_services;
614 GetNetworkListByType(NetworkTypePattern::Ethernet(),
615 false /* configured_only */,
616 false /* visible_only */,
617 0 /* no limit */,
618 &ethernet_services);
619 for (NetworkStateList::const_iterator it = ethernet_services.begin();
620 it != ethernet_services.end(); ++it) {
621 const NetworkState* ethernet_service = *it;
622 if (ethernet_service->update_received() ||
623 ethernet_service->device_path() != device->path()) {
624 continue;
626 RequestUpdateForNetwork(ethernet_service->path());
631 void NetworkStateHandler::UpdateIPConfigProperties(
632 ManagedState::ManagedType type,
633 const std::string& path,
634 const std::string& ip_config_path,
635 const base::DictionaryValue& properties) {
636 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
637 NetworkState* network = GetModifiableNetworkState(path);
638 if (!network)
639 return;
640 network->IPConfigPropertiesChanged(properties);
641 NotifyNetworkPropertiesUpdated(network);
642 if (network->path() == default_network_path_)
643 NotifyDefaultNetworkChanged(network);
644 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
645 DeviceState* device = GetModifiableDeviceState(path);
646 if (!device)
647 return;
648 device->IPConfigPropertiesChanged(ip_config_path, properties);
649 NotifyDevicePropertiesUpdated(device);
650 if (!default_network_path_.empty()) {
651 const NetworkState* default_network =
652 GetNetworkState(default_network_path_);
653 if (default_network && default_network->device_path() == path)
654 NotifyDefaultNetworkChanged(default_network);
659 void NetworkStateHandler::CheckPortalListChanged(
660 const std::string& check_portal_list) {
661 check_portal_list_ = check_portal_list;
664 void NetworkStateHandler::TechnologyListChanged() {
665 // Eventually we would like to replace Technology state with Device state.
666 // For now, treat technology state changes as device list changes.
667 NotifyDeviceListChanged();
670 void NetworkStateHandler::ManagedStateListChanged(
671 ManagedState::ManagedType type) {
672 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
673 SortNetworkList();
674 UpdateNetworkStats();
675 // Notify observers that the list of networks has changed.
676 NET_LOG_EVENT("NOTIFY:NetworkListChanged",
677 base::StringPrintf("Size:%" PRIuS, network_list_.size()));
678 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
679 NetworkListChanged());
680 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
681 std::string devices;
682 for (ManagedStateList::const_iterator iter = device_list_.begin();
683 iter != device_list_.end(); ++iter) {
684 if (iter != device_list_.begin())
685 devices += ", ";
686 devices += (*iter)->name();
688 NET_LOG_EVENT("DeviceList", devices);
689 NotifyDeviceListChanged();
690 } else {
691 NOTREACHED();
695 void NetworkStateHandler::SortNetworkList() {
696 // Note: usually active networks will precede inactive networks, however
697 // this may briefly be untrue during state transitions (e.g. a network may
698 // transition to idle before the list is updated).
699 ManagedStateList active, non_wifi_visible, wifi_visible, hidden, new_networks;
700 for (ManagedStateList::iterator iter = network_list_.begin();
701 iter != network_list_.end(); ++iter) {
702 NetworkState* network = (*iter)->AsNetworkState();
703 if (!network->update_received()) {
704 new_networks.push_back(network);
705 continue;
707 if (network->IsConnectedState() || network->IsConnectingState()) {
708 active.push_back(network);
709 continue;
711 if (network->visible()) {
712 if (NetworkTypePattern::WiFi().MatchesType(network->type()))
713 wifi_visible.push_back(network);
714 else
715 non_wifi_visible.push_back(network);
716 } else {
717 hidden.push_back(network);
720 network_list_.clear();
721 network_list_.insert(network_list_.end(), active.begin(), active.end());
722 network_list_.insert(
723 network_list_.end(), non_wifi_visible.begin(), non_wifi_visible.end());
724 network_list_.insert(
725 network_list_.end(), wifi_visible.begin(), wifi_visible.end());
726 network_list_.insert(network_list_.end(), hidden.begin(), hidden.end());
727 network_list_.insert(
728 network_list_.end(), new_networks.begin(), new_networks.end());
729 network_list_sorted_ = true;
732 void NetworkStateHandler::UpdateNetworkStats() {
733 size_t shared = 0, unshared = 0, visible = 0;
734 for (ManagedStateList::iterator iter = network_list_.begin();
735 iter != network_list_.end(); ++iter) {
736 NetworkState* network = (*iter)->AsNetworkState();
737 if (network->visible())
738 ++visible;
739 if (network->IsInProfile()) {
740 if (network->IsPrivate())
741 ++unshared;
742 else
743 ++shared;
746 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", visible);
747 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared);
748 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared);
751 void NetworkStateHandler::DefaultNetworkServiceChanged(
752 const std::string& service_path) {
753 // Shill uses '/' for empty service path values; check explicitly for that.
754 const char* kEmptyServicePath = "/";
755 std::string new_service_path =
756 (service_path != kEmptyServicePath) ? service_path : "";
757 if (new_service_path == default_network_path_)
758 return;
760 default_network_path_ = service_path;
761 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_);
762 const NetworkState* network = NULL;
763 if (!default_network_path_.empty()) {
764 network = GetNetworkState(default_network_path_);
765 if (!network) {
766 // If NetworkState is not available yet, do not notify observers here,
767 // they will be notified when the state is received.
768 NET_LOG_DEBUG("Default NetworkState not available",
769 default_network_path_);
770 return;
773 if (network && !network->IsConnectedState()) {
774 NET_LOG_ERROR(
775 "DefaultNetwork is not connected: " + network->connection_state(),
776 network->path());
778 NotifyDefaultNetworkChanged(network);
781 //------------------------------------------------------------------------------
782 // Private methods
784 void NetworkStateHandler::UpdateGuid(NetworkState* network) {
785 std::string specifier = network->GetSpecifier();
786 DCHECK(!specifier.empty());
787 if (!network->guid().empty()) {
788 // If the network is saved in a profile, remove the entry from the map.
789 // Otherwise ensure that the entry matches the specified GUID. (e.g. in
790 // case a visible network with a specified guid gets configured with a
791 // new guid).
792 if (network->IsInProfile())
793 specifier_guid_map_.erase(specifier);
794 else
795 specifier_guid_map_[specifier] = network->guid();
796 return;
798 // Ensure that the NetworkState has a valid GUID.
799 std::string guid;
800 SpecifierGuidMap::iterator iter = specifier_guid_map_.find(specifier);
801 if (iter != specifier_guid_map_.end()) {
802 guid = iter->second;
803 } else {
804 guid = base::GenerateGUID();
805 specifier_guid_map_[specifier] = guid;
807 network->SetGuid(guid);
810 void NetworkStateHandler::NotifyDeviceListChanged() {
811 NET_LOG_DEBUG("NOTIFY:DeviceListChanged",
812 base::StringPrintf("Size:%" PRIuS, device_list_.size()));
813 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
814 DeviceListChanged());
817 DeviceState* NetworkStateHandler::GetModifiableDeviceState(
818 const std::string& device_path) const {
819 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
820 if (!managed)
821 return NULL;
822 return managed->AsDeviceState();
825 NetworkState* NetworkStateHandler::GetModifiableNetworkState(
826 const std::string& service_path) const {
827 ManagedState* managed =
828 GetModifiableManagedState(&network_list_, service_path);
829 if (!managed)
830 return NULL;
831 return managed->AsNetworkState();
834 ManagedState* NetworkStateHandler::GetModifiableManagedState(
835 const ManagedStateList* managed_list,
836 const std::string& path) const {
837 for (ManagedStateList::const_iterator iter = managed_list->begin();
838 iter != managed_list->end(); ++iter) {
839 ManagedState* managed = *iter;
840 if (managed->path() == path)
841 return managed;
843 return NULL;
846 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
847 ManagedState::ManagedType type) {
848 switch (type) {
849 case ManagedState::MANAGED_TYPE_NETWORK:
850 return &network_list_;
851 case ManagedState::MANAGED_TYPE_DEVICE:
852 return &device_list_;
854 NOTREACHED();
855 return NULL;
858 void NetworkStateHandler::OnNetworkConnectionStateChanged(
859 NetworkState* network) {
860 DCHECK(network);
861 std::string event = "NetworkConnectionStateChanged";
862 if (network->path() == default_network_path_) {
863 event = "Default" + event;
864 if (!network->IsConnectedState()) {
865 NET_LOG_EVENT(
866 "DefaultNetwork is not connected: " + network->connection_state(),
867 network->path());
868 default_network_path_.clear();
869 SortNetworkList();
870 NotifyDefaultNetworkChanged(NULL);
873 NET_LOG_EVENT("NOTIFY:" + event + ": " + network->connection_state(),
874 GetLogName(network));
875 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
876 NetworkConnectionStateChanged(network));
877 if (network->path() == default_network_path_)
878 NotifyDefaultNetworkChanged(network);
881 void NetworkStateHandler::NotifyDefaultNetworkChanged(
882 const NetworkState* default_network) {
883 NET_LOG_EVENT("NOTIFY:DefaultNetworkChanged", GetLogName(default_network));
884 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
885 DefaultNetworkChanged(default_network));
888 void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
889 const NetworkState* network) {
890 NET_LOG_DEBUG("NOTIFY:NetworkPropertiesUpdated", GetLogName(network));
891 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
892 NetworkPropertiesUpdated(network));
895 void NetworkStateHandler::NotifyDevicePropertiesUpdated(
896 const DeviceState* device) {
897 NET_LOG_DEBUG("NOTIFY:DevicePropertiesUpdated", GetLogName(device));
898 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
899 DevicePropertiesUpdated(device));
902 void NetworkStateHandler::NotifyScanCompleted(const DeviceState* device) {
903 NET_LOG_DEBUG("NOTIFY:ScanCompleted", GetLogName(device));
904 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
905 ScanCompleted(device));
908 std::string NetworkStateHandler::GetTechnologyForType(
909 const NetworkTypePattern& type) const {
910 if (type.MatchesType(shill::kTypeEthernet))
911 return shill::kTypeEthernet;
913 if (type.MatchesType(shill::kTypeWifi))
914 return shill::kTypeWifi;
916 if (type.Equals(NetworkTypePattern::Wimax()))
917 return shill::kTypeWimax;
919 // Prefer Wimax over Cellular only if it's available.
920 if (type.MatchesType(shill::kTypeWimax) &&
921 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
922 return shill::kTypeWimax;
925 if (type.MatchesType(shill::kTypeCellular))
926 return shill::kTypeCellular;
928 NOTREACHED();
929 return std::string();
932 ScopedVector<std::string> NetworkStateHandler::GetTechnologiesForType(
933 const NetworkTypePattern& type) const {
934 ScopedVector<std::string> technologies;
935 if (type.MatchesType(shill::kTypeEthernet))
936 technologies.push_back(new std::string(shill::kTypeEthernet));
937 if (type.MatchesType(shill::kTypeWifi))
938 technologies.push_back(new std::string(shill::kTypeWifi));
939 if (type.MatchesType(shill::kTypeWimax))
940 technologies.push_back(new std::string(shill::kTypeWimax));
941 if (type.MatchesType(shill::kTypeCellular))
942 technologies.push_back(new std::string(shill::kTypeCellular));
943 if (type.MatchesType(shill::kTypeBluetooth))
944 technologies.push_back(new std::string(shill::kTypeBluetooth));
945 if (type.MatchesType(shill::kTypeVPN))
946 technologies.push_back(new std::string(shill::kTypeVPN));
948 CHECK_GT(technologies.size(), 0ul);
949 return technologies.Pass();
952 } // namespace chromeos