[Telemetry] Rename test methods in page_test_results_unittest to follow existing...
[chromium-blink-merge.git] / chromeos / network / network_state_handler.cc
blobc5b77fc46bfd8645ba4c68b99825db0355b8fa86
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromeos/network/network_state_handler.h"
7 #include "base/bind.h"
8 #include "base/format_macros.h"
9 #include "base/guid.h"
10 #include "base/json/json_string_value_serializer.h"
11 #include "base/json/json_writer.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/metrics/histogram.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/values.h"
19 #include "chromeos/network/device_state.h"
20 #include "chromeos/network/managed_state.h"
21 #include "chromeos/network/network_event_log.h"
22 #include "chromeos/network/network_state.h"
23 #include "chromeos/network/network_state_handler_observer.h"
24 #include "chromeos/network/shill_property_handler.h"
25 #include "third_party/cros_system_api/dbus/service_constants.h"
27 namespace chromeos {
29 namespace {
31 bool ConnectionStateChanged(NetworkState* network,
32 const std::string& prev_connection_state,
33 bool prev_is_captive_portal) {
34 return ((network->connection_state() != prev_connection_state) &&
35 !((network->connection_state() == shill::kStateIdle) &&
36 prev_connection_state.empty())) ||
37 (network->is_captive_portal() != prev_is_captive_portal);
40 std::string GetManagedStateLogType(const ManagedState* state) {
41 switch (state->managed_type()) {
42 case ManagedState::MANAGED_TYPE_NETWORK:
43 return "Network";
44 case ManagedState::MANAGED_TYPE_DEVICE:
45 return "Device";
47 NOTREACHED();
48 return "";
51 std::string GetLogName(const ManagedState* state) {
52 if (!state)
53 return "None";
54 return base::StringPrintf("%s (%s)", state->name().c_str(),
55 state->path().c_str());
58 std::string ValueAsString(const base::Value& value) {
59 std::string vstr;
60 base::JSONWriter::WriteWithOptions(
61 &value, base::JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &vstr);
62 return vstr.empty() ? "''" : vstr;
65 } // namespace
67 const char NetworkStateHandler::kDefaultCheckPortalList[] =
68 "ethernet,wifi,cellular";
70 NetworkStateHandler::NetworkStateHandler()
71 : network_list_sorted_(false) {
74 NetworkStateHandler::~NetworkStateHandler() {
75 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, IsShuttingDown());
76 STLDeleteContainerPointers(network_list_.begin(), network_list_.end());
77 STLDeleteContainerPointers(device_list_.begin(), device_list_.end());
80 void NetworkStateHandler::InitShillPropertyHandler() {
81 shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
82 shill_property_handler_->Init();
85 // static
86 NetworkStateHandler* NetworkStateHandler::InitializeForTest() {
87 NetworkStateHandler* handler = new NetworkStateHandler();
88 handler->InitShillPropertyHandler();
89 return handler;
92 void NetworkStateHandler::AddObserver(
93 NetworkStateHandlerObserver* observer,
94 const tracked_objects::Location& from_here) {
95 observers_.AddObserver(observer);
96 device_event_log::AddEntry(from_here.file_name(), from_here.line_number(),
97 device_event_log::LOG_TYPE_NETWORK,
98 device_event_log::LOG_LEVEL_DEBUG,
99 "NetworkStateHandler::AddObserver");
102 void NetworkStateHandler::RemoveObserver(
103 NetworkStateHandlerObserver* observer,
104 const tracked_objects::Location& from_here) {
105 observers_.RemoveObserver(observer);
106 device_event_log::AddEntry(from_here.file_name(), from_here.line_number(),
107 device_event_log::LOG_TYPE_NETWORK,
108 device_event_log::LOG_LEVEL_DEBUG,
109 "NetworkStateHandler::RemoveObserver");
112 NetworkStateHandler::TechnologyState NetworkStateHandler::GetTechnologyState(
113 const NetworkTypePattern& type) const {
114 std::string technology = GetTechnologyForType(type);
115 TechnologyState state;
116 if (shill_property_handler_->IsTechnologyEnabled(technology))
117 state = TECHNOLOGY_ENABLED;
118 else if (shill_property_handler_->IsTechnologyEnabling(technology))
119 state = TECHNOLOGY_ENABLING;
120 else if (shill_property_handler_->IsTechnologyUninitialized(technology))
121 state = TECHNOLOGY_UNINITIALIZED;
122 else if (shill_property_handler_->IsTechnologyAvailable(technology))
123 state = TECHNOLOGY_AVAILABLE;
124 else
125 state = TECHNOLOGY_UNAVAILABLE;
126 VLOG(2) << "GetTechnologyState: " << type.ToDebugString() << " = " << state;
127 return state;
130 void NetworkStateHandler::SetTechnologyEnabled(
131 const NetworkTypePattern& type,
132 bool enabled,
133 const network_handler::ErrorCallback& error_callback) {
134 ScopedVector<std::string> technologies = GetTechnologiesForType(type);
135 for (ScopedVector<std::string>::iterator it = technologies.begin();
136 it != technologies.end(); ++it) {
137 std::string* technology = *it;
138 DCHECK(technology);
139 if (!shill_property_handler_->IsTechnologyAvailable(*technology))
140 continue;
141 NET_LOG_USER("SetTechnologyEnabled",
142 base::StringPrintf("%s:%d", technology->c_str(), enabled));
143 shill_property_handler_->SetTechnologyEnabled(
144 *technology, enabled, error_callback);
146 // Signal Device/Technology state changed.
147 NotifyDeviceListChanged();
150 const DeviceState* NetworkStateHandler::GetDeviceState(
151 const std::string& device_path) const {
152 const DeviceState* device = GetModifiableDeviceState(device_path);
153 if (device && !device->update_received())
154 return NULL;
155 return device;
158 const DeviceState* NetworkStateHandler::GetDeviceStateByType(
159 const NetworkTypePattern& type) const {
160 for (ManagedStateList::const_iterator iter = device_list_.begin();
161 iter != device_list_.end(); ++iter) {
162 ManagedState* device = *iter;
163 if (!device->update_received())
164 continue;
165 if (device->Matches(type))
166 return device->AsDeviceState();
168 return NULL;
171 bool NetworkStateHandler::GetScanningByType(
172 const NetworkTypePattern& type) const {
173 for (ManagedStateList::const_iterator iter = device_list_.begin();
174 iter != device_list_.end(); ++iter) {
175 const DeviceState* device = (*iter)->AsDeviceState();
176 DCHECK(device);
177 if (!device->update_received())
178 continue;
179 if (device->Matches(type) && device->scanning())
180 return true;
182 return false;
185 const NetworkState* NetworkStateHandler::GetNetworkState(
186 const std::string& service_path) const {
187 const NetworkState* network = GetModifiableNetworkState(service_path);
188 if (network && !network->update_received())
189 return NULL;
190 return network;
193 const NetworkState* NetworkStateHandler::DefaultNetwork() const {
194 if (default_network_path_.empty())
195 return NULL;
196 return GetNetworkState(default_network_path_);
199 const NetworkState* NetworkStateHandler::ConnectedNetworkByType(
200 const NetworkTypePattern& type) const {
201 // Active networks are always listed first by Shill so no need to sort.
202 for (ManagedStateList::const_iterator iter = network_list_.begin();
203 iter != network_list_.end(); ++iter) {
204 const NetworkState* network = (*iter)->AsNetworkState();
205 DCHECK(network);
206 if (!network->update_received())
207 continue;
208 if (!network->IsConnectedState())
209 break; // Connected networks are listed first.
210 if (network->Matches(type))
211 return network;
213 return NULL;
216 const NetworkState* NetworkStateHandler::ConnectingNetworkByType(
217 const NetworkTypePattern& type) const {
218 // Active networks are always listed first by Shill so no need to sort.
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) {
235 if (!network_list_sorted_)
236 SortNetworkList(); // Sort to ensure visible networks are listed first.
237 for (ManagedStateList::const_iterator iter = network_list_.begin();
238 iter != network_list_.end(); ++iter) {
239 const NetworkState* network = (*iter)->AsNetworkState();
240 DCHECK(network);
241 if (!network->update_received())
242 continue;
243 if (!network->visible())
244 break;
245 if (network->Matches(type))
246 return network;
248 return NULL;
251 std::string NetworkStateHandler::FormattedHardwareAddressForType(
252 const NetworkTypePattern& type) const {
253 const DeviceState* device = NULL;
254 const NetworkState* network = ConnectedNetworkByType(type);
255 if (network)
256 device = GetDeviceState(network->device_path());
257 else
258 device = GetDeviceStateByType(type);
259 if (!device)
260 return std::string();
261 return network_util::FormattedMacAddress(device->mac_address());
264 void NetworkStateHandler::GetVisibleNetworkListByType(
265 const NetworkTypePattern& type,
266 NetworkStateList* list) {
267 GetNetworkListByType(type,
268 false /* configured_only */,
269 true /* visible_only */,
270 0 /* no limit */,
271 list);
274 void NetworkStateHandler::GetVisibleNetworkList(NetworkStateList* list) {
275 GetVisibleNetworkListByType(NetworkTypePattern::Default(), list);
278 void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type,
279 bool configured_only,
280 bool visible_only,
281 int limit,
282 NetworkStateList* list) {
283 DCHECK(list);
284 list->clear();
285 int count = 0;
286 // Sort the network list if necessary.
287 if (!network_list_sorted_)
288 SortNetworkList();
289 for (ManagedStateList::const_iterator iter = network_list_.begin();
290 iter != network_list_.end(); ++iter) {
291 const NetworkState* network = (*iter)->AsNetworkState();
292 DCHECK(network);
293 if (!network->update_received() || !network->Matches(type))
294 continue;
295 if (configured_only && !network->IsInProfile())
296 continue;
297 if (visible_only && !network->visible())
298 continue;
299 list->push_back(network);
300 if (limit > 0 && ++count >= limit)
301 break;
305 const NetworkState* NetworkStateHandler::GetNetworkStateFromServicePath(
306 const std::string& service_path,
307 bool configured_only) const {
308 ManagedState* managed =
309 GetModifiableManagedState(&network_list_, service_path);
310 if (!managed)
311 return NULL;
312 const NetworkState* network = managed->AsNetworkState();
313 DCHECK(network);
314 if (!network->update_received() ||
315 (configured_only && !network->IsInProfile())) {
316 return NULL;
318 return network;
321 const NetworkState* NetworkStateHandler::GetNetworkStateFromGuid(
322 const std::string& guid) const {
323 DCHECK(!guid.empty());
324 for (ManagedStateList::const_iterator iter = network_list_.begin();
325 iter != network_list_.end(); ++iter) {
326 const NetworkState* network = (*iter)->AsNetworkState();
327 if (network->guid() == guid)
328 return network;
330 return NULL;
333 void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const {
334 GetDeviceListByType(NetworkTypePattern::Default(), list);
337 void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type,
338 DeviceStateList* list) const {
339 DCHECK(list);
340 list->clear();
341 for (ManagedStateList::const_iterator iter = device_list_.begin();
342 iter != device_list_.end(); ++iter) {
343 const DeviceState* device = (*iter)->AsDeviceState();
344 DCHECK(device);
345 if (device->update_received() && device->Matches(type))
346 list->push_back(device);
350 void NetworkStateHandler::RequestScan() const {
351 NET_LOG_USER("RequestScan", "");
352 shill_property_handler_->RequestScan();
355 void NetworkStateHandler::RequestUpdateForNetwork(
356 const std::string& service_path) {
357 NetworkState* network = GetModifiableNetworkState(service_path);
358 if (network)
359 network->set_update_requested(true);
360 NET_LOG_EVENT("RequestUpdate", service_path);
361 shill_property_handler_->RequestProperties(
362 ManagedState::MANAGED_TYPE_NETWORK, service_path);
365 void NetworkStateHandler::ClearLastErrorForNetwork(
366 const std::string& service_path) {
367 NetworkState* network = GetModifiableNetworkState(service_path);
368 if (network)
369 network->clear_last_error();
372 void NetworkStateHandler::SetCheckPortalList(
373 const std::string& check_portal_list) {
374 NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
375 shill_property_handler_->SetCheckPortalList(check_portal_list);
378 void NetworkStateHandler::SetWakeOnLanEnabled(bool enabled) {
379 NET_LOG_EVENT("SetWakeOnLanEnabled",
380 base::StringPrintf("%s", enabled ? "true" : "false"));
381 shill_property_handler_->SetWakeOnLanEnabled(enabled);
384 const NetworkState* NetworkStateHandler::GetEAPForEthernet(
385 const std::string& service_path) {
386 const NetworkState* network = GetNetworkState(service_path);
387 if (!network) {
388 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path);
389 return NULL;
391 if (network->type() != shill::kTypeEthernet) {
392 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path);
393 return NULL;
395 if (!network->IsConnectedState())
396 return NULL;
398 // The same EAP service is shared for all ethernet services/devices.
399 // However EAP is used/enabled per device and only if the connection was
400 // successfully established.
401 const DeviceState* device = GetDeviceState(network->device_path());
402 if (!device) {
403 NET_LOG_ERROR(
404 "GetEAPForEthernet",
405 base::StringPrintf("Unknown device %s of connected ethernet service %s",
406 network->device_path().c_str(),
407 service_path.c_str()));
408 return NULL;
410 if (!device->eap_authentication_completed())
411 return NULL;
413 NetworkStateList list;
414 GetNetworkListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap),
415 true /* configured_only */,
416 false /* visible_only */,
417 1 /* limit */,
418 &list);
419 if (list.empty()) {
420 NET_LOG_ERROR("GetEAPForEthernet",
421 base::StringPrintf(
422 "Ethernet service %s connected using EAP, but no "
423 "EAP service found.",
424 service_path.c_str()));
425 return NULL;
427 return list.front();
430 //------------------------------------------------------------------------------
431 // ShillPropertyHandler::Delegate overrides
433 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type,
434 const base::ListValue& entries) {
435 ManagedStateList* managed_list = GetManagedList(type);
436 NET_LOG_DEBUG("UpdateManagedList: " + ManagedState::TypeToString(type),
437 base::StringPrintf("%" PRIuS, entries.GetSize()));
438 // Create a map of existing entries. Assumes all entries in |managed_list|
439 // are unique.
440 typedef std::map<std::string, ManagedState*> ManagedMap;
441 ManagedMap managed_map;
442 for (ManagedStateList::iterator iter = managed_list->begin();
443 iter != managed_list->end(); ++iter) {
444 ManagedState* managed = *iter;
445 DCHECK(!ContainsKey(managed_map, managed->path()));
446 managed_map[managed->path()] = managed;
448 // Clear the list (pointers are temporarily owned by managed_map).
449 managed_list->clear();
450 // Updates managed_list and request updates for new entries.
451 std::set<std::string> list_entries;
452 for (base::ListValue::const_iterator iter = entries.begin();
453 iter != entries.end(); ++iter) {
454 std::string path;
455 (*iter)->GetAsString(&path);
456 if (path.empty() || path == shill::kFlimflamServicePath) {
457 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path);
458 continue;
460 ManagedMap::iterator found = managed_map.find(path);
461 if (found == managed_map.end()) {
462 if (list_entries.count(path) != 0) {
463 NET_LOG_ERROR("Duplicate entry in list", path);
464 continue;
466 ManagedState* managed = ManagedState::Create(type, path);
467 managed_list->push_back(managed);
468 } else {
469 managed_list->push_back(found->second);
470 managed_map.erase(found);
472 list_entries.insert(path);
474 // Delete any remaining entries in managed_map.
475 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
478 void NetworkStateHandler::ProfileListChanged() {
479 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
480 for (ManagedStateList::iterator iter = network_list_.begin();
481 iter != network_list_.end(); ++iter) {
482 NetworkState* network = (*iter)->AsNetworkState();
483 DCHECK(network);
484 shill_property_handler_->RequestProperties(
485 ManagedState::MANAGED_TYPE_NETWORK, network->path());
489 void NetworkStateHandler::UpdateManagedStateProperties(
490 ManagedState::ManagedType type,
491 const std::string& path,
492 const base::DictionaryValue& properties) {
493 ManagedStateList* managed_list = GetManagedList(type);
494 ManagedState* managed = GetModifiableManagedState(managed_list, path);
495 if (!managed) {
496 // The network has been removed from the list of networks.
497 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path);
498 return;
500 managed->set_update_received();
502 std::string desc = GetManagedStateLogType(managed) + " Properties Received";
503 NET_LOG_DEBUG(desc, GetLogName(managed));
505 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
506 UpdateNetworkStateProperties(managed->AsNetworkState(), properties);
507 } else {
508 // Device
509 for (base::DictionaryValue::Iterator iter(properties);
510 !iter.IsAtEnd(); iter.Advance()) {
511 managed->PropertyChanged(iter.key(), iter.value());
513 managed->InitialPropertiesReceived(properties);
515 managed->set_update_requested(false);
518 void NetworkStateHandler::UpdateNetworkStateProperties(
519 NetworkState* network,
520 const base::DictionaryValue& properties) {
521 DCHECK(network);
522 bool network_property_updated = false;
523 std::string prev_connection_state = network->connection_state();
524 bool prev_is_captive_portal = network->is_captive_portal();
525 for (base::DictionaryValue::Iterator iter(properties);
526 !iter.IsAtEnd(); iter.Advance()) {
527 if (network->PropertyChanged(iter.key(), iter.value()))
528 network_property_updated = true;
530 network_property_updated |= network->InitialPropertiesReceived(properties);
531 UpdateGuid(network);
532 network_list_sorted_ = false;
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 prev_is_captive_portal)) {
539 OnNetworkConnectionStateChanged(network);
541 NET_LOG_EVENT("NetworkPropertiesUpdated", GetLogName(network));
542 NotifyNetworkPropertiesUpdated(network);
546 void NetworkStateHandler::UpdateNetworkServiceProperty(
547 const std::string& service_path,
548 const std::string& key,
549 const base::Value& value) {
550 SCOPED_NET_LOG_IF_SLOW();
551 bool changed = false;
552 NetworkState* network = GetModifiableNetworkState(service_path);
553 if (!network)
554 return;
555 std::string prev_connection_state = network->connection_state();
556 bool prev_is_captive_portal = network->is_captive_portal();
557 std::string prev_profile_path = network->profile_path();
558 changed |= network->PropertyChanged(key, value);
559 if (!changed)
560 return;
562 if (key == shill::kStateProperty || key == shill::kVisibleProperty) {
563 network_list_sorted_ = false;
564 if (ConnectionStateChanged(network, prev_connection_state,
565 prev_is_captive_portal)) {
566 OnNetworkConnectionStateChanged(network);
567 // If the connection state changes, other properties such as IPConfig
568 // may have changed, so request a full update.
569 RequestUpdateForNetwork(service_path);
571 } else {
572 std::string value_str;
573 value.GetAsString(&value_str);
574 // Some property changes are noisy and not interesting:
575 // * Wifi SignalStrength
576 // * WifiFrequencyList updates
577 // * Device property changes to "/" (occurs before a service is removed)
578 if (key != shill::kSignalStrengthProperty &&
579 key != shill::kWifiFrequencyListProperty &&
580 (key != shill::kDeviceProperty || value_str != "/")) {
581 std::string log_event = "NetworkPropertyUpdated";
582 // Trigger a default network update for interesting changes only.
583 if (network->path() == default_network_path_) {
584 NotifyDefaultNetworkChanged(network);
585 log_event = "Default" + log_event;
587 // Log event.
588 std::string detail = network->name() + "." + key;
589 detail += " = " + ValueAsString(value);
590 device_event_log::LogLevel log_level;
591 if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) {
592 log_level = device_event_log::LOG_LEVEL_ERROR;
593 } else {
594 log_level = device_event_log::LOG_LEVEL_EVENT;
596 NET_LOG_LEVEL(log_level, log_event, detail);
600 // All property updates signal 'NetworkPropertiesUpdated'.
601 NotifyNetworkPropertiesUpdated(network);
603 // If added to a Profile, request a full update so that a NetworkState
604 // gets created.
605 if (prev_profile_path.empty() && !network->profile_path().empty())
606 RequestUpdateForNetwork(service_path);
609 void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path,
610 const std::string& key,
611 const base::Value& value) {
612 SCOPED_NET_LOG_IF_SLOW();
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 += " = " + ValueAsString(value);
621 NET_LOG_EVENT("DevicePropertyUpdated", detail);
623 NotifyDeviceListChanged();
624 NotifyDevicePropertiesUpdated(device);
626 if (key == shill::kScanningProperty && device->scanning() == false) {
627 NotifyScanCompleted(device);
629 if (key == shill::kEapAuthenticationCompletedProperty) {
630 // Notify a change for each Ethernet service using this device.
631 NetworkStateList ethernet_services;
632 GetNetworkListByType(NetworkTypePattern::Ethernet(),
633 false /* configured_only */,
634 false /* visible_only */,
635 0 /* no limit */,
636 &ethernet_services);
637 for (NetworkStateList::const_iterator it = ethernet_services.begin();
638 it != ethernet_services.end(); ++it) {
639 const NetworkState* ethernet_service = *it;
640 if (ethernet_service->update_received() ||
641 ethernet_service->device_path() != device->path()) {
642 continue;
644 RequestUpdateForNetwork(ethernet_service->path());
649 void NetworkStateHandler::UpdateIPConfigProperties(
650 ManagedState::ManagedType type,
651 const std::string& path,
652 const std::string& ip_config_path,
653 const base::DictionaryValue& properties) {
654 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
655 NetworkState* network = GetModifiableNetworkState(path);
656 if (!network)
657 return;
658 network->IPConfigPropertiesChanged(properties);
659 NotifyNetworkPropertiesUpdated(network);
660 if (network->path() == default_network_path_)
661 NotifyDefaultNetworkChanged(network);
662 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
663 DeviceState* device = GetModifiableDeviceState(path);
664 if (!device)
665 return;
666 device->IPConfigPropertiesChanged(ip_config_path, properties);
667 NotifyDevicePropertiesUpdated(device);
668 if (!default_network_path_.empty()) {
669 const NetworkState* default_network =
670 GetNetworkState(default_network_path_);
671 if (default_network && default_network->device_path() == path)
672 NotifyDefaultNetworkChanged(default_network);
677 void NetworkStateHandler::CheckPortalListChanged(
678 const std::string& check_portal_list) {
679 check_portal_list_ = check_portal_list;
682 void NetworkStateHandler::TechnologyListChanged() {
683 // Eventually we would like to replace Technology state with Device state.
684 // For now, treat technology state changes as device list changes.
685 NotifyDeviceListChanged();
688 void NetworkStateHandler::ManagedStateListChanged(
689 ManagedState::ManagedType type) {
690 SCOPED_NET_LOG_IF_SLOW();
691 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
692 SortNetworkList();
693 UpdateNetworkStats();
694 // Notify observers that the list of networks has changed.
695 NET_LOG_EVENT("NOTIFY:NetworkListChanged",
696 base::StringPrintf("Size:%" PRIuS, network_list_.size()));
697 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
698 NetworkListChanged());
699 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
700 std::string devices;
701 for (ManagedStateList::const_iterator iter = device_list_.begin();
702 iter != device_list_.end(); ++iter) {
703 if (iter != device_list_.begin())
704 devices += ", ";
705 devices += (*iter)->name();
707 NET_LOG_EVENT("DeviceList", devices);
708 NotifyDeviceListChanged();
709 } else {
710 NOTREACHED();
714 void NetworkStateHandler::SortNetworkList() {
715 // Note: usually active networks will precede inactive networks, however
716 // this may briefly be untrue during state transitions (e.g. a network may
717 // transition to idle before the list is updated).
718 ManagedStateList active, non_wifi_visible, wifi_visible, hidden, new_networks;
719 for (ManagedStateList::iterator iter = network_list_.begin();
720 iter != network_list_.end(); ++iter) {
721 NetworkState* network = (*iter)->AsNetworkState();
722 if (!network->update_received()) {
723 new_networks.push_back(network);
724 continue;
726 if (network->IsConnectedState() || network->IsConnectingState()) {
727 active.push_back(network);
728 continue;
730 if (network->visible()) {
731 if (NetworkTypePattern::WiFi().MatchesType(network->type()))
732 wifi_visible.push_back(network);
733 else
734 non_wifi_visible.push_back(network);
735 } else {
736 hidden.push_back(network);
739 network_list_.clear();
740 network_list_.insert(network_list_.end(), active.begin(), active.end());
741 network_list_.insert(
742 network_list_.end(), non_wifi_visible.begin(), non_wifi_visible.end());
743 network_list_.insert(
744 network_list_.end(), wifi_visible.begin(), wifi_visible.end());
745 network_list_.insert(network_list_.end(), hidden.begin(), hidden.end());
746 network_list_.insert(
747 network_list_.end(), new_networks.begin(), new_networks.end());
748 network_list_sorted_ = true;
751 void NetworkStateHandler::UpdateNetworkStats() {
752 size_t shared = 0, unshared = 0, visible = 0;
753 for (ManagedStateList::iterator iter = network_list_.begin();
754 iter != network_list_.end(); ++iter) {
755 NetworkState* network = (*iter)->AsNetworkState();
756 if (network->visible())
757 ++visible;
758 if (network->IsInProfile()) {
759 if (network->IsPrivate())
760 ++unshared;
761 else
762 ++shared;
765 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", visible);
766 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared);
767 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared);
770 void NetworkStateHandler::DefaultNetworkServiceChanged(
771 const std::string& service_path) {
772 // Shill uses '/' for empty service path values; check explicitly for that.
773 const char* kEmptyServicePath = "/";
774 std::string new_service_path =
775 (service_path != kEmptyServicePath) ? service_path : "";
776 if (new_service_path == default_network_path_)
777 return;
779 default_network_path_ = service_path;
780 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_);
781 const NetworkState* network = NULL;
782 if (!default_network_path_.empty()) {
783 network = GetNetworkState(default_network_path_);
784 if (!network) {
785 // If NetworkState is not available yet, do not notify observers here,
786 // they will be notified when the state is received.
787 NET_LOG_DEBUG("Default NetworkState not available",
788 default_network_path_);
789 return;
792 if (network && !network->IsConnectedState()) {
793 NET_LOG_ERROR(
794 "DefaultNetwork is not connected: " + network->connection_state(),
795 network->path());
797 NotifyDefaultNetworkChanged(network);
800 //------------------------------------------------------------------------------
801 // Private methods
803 void NetworkStateHandler::UpdateGuid(NetworkState* network) {
804 std::string specifier = network->GetSpecifier();
805 DCHECK(!specifier.empty());
806 if (!network->guid().empty()) {
807 // If the network is saved in a profile, remove the entry from the map.
808 // Otherwise ensure that the entry matches the specified GUID. (e.g. in
809 // case a visible network with a specified guid gets configured with a
810 // new guid).
811 if (network->IsInProfile())
812 specifier_guid_map_.erase(specifier);
813 else
814 specifier_guid_map_[specifier] = network->guid();
815 return;
817 // Ensure that the NetworkState has a valid GUID.
818 std::string guid;
819 SpecifierGuidMap::iterator iter = specifier_guid_map_.find(specifier);
820 if (iter != specifier_guid_map_.end()) {
821 guid = iter->second;
822 } else {
823 guid = base::GenerateGUID();
824 specifier_guid_map_[specifier] = guid;
826 network->SetGuid(guid);
829 void NetworkStateHandler::NotifyDeviceListChanged() {
830 SCOPED_NET_LOG_IF_SLOW();
831 NET_LOG_DEBUG("NOTIFY:DeviceListChanged",
832 base::StringPrintf("Size:%" PRIuS, device_list_.size()));
833 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
834 DeviceListChanged());
837 DeviceState* NetworkStateHandler::GetModifiableDeviceState(
838 const std::string& device_path) const {
839 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
840 if (!managed)
841 return NULL;
842 return managed->AsDeviceState();
845 NetworkState* NetworkStateHandler::GetModifiableNetworkState(
846 const std::string& service_path) const {
847 ManagedState* managed =
848 GetModifiableManagedState(&network_list_, service_path);
849 if (!managed)
850 return NULL;
851 return managed->AsNetworkState();
854 ManagedState* NetworkStateHandler::GetModifiableManagedState(
855 const ManagedStateList* managed_list,
856 const std::string& path) const {
857 for (ManagedStateList::const_iterator iter = managed_list->begin();
858 iter != managed_list->end(); ++iter) {
859 ManagedState* managed = *iter;
860 if (managed->path() == path)
861 return managed;
863 return NULL;
866 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
867 ManagedState::ManagedType type) {
868 switch (type) {
869 case ManagedState::MANAGED_TYPE_NETWORK:
870 return &network_list_;
871 case ManagedState::MANAGED_TYPE_DEVICE:
872 return &device_list_;
874 NOTREACHED();
875 return NULL;
878 void NetworkStateHandler::OnNetworkConnectionStateChanged(
879 NetworkState* network) {
880 SCOPED_NET_LOG_IF_SLOW();
881 DCHECK(network);
882 std::string event = "NetworkConnectionStateChanged";
883 if (network->path() == default_network_path_) {
884 event = "Default" + event;
885 if (!network->IsConnectedState()) {
886 NET_LOG_EVENT(
887 "DefaultNetwork is not connected: " + network->connection_state(),
888 network->path());
889 default_network_path_.clear();
890 SortNetworkList();
891 NotifyDefaultNetworkChanged(NULL);
894 NET_LOG_EVENT("NOTIFY:" + event + ": " + network->connection_state(),
895 GetLogName(network));
896 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
897 NetworkConnectionStateChanged(network));
898 if (network->path() == default_network_path_)
899 NotifyDefaultNetworkChanged(network);
902 void NetworkStateHandler::NotifyDefaultNetworkChanged(
903 const NetworkState* default_network) {
904 SCOPED_NET_LOG_IF_SLOW();
905 NET_LOG_EVENT("NOTIFY:DefaultNetworkChanged", GetLogName(default_network));
906 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
907 DefaultNetworkChanged(default_network));
910 void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
911 const NetworkState* network) {
912 SCOPED_NET_LOG_IF_SLOW();
913 NET_LOG_DEBUG("NOTIFY:NetworkPropertiesUpdated", GetLogName(network));
914 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
915 NetworkPropertiesUpdated(network));
918 void NetworkStateHandler::NotifyDevicePropertiesUpdated(
919 const DeviceState* device) {
920 SCOPED_NET_LOG_IF_SLOW();
921 NET_LOG_DEBUG("NOTIFY:DevicePropertiesUpdated", GetLogName(device));
922 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
923 DevicePropertiesUpdated(device));
926 void NetworkStateHandler::NotifyScanCompleted(const DeviceState* device) {
927 SCOPED_NET_LOG_IF_SLOW();
928 NET_LOG_DEBUG("NOTIFY:ScanCompleted", GetLogName(device));
929 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
930 ScanCompleted(device));
933 std::string NetworkStateHandler::GetTechnologyForType(
934 const NetworkTypePattern& type) const {
935 if (type.MatchesType(shill::kTypeEthernet))
936 return shill::kTypeEthernet;
938 if (type.MatchesType(shill::kTypeWifi))
939 return shill::kTypeWifi;
941 if (type.Equals(NetworkTypePattern::Wimax()))
942 return shill::kTypeWimax;
944 // Prefer Wimax over Cellular only if it's available.
945 if (type.MatchesType(shill::kTypeWimax) &&
946 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
947 return shill::kTypeWimax;
950 if (type.MatchesType(shill::kTypeCellular))
951 return shill::kTypeCellular;
953 NOTREACHED();
954 return std::string();
957 ScopedVector<std::string> NetworkStateHandler::GetTechnologiesForType(
958 const NetworkTypePattern& type) const {
959 ScopedVector<std::string> technologies;
960 if (type.MatchesType(shill::kTypeEthernet))
961 technologies.push_back(new std::string(shill::kTypeEthernet));
962 if (type.MatchesType(shill::kTypeWifi))
963 technologies.push_back(new std::string(shill::kTypeWifi));
964 if (type.MatchesType(shill::kTypeWimax))
965 technologies.push_back(new std::string(shill::kTypeWimax));
966 if (type.MatchesType(shill::kTypeCellular))
967 technologies.push_back(new std::string(shill::kTypeCellular));
968 if (type.MatchesType(shill::kTypeBluetooth))
969 technologies.push_back(new std::string(shill::kTypeBluetooth));
970 if (type.MatchesType(shill::kTypeVPN))
971 technologies.push_back(new std::string(shill::kTypeVPN));
973 CHECK_GT(technologies.size(), 0ul);
974 return technologies.Pass();
977 } // namespace chromeos