Update broken references to image assets
[chromium-blink-merge.git] / chromeos / network / network_state_handler.cc
blobe1f18902b2dc193c224172147fc9ced63ea196d0
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/network_event_log.h"
21 #include "chromeos/network/network_state.h"
22 #include "chromeos/network/network_state_handler_observer.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 bool prev_is_captive_portal) {
32 return ((network->connection_state() != prev_connection_state) &&
33 !((network->connection_state() == shill::kStateIdle) &&
34 prev_connection_state.empty())) ||
35 (network->is_captive_portal() != prev_is_captive_portal);
38 std::string GetManagedStateLogType(const ManagedState* state) {
39 switch (state->managed_type()) {
40 case ManagedState::MANAGED_TYPE_NETWORK:
41 return "Network";
42 case ManagedState::MANAGED_TYPE_DEVICE:
43 return "Device";
45 NOTREACHED();
46 return "";
49 std::string GetLogName(const ManagedState* state) {
50 if (!state)
51 return "None";
52 return base::StringPrintf("%s (%s)", state->name().c_str(),
53 state->path().c_str());
56 std::string ValueAsString(const base::Value& value) {
57 std::string vstr;
58 base::JSONWriter::WriteWithOptions(
59 value, base::JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &vstr);
60 return vstr.empty() ? "''" : vstr;
63 } // namespace
65 const char NetworkStateHandler::kDefaultCheckPortalList[] =
66 "ethernet,wifi,cellular";
68 NetworkStateHandler::NetworkStateHandler() : network_list_sorted_(false) {
71 NetworkStateHandler::~NetworkStateHandler() {
72 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, IsShuttingDown());
73 STLDeleteContainerPointers(network_list_.begin(), network_list_.end());
74 STLDeleteContainerPointers(device_list_.begin(), device_list_.end());
77 void NetworkStateHandler::InitShillPropertyHandler() {
78 shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
79 shill_property_handler_->Init();
82 // static
83 NetworkStateHandler* NetworkStateHandler::InitializeForTest() {
84 NetworkStateHandler* handler = new NetworkStateHandler();
85 handler->InitShillPropertyHandler();
86 return handler;
89 void NetworkStateHandler::AddObserver(
90 NetworkStateHandlerObserver* observer,
91 const tracked_objects::Location& from_here) {
92 observers_.AddObserver(observer);
93 device_event_log::AddEntry(from_here.file_name(), from_here.line_number(),
94 device_event_log::LOG_TYPE_NETWORK,
95 device_event_log::LOG_LEVEL_DEBUG,
96 "NetworkStateHandler::AddObserver");
99 void NetworkStateHandler::RemoveObserver(
100 NetworkStateHandlerObserver* observer,
101 const tracked_objects::Location& from_here) {
102 observers_.RemoveObserver(observer);
103 device_event_log::AddEntry(from_here.file_name(), from_here.line_number(),
104 device_event_log::LOG_TYPE_NETWORK,
105 device_event_log::LOG_LEVEL_DEBUG,
106 "NetworkStateHandler::RemoveObserver");
109 NetworkStateHandler::TechnologyState NetworkStateHandler::GetTechnologyState(
110 const NetworkTypePattern& type) const {
111 std::string technology = GetTechnologyForType(type);
112 TechnologyState state;
113 if (shill_property_handler_->IsTechnologyEnabled(technology))
114 state = TECHNOLOGY_ENABLED;
115 else if (shill_property_handler_->IsTechnologyEnabling(technology))
116 state = TECHNOLOGY_ENABLING;
117 else if (shill_property_handler_->IsTechnologyUninitialized(technology))
118 state = TECHNOLOGY_UNINITIALIZED;
119 else if (shill_property_handler_->IsTechnologyAvailable(technology))
120 state = TECHNOLOGY_AVAILABLE;
121 else
122 state = TECHNOLOGY_UNAVAILABLE;
123 VLOG(2) << "GetTechnologyState: " << type.ToDebugString() << " = " << state;
124 return state;
127 void NetworkStateHandler::SetTechnologyEnabled(
128 const NetworkTypePattern& type,
129 bool enabled,
130 const network_handler::ErrorCallback& error_callback) {
131 ScopedVector<std::string> technologies = GetTechnologiesForType(type);
132 for (ScopedVector<std::string>::iterator it = technologies.begin();
133 it != technologies.end(); ++it) {
134 std::string* technology = *it;
135 DCHECK(technology);
136 if (!shill_property_handler_->IsTechnologyAvailable(*technology))
137 continue;
138 NET_LOG_USER("SetTechnologyEnabled",
139 base::StringPrintf("%s:%d", technology->c_str(), enabled));
140 shill_property_handler_->SetTechnologyEnabled(*technology, enabled,
141 error_callback);
143 // Signal Device/Technology state changed.
144 NotifyDeviceListChanged();
147 const DeviceState* NetworkStateHandler::GetDeviceState(
148 const std::string& device_path) const {
149 const DeviceState* device = GetModifiableDeviceState(device_path);
150 if (device && !device->update_received())
151 return nullptr;
152 return device;
155 const DeviceState* NetworkStateHandler::GetDeviceStateByType(
156 const NetworkTypePattern& type) const {
157 for (ManagedStateList::const_iterator iter = device_list_.begin();
158 iter != device_list_.end(); ++iter) {
159 ManagedState* device = *iter;
160 if (!device->update_received())
161 continue;
162 if (device->Matches(type))
163 return device->AsDeviceState();
165 return nullptr;
168 bool NetworkStateHandler::GetScanningByType(
169 const NetworkTypePattern& type) const {
170 for (ManagedStateList::const_iterator iter = device_list_.begin();
171 iter != device_list_.end(); ++iter) {
172 const DeviceState* device = (*iter)->AsDeviceState();
173 DCHECK(device);
174 if (!device->update_received())
175 continue;
176 if (device->Matches(type) && device->scanning())
177 return true;
179 return false;
182 const NetworkState* NetworkStateHandler::GetNetworkState(
183 const std::string& service_path) const {
184 const NetworkState* network = GetModifiableNetworkState(service_path);
185 if (network && !network->update_received())
186 return nullptr;
187 return network;
190 const NetworkState* NetworkStateHandler::DefaultNetwork() const {
191 if (default_network_path_.empty())
192 return nullptr;
193 return GetNetworkState(default_network_path_);
196 const NetworkState* NetworkStateHandler::ConnectedNetworkByType(
197 const NetworkTypePattern& type) const {
198 // Active networks are always listed first by Shill so no need to sort.
199 for (ManagedStateList::const_iterator iter = network_list_.begin();
200 iter != network_list_.end(); ++iter) {
201 const NetworkState* network = (*iter)->AsNetworkState();
202 DCHECK(network);
203 if (!network->update_received())
204 continue;
205 if (!network->IsConnectedState())
206 break; // Connected networks are listed first.
207 if (network->Matches(type))
208 return network;
210 return nullptr;
213 const NetworkState* NetworkStateHandler::ConnectingNetworkByType(
214 const NetworkTypePattern& type) const {
215 // Active networks are always listed first by Shill so no need to sort.
216 for (ManagedStateList::const_iterator iter = network_list_.begin();
217 iter != network_list_.end(); ++iter) {
218 const NetworkState* network = (*iter)->AsNetworkState();
219 DCHECK(network);
220 if (!network->update_received() || network->IsConnectedState())
221 continue;
222 if (!network->IsConnectingState())
223 break; // Connected and connecting networks are listed first.
224 if (network->Matches(type))
225 return network;
227 return nullptr;
230 const NetworkState* NetworkStateHandler::FirstNetworkByType(
231 const NetworkTypePattern& type) {
232 if (!network_list_sorted_)
233 SortNetworkList(); // Sort to ensure visible networks are listed first.
234 for (ManagedStateList::const_iterator iter = network_list_.begin();
235 iter != network_list_.end(); ++iter) {
236 const NetworkState* network = (*iter)->AsNetworkState();
237 DCHECK(network);
238 if (!network->update_received())
239 continue;
240 if (!network->visible())
241 break;
242 if (network->Matches(type))
243 return network;
245 return nullptr;
248 std::string NetworkStateHandler::FormattedHardwareAddressForType(
249 const NetworkTypePattern& type) const {
250 const DeviceState* device = nullptr;
251 const NetworkState* network = ConnectedNetworkByType(type);
252 if (network)
253 device = GetDeviceState(network->device_path());
254 else
255 device = GetDeviceStateByType(type);
256 if (!device)
257 return std::string();
258 return network_util::FormattedMacAddress(device->mac_address());
261 void NetworkStateHandler::GetVisibleNetworkListByType(
262 const NetworkTypePattern& type,
263 NetworkStateList* list) {
264 GetNetworkListByType(type, false /* configured_only */,
265 true /* visible_only */, 0 /* no limit */, list);
268 void NetworkStateHandler::GetVisibleNetworkList(NetworkStateList* list) {
269 GetVisibleNetworkListByType(NetworkTypePattern::Default(), list);
272 void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type,
273 bool configured_only,
274 bool visible_only,
275 int limit,
276 NetworkStateList* list) {
277 DCHECK(list);
278 list->clear();
279 int count = 0;
280 // Sort the network list if necessary.
281 if (!network_list_sorted_)
282 SortNetworkList();
283 for (ManagedStateList::const_iterator iter = network_list_.begin();
284 iter != network_list_.end(); ++iter) {
285 const NetworkState* network = (*iter)->AsNetworkState();
286 DCHECK(network);
287 if (!network->update_received() || !network->Matches(type))
288 continue;
289 if (configured_only && !network->IsInProfile())
290 continue;
291 if (visible_only && !network->visible())
292 continue;
293 list->push_back(network);
294 if (limit > 0 && ++count >= limit)
295 break;
299 const NetworkState* NetworkStateHandler::GetNetworkStateFromServicePath(
300 const std::string& service_path,
301 bool configured_only) const {
302 ManagedState* managed =
303 GetModifiableManagedState(&network_list_, service_path);
304 if (!managed)
305 return nullptr;
306 const NetworkState* network = managed->AsNetworkState();
307 DCHECK(network);
308 if (!network->update_received() ||
309 (configured_only && !network->IsInProfile())) {
310 return nullptr;
312 return network;
315 const NetworkState* NetworkStateHandler::GetNetworkStateFromGuid(
316 const std::string& guid) const {
317 DCHECK(!guid.empty());
318 for (ManagedStateList::const_iterator iter = network_list_.begin();
319 iter != network_list_.end(); ++iter) {
320 const NetworkState* network = (*iter)->AsNetworkState();
321 if (network->guid() == guid)
322 return network;
324 return nullptr;
327 void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const {
328 GetDeviceListByType(NetworkTypePattern::Default(), list);
331 void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type,
332 DeviceStateList* list) const {
333 DCHECK(list);
334 list->clear();
335 for (ManagedStateList::const_iterator iter = device_list_.begin();
336 iter != device_list_.end(); ++iter) {
337 const DeviceState* device = (*iter)->AsDeviceState();
338 DCHECK(device);
339 if (device->update_received() && device->Matches(type))
340 list->push_back(device);
344 void NetworkStateHandler::RequestScan() const {
345 NET_LOG_USER("RequestScan", "");
346 shill_property_handler_->RequestScan();
349 void NetworkStateHandler::RequestUpdateForNetwork(
350 const std::string& service_path) {
351 NetworkState* network = GetModifiableNetworkState(service_path);
352 if (network)
353 network->set_update_requested(true);
354 NET_LOG_EVENT("RequestUpdate", service_path);
355 shill_property_handler_->RequestProperties(ManagedState::MANAGED_TYPE_NETWORK,
356 service_path);
359 void NetworkStateHandler::ClearLastErrorForNetwork(
360 const std::string& service_path) {
361 NetworkState* network = GetModifiableNetworkState(service_path);
362 if (network)
363 network->clear_last_error();
366 void NetworkStateHandler::SetCheckPortalList(
367 const std::string& check_portal_list) {
368 NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
369 shill_property_handler_->SetCheckPortalList(check_portal_list);
372 void NetworkStateHandler::SetWakeOnLanEnabled(bool enabled) {
373 NET_LOG_EVENT("SetWakeOnLanEnabled", enabled ? "true" : "false");
374 shill_property_handler_->SetWakeOnLanEnabled(enabled);
377 const NetworkState* NetworkStateHandler::GetEAPForEthernet(
378 const std::string& service_path) {
379 const NetworkState* network = GetNetworkState(service_path);
380 if (!network) {
381 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path);
382 return nullptr;
384 if (network->type() != shill::kTypeEthernet) {
385 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path);
386 return nullptr;
388 if (!network->IsConnectedState())
389 return nullptr;
391 // The same EAP service is shared for all ethernet services/devices.
392 // However EAP is used/enabled per device and only if the connection was
393 // successfully established.
394 const DeviceState* device = GetDeviceState(network->device_path());
395 if (!device) {
396 NET_LOG(ERROR) << "GetEAPForEthernet: Unknown device "
397 << network->device_path()
398 << " for connected ethernet service: " << service_path;
399 return nullptr;
401 if (!device->eap_authentication_completed())
402 return nullptr;
404 NetworkStateList list;
405 GetNetworkListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap),
406 true /* configured_only */, false /* visible_only */,
407 1 /* limit */, &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 nullptr;
416 return list.front();
419 void NetworkStateHandler::SetLastErrorForTest(const std::string& service_path,
420 const std::string& error) {
421 NetworkState* network_state = GetModifiableNetworkState(service_path);
422 if (!network_state) {
423 LOG(ERROR) << "No matching NetworkState for: " << service_path;
424 return;
426 network_state->last_error_ = error;
429 //------------------------------------------------------------------------------
430 // ShillPropertyHandler::Delegate overrides
432 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type,
433 const base::ListValue& entries) {
434 ManagedStateList* managed_list = GetManagedList(type);
435 NET_LOG_DEBUG("UpdateManagedList: " + ManagedState::TypeToString(type),
436 base::StringPrintf("%" PRIuS, entries.GetSize()));
437 // Create a map of existing entries. Assumes all entries in |managed_list|
438 // are unique.
439 typedef std::map<std::string, ManagedState*> ManagedMap;
440 ManagedMap managed_map;
441 for (ManagedStateList::iterator iter = managed_list->begin();
442 iter != managed_list->end(); ++iter) {
443 ManagedState* managed = *iter;
444 DCHECK(!ContainsKey(managed_map, managed->path()));
445 managed_map[managed->path()] = managed;
447 // Clear the list (pointers are temporarily owned by managed_map).
448 managed_list->clear();
449 // Updates managed_list and request updates for new entries.
450 std::set<std::string> list_entries;
451 for (base::ListValue::const_iterator iter = entries.begin();
452 iter != entries.end(); ++iter) {
453 std::string path;
454 (*iter)->GetAsString(&path);
455 if (path.empty() || path == shill::kFlimflamServicePath) {
456 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path);
457 continue;
459 ManagedMap::iterator found = managed_map.find(path);
460 if (found == managed_map.end()) {
461 if (list_entries.count(path) != 0) {
462 NET_LOG_ERROR("Duplicate entry in list", path);
463 continue;
465 ManagedState* managed = ManagedState::Create(type, path);
466 managed_list->push_back(managed);
467 } else {
468 managed_list->push_back(found->second);
469 managed_map.erase(found);
471 list_entries.insert(path);
473 // Delete any remaining entries in managed_map.
474 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
477 void NetworkStateHandler::ProfileListChanged() {
478 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
479 for (ManagedStateList::iterator iter = network_list_.begin();
480 iter != network_list_.end(); ++iter) {
481 NetworkState* network = (*iter)->AsNetworkState();
482 DCHECK(network);
483 shill_property_handler_->RequestProperties(
484 ManagedState::MANAGED_TYPE_NETWORK, network->path());
488 void NetworkStateHandler::UpdateManagedStateProperties(
489 ManagedState::ManagedType type,
490 const std::string& path,
491 const base::DictionaryValue& properties) {
492 ManagedStateList* managed_list = GetManagedList(type);
493 ManagedState* managed = GetModifiableManagedState(managed_list, path);
494 if (!managed) {
495 // The network has been removed from the list of networks.
496 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path);
497 return;
499 managed->set_update_received();
501 std::string desc = GetManagedStateLogType(managed) + " Properties Received";
502 NET_LOG_DEBUG(desc, GetLogName(managed));
504 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
505 UpdateNetworkStateProperties(managed->AsNetworkState(), properties);
506 } else {
507 // Device
508 for (base::DictionaryValue::Iterator iter(properties); !iter.IsAtEnd();
509 iter.Advance()) {
510 managed->PropertyChanged(iter.key(), iter.value());
512 managed->InitialPropertiesReceived(properties);
514 managed->set_update_requested(false);
517 void NetworkStateHandler::UpdateNetworkStateProperties(
518 NetworkState* network,
519 const base::DictionaryValue& properties) {
520 DCHECK(network);
521 bool network_property_updated = false;
522 std::string prev_connection_state = network->connection_state();
523 bool prev_is_captive_portal = network->is_captive_portal();
524 for (base::DictionaryValue::Iterator iter(properties); !iter.IsAtEnd();
525 iter.Advance()) {
526 if (network->PropertyChanged(iter.key(), iter.value()))
527 network_property_updated = true;
529 network_property_updated |= network->InitialPropertiesReceived(properties);
530 UpdateGuid(network);
531 network_list_sorted_ = false;
533 // Notify observers of NetworkState changes.
534 if (network_property_updated || network->update_requested()) {
535 // Signal connection state changed after all properties have been updated.
536 if (ConnectionStateChanged(network, prev_connection_state,
537 prev_is_captive_portal)) {
538 OnNetworkConnectionStateChanged(network);
540 NET_LOG_EVENT("NetworkPropertiesUpdated", GetLogName(network));
541 NotifyNetworkPropertiesUpdated(network);
545 void NetworkStateHandler::UpdateNetworkServiceProperty(
546 const std::string& service_path,
547 const std::string& key,
548 const base::Value& value) {
549 SCOPED_NET_LOG_IF_SLOW();
550 bool changed = false;
551 NetworkState* network = GetModifiableNetworkState(service_path);
552 if (!network)
553 return;
554 std::string prev_connection_state = network->connection_state();
555 bool prev_is_captive_portal = network->is_captive_portal();
556 std::string prev_profile_path = network->profile_path();
557 changed |= network->PropertyChanged(key, value);
558 if (!changed)
559 return;
561 if (key == shill::kStateProperty || key == shill::kVisibleProperty) {
562 network_list_sorted_ = false;
563 if (ConnectionStateChanged(network, prev_connection_state,
564 prev_is_captive_portal)) {
565 OnNetworkConnectionStateChanged(network);
566 // If the connection state changes, other properties such as IPConfig
567 // may have changed, so request a full update.
568 RequestUpdateForNetwork(service_path);
570 } else {
571 std::string value_str;
572 value.GetAsString(&value_str);
573 // Some property changes are noisy and not interesting:
574 // * Wifi SignalStrength
575 // * WifiFrequencyList updates
576 // * Device property changes to "/" (occurs before a service is removed)
577 if (key != shill::kSignalStrengthProperty &&
578 key != shill::kWifiFrequencyListProperty &&
579 (key != shill::kDeviceProperty || value_str != "/")) {
580 std::string log_event = "NetworkPropertyUpdated";
581 // Trigger a default network update for interesting changes only.
582 if (network->path() == default_network_path_) {
583 NotifyDefaultNetworkChanged(network);
584 log_event = "Default" + log_event;
586 // Log event.
587 std::string detail = network->name() + "." + key;
588 detail += " = " + ValueAsString(value);
589 device_event_log::LogLevel log_level;
590 if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) {
591 log_level = device_event_log::LOG_LEVEL_ERROR;
592 } else {
593 log_level = device_event_log::LOG_LEVEL_EVENT;
595 NET_LOG_LEVEL(log_level, log_event, detail);
599 // All property updates signal 'NetworkPropertiesUpdated'.
600 NotifyNetworkPropertiesUpdated(network);
602 // If added to a Profile, request a full update so that a NetworkState
603 // gets created.
604 if (prev_profile_path.empty() && !network->profile_path().empty())
605 RequestUpdateForNetwork(service_path);
608 void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path,
609 const std::string& key,
610 const base::Value& value) {
611 SCOPED_NET_LOG_IF_SLOW();
612 DeviceState* device = GetModifiableDeviceState(device_path);
613 if (!device)
614 return;
615 if (!device->PropertyChanged(key, value))
616 return;
618 std::string detail = device->name() + "." + key;
619 detail += " = " + ValueAsString(value);
620 NET_LOG_EVENT("DevicePropertyUpdated", detail);
622 NotifyDeviceListChanged();
623 NotifyDevicePropertiesUpdated(device);
625 if (key == shill::kScanningProperty && device->scanning() == false) {
626 NotifyScanCompleted(device);
628 if (key == shill::kEapAuthenticationCompletedProperty) {
629 // Notify a change for each Ethernet service using this device.
630 NetworkStateList ethernet_services;
631 GetNetworkListByType(NetworkTypePattern::Ethernet(),
632 false /* configured_only */, false /* visible_only */,
633 0 /* no limit */, &ethernet_services);
634 for (NetworkStateList::const_iterator it = ethernet_services.begin();
635 it != ethernet_services.end(); ++it) {
636 const NetworkState* ethernet_service = *it;
637 if (ethernet_service->update_received() ||
638 ethernet_service->device_path() != device->path()) {
639 continue;
641 RequestUpdateForNetwork(ethernet_service->path());
646 void NetworkStateHandler::UpdateIPConfigProperties(
647 ManagedState::ManagedType type,
648 const std::string& path,
649 const std::string& ip_config_path,
650 const base::DictionaryValue& properties) {
651 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
652 NetworkState* network = GetModifiableNetworkState(path);
653 if (!network)
654 return;
655 network->IPConfigPropertiesChanged(properties);
656 NotifyNetworkPropertiesUpdated(network);
657 if (network->path() == default_network_path_)
658 NotifyDefaultNetworkChanged(network);
659 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
660 DeviceState* device = GetModifiableDeviceState(path);
661 if (!device)
662 return;
663 device->IPConfigPropertiesChanged(ip_config_path, properties);
664 NotifyDevicePropertiesUpdated(device);
665 if (!default_network_path_.empty()) {
666 const NetworkState* default_network =
667 GetNetworkState(default_network_path_);
668 if (default_network && default_network->device_path() == path)
669 NotifyDefaultNetworkChanged(default_network);
674 void NetworkStateHandler::CheckPortalListChanged(
675 const std::string& check_portal_list) {
676 check_portal_list_ = check_portal_list;
679 void NetworkStateHandler::TechnologyListChanged() {
680 // Eventually we would like to replace Technology state with Device state.
681 // For now, treat technology state changes as device list changes.
682 NotifyDeviceListChanged();
685 void NetworkStateHandler::ManagedStateListChanged(
686 ManagedState::ManagedType type) {
687 SCOPED_NET_LOG_IF_SLOW();
688 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
689 SortNetworkList();
690 UpdateNetworkStats();
691 // Notify observers that the list of networks has changed.
692 NET_LOG_EVENT("NOTIFY:NetworkListChanged",
693 base::StringPrintf("Size:%" PRIuS, network_list_.size()));
694 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
695 NetworkListChanged());
696 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
697 std::string devices;
698 for (ManagedStateList::const_iterator iter = device_list_.begin();
699 iter != device_list_.end(); ++iter) {
700 if (iter != device_list_.begin())
701 devices += ", ";
702 devices += (*iter)->name();
704 NET_LOG_EVENT("DeviceList", devices);
705 NotifyDeviceListChanged();
706 } else {
707 NOTREACHED();
711 void NetworkStateHandler::SortNetworkList() {
712 // Note: usually active networks will precede inactive networks, however
713 // this may briefly be untrue during state transitions (e.g. a network may
714 // transition to idle before the list is updated).
715 ManagedStateList active, non_wifi_visible, wifi_visible, hidden, new_networks;
716 for (ManagedStateList::iterator iter = network_list_.begin();
717 iter != network_list_.end(); ++iter) {
718 NetworkState* network = (*iter)->AsNetworkState();
719 if (!network->update_received()) {
720 new_networks.push_back(network);
721 continue;
723 if (network->IsConnectedState() || network->IsConnectingState()) {
724 active.push_back(network);
725 continue;
727 if (network->visible()) {
728 if (NetworkTypePattern::WiFi().MatchesType(network->type()))
729 wifi_visible.push_back(network);
730 else
731 non_wifi_visible.push_back(network);
732 } else {
733 hidden.push_back(network);
736 network_list_.clear();
737 network_list_.insert(network_list_.end(), active.begin(), active.end());
738 network_list_.insert(network_list_.end(), non_wifi_visible.begin(),
739 non_wifi_visible.end());
740 network_list_.insert(network_list_.end(), wifi_visible.begin(),
741 wifi_visible.end());
742 network_list_.insert(network_list_.end(), hidden.begin(), hidden.end());
743 network_list_.insert(network_list_.end(), new_networks.begin(),
744 new_networks.end());
745 network_list_sorted_ = true;
748 void NetworkStateHandler::UpdateNetworkStats() {
749 size_t shared = 0, unshared = 0, visible = 0;
750 for (ManagedStateList::iterator iter = network_list_.begin();
751 iter != network_list_.end(); ++iter) {
752 NetworkState* network = (*iter)->AsNetworkState();
753 if (network->visible())
754 ++visible;
755 if (network->IsInProfile()) {
756 if (network->IsPrivate())
757 ++unshared;
758 else
759 ++shared;
762 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", visible);
763 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared);
764 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared);
767 void NetworkStateHandler::DefaultNetworkServiceChanged(
768 const std::string& service_path) {
769 // Shill uses '/' for empty service path values; check explicitly for that.
770 const char* kEmptyServicePath = "/";
771 std::string new_service_path =
772 (service_path != kEmptyServicePath) ? service_path : "";
773 if (new_service_path == default_network_path_)
774 return;
776 default_network_path_ = service_path;
777 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_);
778 const NetworkState* network = nullptr;
779 if (!default_network_path_.empty()) {
780 network = GetNetworkState(default_network_path_);
781 if (!network) {
782 // If NetworkState is not available yet, do not notify observers here,
783 // they will be notified when the state is received.
784 NET_LOG(EVENT) << "Default NetworkState not available: "
785 << default_network_path_;
786 return;
789 if (network && !network->IsConnectedState()) {
790 if (network->IsConnectingState()) {
791 NET_LOG(EVENT) << "DefaultNetwork is connecting: " << GetLogName(network)
792 << ": " << network->connection_state();
793 } else {
794 NET_LOG(ERROR) << "DefaultNetwork in unexpected state: "
795 << GetLogName(network) << ": "
796 << network->connection_state();
798 // Do not notify observers here, the notification will occur when the
799 // connection state changes.
800 return;
802 NotifyDefaultNetworkChanged(network);
805 //------------------------------------------------------------------------------
806 // Private methods
808 void NetworkStateHandler::UpdateGuid(NetworkState* network) {
809 std::string specifier = network->GetSpecifier();
810 DCHECK(!specifier.empty());
811 if (!network->guid().empty()) {
812 // If the network is saved in a profile, remove the entry from the map.
813 // Otherwise ensure that the entry matches the specified GUID. (e.g. in
814 // case a visible network with a specified guid gets configured with a
815 // new guid).
816 if (network->IsInProfile())
817 specifier_guid_map_.erase(specifier);
818 else
819 specifier_guid_map_[specifier] = network->guid();
820 return;
822 // Ensure that the NetworkState has a valid GUID.
823 std::string guid;
824 SpecifierGuidMap::iterator iter = specifier_guid_map_.find(specifier);
825 if (iter != specifier_guid_map_.end()) {
826 guid = iter->second;
827 } else {
828 guid = base::GenerateGUID();
829 specifier_guid_map_[specifier] = guid;
831 network->SetGuid(guid);
834 void NetworkStateHandler::NotifyDeviceListChanged() {
835 SCOPED_NET_LOG_IF_SLOW();
836 NET_LOG_DEBUG("NOTIFY:DeviceListChanged",
837 base::StringPrintf("Size:%" PRIuS, device_list_.size()));
838 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
839 DeviceListChanged());
842 DeviceState* NetworkStateHandler::GetModifiableDeviceState(
843 const std::string& device_path) const {
844 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
845 if (!managed)
846 return nullptr;
847 return managed->AsDeviceState();
850 NetworkState* NetworkStateHandler::GetModifiableNetworkState(
851 const std::string& service_path) const {
852 ManagedState* managed =
853 GetModifiableManagedState(&network_list_, service_path);
854 if (!managed)
855 return nullptr;
856 return managed->AsNetworkState();
859 ManagedState* NetworkStateHandler::GetModifiableManagedState(
860 const ManagedStateList* managed_list,
861 const std::string& path) const {
862 for (ManagedStateList::const_iterator iter = managed_list->begin();
863 iter != managed_list->end(); ++iter) {
864 ManagedState* managed = *iter;
865 if (managed->path() == path)
866 return managed;
868 return nullptr;
871 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
872 ManagedState::ManagedType type) {
873 switch (type) {
874 case ManagedState::MANAGED_TYPE_NETWORK:
875 return &network_list_;
876 case ManagedState::MANAGED_TYPE_DEVICE:
877 return &device_list_;
879 NOTREACHED();
880 return nullptr;
883 void NetworkStateHandler::OnNetworkConnectionStateChanged(
884 NetworkState* network) {
885 SCOPED_NET_LOG_IF_SLOW();
886 DCHECK(network);
887 bool notify_default = false;
888 if (network->path() == default_network_path_) {
889 if (network->IsConnectedState()) {
890 notify_default = true;
891 } else if (network->IsConnectingState()) {
892 // Wait until the network is actually connected to notify that the default
893 // network changed.
894 NET_LOG(EVENT) << "Default network is not connected: "
895 << GetLogName(network)
896 << "State: " << network->connection_state();
897 } else {
898 NET_LOG(ERROR) << "Default network in unexpected state: "
899 << GetLogName(network)
900 << "State: " << network->connection_state();
901 default_network_path_.clear();
902 SortNetworkList();
903 NotifyDefaultNetworkChanged(nullptr);
906 std::string desc = "NetworkConnectionStateChanged";
907 if (notify_default)
908 desc = "Default" + desc;
909 NET_LOG(EVENT) << "NOTIFY: " << desc << ": " << GetLogName(network) << ": "
910 << network->connection_state();
911 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
912 NetworkConnectionStateChanged(network));
913 if (notify_default)
914 NotifyDefaultNetworkChanged(network);
917 void NetworkStateHandler::NotifyDefaultNetworkChanged(
918 const NetworkState* default_network) {
919 SCOPED_NET_LOG_IF_SLOW();
920 NET_LOG_EVENT("NOTIFY:DefaultNetworkChanged", GetLogName(default_network));
921 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
922 DefaultNetworkChanged(default_network));
925 void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
926 const NetworkState* network) {
927 SCOPED_NET_LOG_IF_SLOW();
928 NET_LOG_DEBUG("NOTIFY:NetworkPropertiesUpdated", GetLogName(network));
929 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
930 NetworkPropertiesUpdated(network));
933 void NetworkStateHandler::NotifyDevicePropertiesUpdated(
934 const DeviceState* device) {
935 SCOPED_NET_LOG_IF_SLOW();
936 NET_LOG_DEBUG("NOTIFY:DevicePropertiesUpdated", GetLogName(device));
937 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
938 DevicePropertiesUpdated(device));
941 void NetworkStateHandler::NotifyScanCompleted(const DeviceState* device) {
942 SCOPED_NET_LOG_IF_SLOW();
943 NET_LOG_DEBUG("NOTIFY:ScanCompleted", GetLogName(device));
944 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
945 ScanCompleted(device));
948 std::string NetworkStateHandler::GetTechnologyForType(
949 const NetworkTypePattern& type) const {
950 if (type.MatchesType(shill::kTypeEthernet))
951 return shill::kTypeEthernet;
953 if (type.MatchesType(shill::kTypeWifi))
954 return shill::kTypeWifi;
956 if (type.Equals(NetworkTypePattern::Wimax()))
957 return shill::kTypeWimax;
959 // Prefer Wimax over Cellular only if it's available.
960 if (type.MatchesType(shill::kTypeWimax) &&
961 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
962 return shill::kTypeWimax;
965 if (type.MatchesType(shill::kTypeCellular))
966 return shill::kTypeCellular;
968 NOTREACHED();
969 return std::string();
972 ScopedVector<std::string> NetworkStateHandler::GetTechnologiesForType(
973 const NetworkTypePattern& type) const {
974 ScopedVector<std::string> technologies;
975 if (type.MatchesType(shill::kTypeEthernet))
976 technologies.push_back(new std::string(shill::kTypeEthernet));
977 if (type.MatchesType(shill::kTypeWifi))
978 technologies.push_back(new std::string(shill::kTypeWifi));
979 if (type.MatchesType(shill::kTypeWimax))
980 technologies.push_back(new std::string(shill::kTypeWimax));
981 if (type.MatchesType(shill::kTypeCellular))
982 technologies.push_back(new std::string(shill::kTypeCellular));
983 if (type.MatchesType(shill::kTypeBluetooth))
984 technologies.push_back(new std::string(shill::kTypeBluetooth));
985 if (type.MatchesType(shill::kTypeVPN))
986 technologies.push_back(new std::string(shill::kTypeVPN));
988 CHECK_GT(technologies.size(), 0ul);
989 return technologies.Pass();
992 } // namespace chromeos