Fix copyright line on hotword extension files.
[chromium-blink-merge.git] / chromeos / network / network_state_handler.cc
bloba78b6eebdaaa0044a1bbf463d11933531cc54307
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::WaitForScan(const std::string& type,
345 const base::Closure& callback) {
346 scan_complete_callbacks_[type].push_back(callback);
347 if (!GetScanningByType(NetworkTypePattern::Primitive(type)))
348 RequestScan();
351 void NetworkStateHandler::ConnectToBestWifiNetwork() {
352 NET_LOG_USER("ConnectToBestWifiNetwork", "");
353 WaitForScan(shill::kTypeWifi,
354 base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices,
355 shill_property_handler_->AsWeakPtr()));
358 void NetworkStateHandler::RequestUpdateForNetwork(
359 const std::string& service_path) {
360 NetworkState* network = GetModifiableNetworkState(service_path);
361 if (network)
362 network->set_update_requested(true);
363 NET_LOG_EVENT("RequestUpdate", service_path);
364 shill_property_handler_->RequestProperties(
365 ManagedState::MANAGED_TYPE_NETWORK, service_path);
368 void NetworkStateHandler::ClearLastErrorForNetwork(
369 const std::string& service_path) {
370 NetworkState* network = GetModifiableNetworkState(service_path);
371 if (network)
372 network->clear_last_error();
375 void NetworkStateHandler::SetCheckPortalList(
376 const std::string& check_portal_list) {
377 NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
378 shill_property_handler_->SetCheckPortalList(check_portal_list);
381 const NetworkState* NetworkStateHandler::GetEAPForEthernet(
382 const std::string& service_path) {
383 const NetworkState* network = GetNetworkState(service_path);
384 if (!network) {
385 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path);
386 return NULL;
388 if (network->type() != shill::kTypeEthernet) {
389 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path);
390 return NULL;
392 if (!network->IsConnectedState())
393 return NULL;
395 // The same EAP service is shared for all ethernet services/devices.
396 // However EAP is used/enabled per device and only if the connection was
397 // successfully established.
398 const DeviceState* device = GetDeviceState(network->device_path());
399 if (!device) {
400 NET_LOG_ERROR(
401 "GetEAPForEthernet",
402 base::StringPrintf("Unknown device %s of connected ethernet service %s",
403 network->device_path().c_str(),
404 service_path.c_str()));
405 return NULL;
407 if (!device->eap_authentication_completed())
408 return NULL;
410 NetworkStateList list;
411 GetNetworkListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap),
412 true /* configured_only */,
413 false /* visible_only */,
414 1 /* limit */,
415 &list);
416 if (list.empty()) {
417 NET_LOG_ERROR("GetEAPForEthernet",
418 base::StringPrintf(
419 "Ethernet service %s connected using EAP, but no "
420 "EAP service found.",
421 service_path.c_str()));
422 return NULL;
424 return list.front();
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("UpdateManagedList: " + ManagedState::TypeToString(type),
434 base::StringPrintf("%" PRIuS, entries.GetSize()));
435 // Create a map of existing entries. Assumes all entries in |managed_list|
436 // are unique.
437 typedef std::map<std::string, ManagedState*> ManagedMap;
438 ManagedMap managed_map;
439 for (ManagedStateList::iterator iter = managed_list->begin();
440 iter != managed_list->end(); ++iter) {
441 ManagedState* managed = *iter;
442 DCHECK(!ContainsKey(managed_map, managed->path()));
443 managed_map[managed->path()] = managed;
445 // Clear the list (pointers are temporarily owned by managed_map).
446 managed_list->clear();
447 // Updates managed_list and request updates for new entries.
448 std::set<std::string> list_entries;
449 for (base::ListValue::const_iterator iter = entries.begin();
450 iter != entries.end(); ++iter) {
451 std::string path;
452 (*iter)->GetAsString(&path);
453 if (path.empty() || path == shill::kFlimflamServicePath) {
454 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path);
455 continue;
457 ManagedMap::iterator found = managed_map.find(path);
458 if (found == managed_map.end()) {
459 if (list_entries.count(path) != 0) {
460 NET_LOG_ERROR("Duplicate entry in list", path);
461 continue;
463 ManagedState* managed = ManagedState::Create(type, path);
464 managed_list->push_back(managed);
465 } else {
466 managed_list->push_back(found->second);
467 managed_map.erase(found);
469 list_entries.insert(path);
471 // Delete any remaining entries in managed_map.
472 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
475 void NetworkStateHandler::ProfileListChanged() {
476 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
477 for (ManagedStateList::iterator iter = network_list_.begin();
478 iter != network_list_.end(); ++iter) {
479 NetworkState* network = (*iter)->AsNetworkState();
480 DCHECK(network);
481 shill_property_handler_->RequestProperties(
482 ManagedState::MANAGED_TYPE_NETWORK, network->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 // The network has been removed from the list of networks.
494 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path);
495 return;
497 managed->set_update_received();
499 std::string desc = GetManagedStateLogType(managed) + " Properties Received";
500 NET_LOG_DEBUG(desc, GetLogName(managed));
502 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
503 UpdateNetworkStateProperties(managed->AsNetworkState(), properties);
504 } else {
505 // Device
506 for (base::DictionaryValue::Iterator iter(properties);
507 !iter.IsAtEnd(); iter.Advance()) {
508 managed->PropertyChanged(iter.key(), iter.value());
510 managed->InitialPropertiesReceived(properties);
512 managed->set_update_requested(false);
515 void NetworkStateHandler::UpdateNetworkStateProperties(
516 NetworkState* network,
517 const base::DictionaryValue& properties) {
518 DCHECK(network);
519 bool network_property_updated = false;
520 std::string prev_connection_state = network->connection_state();
521 for (base::DictionaryValue::Iterator iter(properties);
522 !iter.IsAtEnd(); iter.Advance()) {
523 if (network->PropertyChanged(iter.key(), iter.value()))
524 network_property_updated = true;
526 network_property_updated |= network->InitialPropertiesReceived(properties);
527 UpdateGuid(network);
528 network_list_sorted_ = false;
530 // Notify observers of NetworkState changes.
531 if (network_property_updated || network->update_requested()) {
532 // Signal connection state changed after all properties have been updated.
533 if (ConnectionStateChanged(network, prev_connection_state))
534 OnNetworkConnectionStateChanged(network);
535 NET_LOG_EVENT("NetworkPropertiesUpdated", GetLogName(network));
536 NotifyNetworkPropertiesUpdated(network);
540 void NetworkStateHandler::UpdateNetworkServiceProperty(
541 const std::string& service_path,
542 const std::string& key,
543 const base::Value& value) {
544 bool changed = false;
545 NetworkState* network = GetModifiableNetworkState(service_path);
546 if (!network)
547 return;
548 std::string prev_connection_state = network->connection_state();
549 std::string prev_profile_path = network->profile_path();
550 changed |= network->PropertyChanged(key, value);
551 if (!changed)
552 return;
554 if (key == shill::kStateProperty || key == shill::kVisibleProperty) {
555 network_list_sorted_ = false;
556 if (ConnectionStateChanged(network, prev_connection_state)) {
557 OnNetworkConnectionStateChanged(network);
558 // If the connection state changes, other properties such as IPConfig
559 // may have changed, so request a full update.
560 RequestUpdateForNetwork(service_path);
562 } else {
563 std::string value_str;
564 value.GetAsString(&value_str);
565 // Some property changes are noisy and not interesting:
566 // * Wifi SignalStrength
567 // * WifiFrequencyList updates
568 // * Device property changes to "/" (occurs before a service is removed)
569 if (key != shill::kSignalStrengthProperty &&
570 key != shill::kWifiFrequencyListProperty &&
571 (key != shill::kDeviceProperty || value_str != "/")) {
572 std::string log_event = "NetworkPropertyUpdated";
573 // Trigger a default network update for interesting changes only.
574 if (network->path() == default_network_path_) {
575 NotifyDefaultNetworkChanged(network);
576 log_event = "Default" + log_event;
578 // Log event.
579 std::string detail = network->name() + "." + key;
580 detail += " = " + network_event_log::ValueAsString(value);
581 network_event_log::LogLevel log_level;
582 if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) {
583 log_level = network_event_log::LOG_LEVEL_ERROR;
584 } else {
585 log_level = network_event_log::LOG_LEVEL_EVENT;
587 NET_LOG_LEVEL(log_level, log_event, detail);
591 // All property updates signal 'NetworkPropertiesUpdated'.
592 NotifyNetworkPropertiesUpdated(network);
594 // If added to a Profile, request a full update so that a NetworkState
595 // gets created.
596 if (prev_profile_path.empty() && !network->profile_path().empty())
597 RequestUpdateForNetwork(service_path);
600 void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path,
601 const std::string& key,
602 const base::Value& value) {
603 DeviceState* device = GetModifiableDeviceState(device_path);
604 if (!device)
605 return;
606 if (!device->PropertyChanged(key, value))
607 return;
609 std::string detail = device->name() + "." + key;
610 detail += " = " + network_event_log::ValueAsString(value);
611 NET_LOG_EVENT("DevicePropertyUpdated", detail);
613 NotifyDeviceListChanged();
614 NotifyDevicePropertiesUpdated(device);
616 if (key == shill::kScanningProperty && device->scanning() == false)
617 ScanCompleted(device->type());
618 if (key == shill::kEapAuthenticationCompletedProperty) {
619 // Notify a change for each Ethernet service using this device.
620 NetworkStateList ethernet_services;
621 GetNetworkListByType(NetworkTypePattern::Ethernet(),
622 false /* configured_only */,
623 false /* visible_only */,
624 0 /* no limit */,
625 &ethernet_services);
626 for (NetworkStateList::const_iterator it = ethernet_services.begin();
627 it != ethernet_services.end(); ++it) {
628 const NetworkState* ethernet_service = *it;
629 if (ethernet_service->update_received() ||
630 ethernet_service->device_path() != device->path()) {
631 continue;
633 RequestUpdateForNetwork(ethernet_service->path());
638 void NetworkStateHandler::UpdateIPConfigProperties(
639 ManagedState::ManagedType type,
640 const std::string& path,
641 const std::string& ip_config_path,
642 const base::DictionaryValue& properties) {
643 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
644 NetworkState* network = GetModifiableNetworkState(path);
645 if (!network)
646 return;
647 network->IPConfigPropertiesChanged(properties);
648 NotifyNetworkPropertiesUpdated(network);
649 if (network->path() == default_network_path_)
650 NotifyDefaultNetworkChanged(network);
651 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
652 DeviceState* device = GetModifiableDeviceState(path);
653 if (!device)
654 return;
655 device->IPConfigPropertiesChanged(ip_config_path, properties);
656 NotifyDevicePropertiesUpdated(device);
657 if (!default_network_path_.empty()) {
658 const NetworkState* default_network =
659 GetNetworkState(default_network_path_);
660 if (default_network && default_network->device_path() == path)
661 NotifyDefaultNetworkChanged(default_network);
666 void NetworkStateHandler::CheckPortalListChanged(
667 const std::string& check_portal_list) {
668 check_portal_list_ = check_portal_list;
671 void NetworkStateHandler::TechnologyListChanged() {
672 // Eventually we would like to replace Technology state with Device state.
673 // For now, treat technology state changes as device list changes.
674 NotifyDeviceListChanged();
677 void NetworkStateHandler::ManagedStateListChanged(
678 ManagedState::ManagedType type) {
679 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
680 SortNetworkList();
681 UpdateNetworkStats();
682 // Notify observers that the list of networks has changed.
683 NET_LOG_EVENT("NOTIFY:NetworkListChanged",
684 base::StringPrintf("Size:%" PRIuS, network_list_.size()));
685 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
686 NetworkListChanged());
687 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
688 std::string devices;
689 for (ManagedStateList::const_iterator iter = device_list_.begin();
690 iter != device_list_.end(); ++iter) {
691 if (iter != device_list_.begin())
692 devices += ", ";
693 devices += (*iter)->name();
695 NET_LOG_EVENT("DeviceList", devices);
696 NotifyDeviceListChanged();
697 } else {
698 NOTREACHED();
702 void NetworkStateHandler::SortNetworkList() {
703 // Note: usually active networks will precede inactive networks, however
704 // this may briefly be untrue during state transitions (e.g. a network may
705 // transition to idle before the list is updated).
706 ManagedStateList active, non_wifi_visible, wifi_visible, hidden, new_networks;
707 for (ManagedStateList::iterator iter = network_list_.begin();
708 iter != network_list_.end(); ++iter) {
709 NetworkState* network = (*iter)->AsNetworkState();
710 if (!network->update_received()) {
711 new_networks.push_back(network);
712 continue;
714 if (network->IsConnectedState() || network->IsConnectingState()) {
715 active.push_back(network);
716 continue;
718 if (network->visible()) {
719 if (NetworkTypePattern::WiFi().MatchesType(network->type()))
720 wifi_visible.push_back(network);
721 else
722 non_wifi_visible.push_back(network);
723 } else {
724 hidden.push_back(network);
727 network_list_.clear();
728 network_list_.insert(network_list_.end(), active.begin(), active.end());
729 network_list_.insert(
730 network_list_.end(), non_wifi_visible.begin(), non_wifi_visible.end());
731 network_list_.insert(
732 network_list_.end(), wifi_visible.begin(), wifi_visible.end());
733 network_list_.insert(network_list_.end(), hidden.begin(), hidden.end());
734 network_list_.insert(
735 network_list_.end(), new_networks.begin(), new_networks.end());
736 network_list_sorted_ = true;
739 void NetworkStateHandler::UpdateNetworkStats() {
740 size_t shared = 0, unshared = 0, visible = 0;
741 for (ManagedStateList::iterator iter = network_list_.begin();
742 iter != network_list_.end(); ++iter) {
743 NetworkState* network = (*iter)->AsNetworkState();
744 if (network->visible())
745 ++visible;
746 if (network->IsInProfile()) {
747 if (network->IsPrivate())
748 ++unshared;
749 else
750 ++shared;
753 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", visible);
754 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared);
755 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared);
758 void NetworkStateHandler::DefaultNetworkServiceChanged(
759 const std::string& service_path) {
760 // Shill uses '/' for empty service path values; check explicitly for that.
761 const char* kEmptyServicePath = "/";
762 std::string new_service_path =
763 (service_path != kEmptyServicePath) ? service_path : "";
764 if (new_service_path == default_network_path_)
765 return;
767 default_network_path_ = service_path;
768 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_);
769 const NetworkState* network = NULL;
770 if (!default_network_path_.empty()) {
771 network = GetNetworkState(default_network_path_);
772 if (!network) {
773 // If NetworkState is not available yet, do not notify observers here,
774 // they will be notified when the state is received.
775 NET_LOG_DEBUG("Default NetworkState not available",
776 default_network_path_);
777 return;
780 if (network && !network->IsConnectedState()) {
781 NET_LOG_ERROR(
782 "DefaultNetwork is not connected: " + network->connection_state(),
783 network->path());
785 NotifyDefaultNetworkChanged(network);
788 //------------------------------------------------------------------------------
789 // Private methods
791 void NetworkStateHandler::UpdateGuid(NetworkState* network) {
792 std::string specifier = network->GetSpecifier();
793 DCHECK(!specifier.empty());
794 if (!network->guid().empty()) {
795 // If the network is saved in a profile, remove the entry from the map.
796 // Otherwise ensure that the entry matches the specified GUID. (e.g. in
797 // case a visible network with a specified guid gets configured with a
798 // new guid).
799 if (network->IsInProfile())
800 specifier_guid_map_.erase(specifier);
801 else
802 specifier_guid_map_[specifier] = network->guid();
803 return;
805 // Ensure that the NetworkState has a valid GUID.
806 std::string guid;
807 SpecifierGuidMap::iterator iter = specifier_guid_map_.find(specifier);
808 if (iter != specifier_guid_map_.end()) {
809 guid = iter->second;
810 } else {
811 guid = base::GenerateGUID();
812 specifier_guid_map_[specifier] = guid;
814 network->SetGuid(guid);
817 void NetworkStateHandler::NotifyDeviceListChanged() {
818 NET_LOG_DEBUG("NOTIFY:DeviceListChanged",
819 base::StringPrintf("Size:%" PRIuS, device_list_.size()));
820 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
821 DeviceListChanged());
824 DeviceState* NetworkStateHandler::GetModifiableDeviceState(
825 const std::string& device_path) const {
826 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
827 if (!managed)
828 return NULL;
829 return managed->AsDeviceState();
832 NetworkState* NetworkStateHandler::GetModifiableNetworkState(
833 const std::string& service_path) const {
834 ManagedState* managed =
835 GetModifiableManagedState(&network_list_, service_path);
836 if (!managed)
837 return NULL;
838 return managed->AsNetworkState();
841 ManagedState* NetworkStateHandler::GetModifiableManagedState(
842 const ManagedStateList* managed_list,
843 const std::string& path) const {
844 for (ManagedStateList::const_iterator iter = managed_list->begin();
845 iter != managed_list->end(); ++iter) {
846 ManagedState* managed = *iter;
847 if (managed->path() == path)
848 return managed;
850 return NULL;
853 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
854 ManagedState::ManagedType type) {
855 switch (type) {
856 case ManagedState::MANAGED_TYPE_NETWORK:
857 return &network_list_;
858 case ManagedState::MANAGED_TYPE_DEVICE:
859 return &device_list_;
861 NOTREACHED();
862 return NULL;
865 void NetworkStateHandler::OnNetworkConnectionStateChanged(
866 NetworkState* network) {
867 DCHECK(network);
868 std::string event = "NetworkConnectionStateChanged";
869 if (network->path() == default_network_path_) {
870 event = "Default" + event;
871 if (!network->IsConnectedState()) {
872 NET_LOG_EVENT(
873 "DefaultNetwork is not connected: " + network->connection_state(),
874 network->path());
875 default_network_path_.clear();
876 SortNetworkList();
877 NotifyDefaultNetworkChanged(NULL);
880 NET_LOG_EVENT("NOTIFY:" + event + ": " + network->connection_state(),
881 GetLogName(network));
882 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
883 NetworkConnectionStateChanged(network));
884 if (network->path() == default_network_path_)
885 NotifyDefaultNetworkChanged(network);
888 void NetworkStateHandler::NotifyDefaultNetworkChanged(
889 const NetworkState* default_network) {
890 NET_LOG_EVENT("NOTIFY:DefaultNetworkChanged", GetLogName(default_network));
891 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
892 DefaultNetworkChanged(default_network));
895 void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
896 const NetworkState* network) {
897 NET_LOG_DEBUG("NOTIFY:NetworkPropertiesUpdated", GetLogName(network));
898 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
899 NetworkPropertiesUpdated(network));
902 void NetworkStateHandler::NotifyDevicePropertiesUpdated(
903 const DeviceState* device) {
904 NET_LOG_DEBUG("NOTIFY:DevicePropertiesUpdated", GetLogName(device));
905 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
906 DevicePropertiesUpdated(device));
909 void NetworkStateHandler::ScanCompleted(const std::string& type) {
910 size_t num_callbacks = scan_complete_callbacks_.count(type);
911 NET_LOG_EVENT("ScanCompleted",
912 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks));
913 if (num_callbacks == 0)
914 return;
915 ScanCallbackList& callback_list = scan_complete_callbacks_[type];
916 for (ScanCallbackList::iterator iter = callback_list.begin();
917 iter != callback_list.end(); ++iter) {
918 (*iter).Run();
920 scan_complete_callbacks_.erase(type);
923 std::string NetworkStateHandler::GetTechnologyForType(
924 const NetworkTypePattern& type) const {
925 if (type.MatchesType(shill::kTypeEthernet))
926 return shill::kTypeEthernet;
928 if (type.MatchesType(shill::kTypeWifi))
929 return shill::kTypeWifi;
931 if (type.Equals(NetworkTypePattern::Wimax()))
932 return shill::kTypeWimax;
934 // Prefer Wimax over Cellular only if it's available.
935 if (type.MatchesType(shill::kTypeWimax) &&
936 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
937 return shill::kTypeWimax;
940 if (type.MatchesType(shill::kTypeCellular))
941 return shill::kTypeCellular;
943 NOTREACHED();
944 return std::string();
947 ScopedVector<std::string> NetworkStateHandler::GetTechnologiesForType(
948 const NetworkTypePattern& type) const {
949 ScopedVector<std::string> technologies;
950 if (type.MatchesType(shill::kTypeEthernet))
951 technologies.push_back(new std::string(shill::kTypeEthernet));
952 if (type.MatchesType(shill::kTypeWifi))
953 technologies.push_back(new std::string(shill::kTypeWifi));
954 if (type.MatchesType(shill::kTypeWimax))
955 technologies.push_back(new std::string(shill::kTypeWimax));
956 if (type.MatchesType(shill::kTypeCellular))
957 technologies.push_back(new std::string(shill::kTypeCellular));
958 if (type.MatchesType(shill::kTypeBluetooth))
959 technologies.push_back(new std::string(shill::kTypeBluetooth));
960 if (type.MatchesType(shill::kTypeVPN))
961 technologies.push_back(new std::string(shill::kTypeVPN));
963 CHECK_GT(technologies.size(), 0ul);
964 return technologies.Pass();
967 } // namespace chromeos