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.
4
5 #include "chromeos/network/network_state_handler.h"
6
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"
24
25 namespace chromeos {
26
27 namespace {
28
ConnectionStateChanged(NetworkState * network,const std::string & prev_connection_state)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());
34 }
35
GetManagedStateLogType(const ManagedState * state)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";
42 }
43 NOTREACHED();
44 return "";
45 }
46
GetLogName(const ManagedState * state)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());
52 }
53
54 } // namespace
55
56 const char NetworkStateHandler::kDefaultCheckPortalList[] =
57 "ethernet,wifi,cellular";
58
NetworkStateHandler()59 NetworkStateHandler::NetworkStateHandler()
60 : network_list_sorted_(false) {
61 }
62
~NetworkStateHandler()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());
67 }
68
InitShillPropertyHandler()69 void NetworkStateHandler::InitShillPropertyHandler() {
70 shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
71 shill_property_handler_->Init();
72 }
73
74 // static
InitializeForTest()75 NetworkStateHandler* NetworkStateHandler::InitializeForTest() {
76 NetworkStateHandler* handler = new NetworkStateHandler();
77 handler->InitShillPropertyHandler();
78 return handler;
79 }
80
AddObserver(NetworkStateHandlerObserver * observer,const tracked_objects::Location & from_here)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", "");
89 }
90
RemoveObserver(NetworkStateHandlerObserver * observer,const tracked_objects::Location & from_here)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", "");
99 }
100
GetTechnologyState(const NetworkTypePattern & type) const101 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;
117 }
118
SetTechnologyEnabled(const NetworkTypePattern & type,bool enabled,const network_handler::ErrorCallback & error_callback)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);
134 }
135 // Signal Device/Technology state changed.
136 NotifyDeviceListChanged();
137 }
138
GetDeviceState(const std::string & device_path) const139 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;
145 }
146
GetDeviceStateByType(const NetworkTypePattern & type) const147 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();
156 }
157 return NULL;
158 }
159
GetScanningByType(const NetworkTypePattern & type) const160 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;
170 }
171 return false;
172 }
173
GetNetworkState(const std::string & service_path) const174 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;
180 }
181
DefaultNetwork() const182 const NetworkState* NetworkStateHandler::DefaultNetwork() const {
183 if (default_network_path_.empty())
184 return NULL;
185 return GetNetworkState(default_network_path_);
186 }
187
ConnectedNetworkByType(const NetworkTypePattern & type) const188 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;
201 }
202 return NULL;
203 }
204
ConnectingNetworkByType(const NetworkTypePattern & type) const205 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;
218 }
219 return NULL;
220 }
221
FirstNetworkByType(const NetworkTypePattern & type)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;
236 }
237 return NULL;
238 }
239
FormattedHardwareAddressForType(const NetworkTypePattern & type) const240 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());
251 }
252
GetVisibleNetworkListByType(const NetworkTypePattern & type,NetworkStateList * list)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);
261 }
262
GetVisibleNetworkList(NetworkStateList * list)263 void NetworkStateHandler::GetVisibleNetworkList(NetworkStateList* list) {
264 GetVisibleNetworkListByType(NetworkTypePattern::Default(), list);
265 }
266
GetNetworkListByType(const NetworkTypePattern & type,bool configured_only,bool visible_only,int limit,NetworkStateList * 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;
291 }
292 }
293
GetNetworkStateFromServicePath(const std::string & service_path,bool configured_only) const294 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;
306 }
307 return network;
308 }
309
GetNetworkStateFromGuid(const std::string & guid) const310 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;
318 }
319 return NULL;
320 }
321
GetDeviceList(DeviceStateList * list) const322 void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const {
323 GetDeviceListByType(NetworkTypePattern::Default(), list);
324 }
325
GetDeviceListByType(const NetworkTypePattern & type,DeviceStateList * list) const326 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);
336 }
337 }
338
RequestScan() const339 void NetworkStateHandler::RequestScan() const {
340 NET_LOG_USER("RequestScan", "");
341 shill_property_handler_->RequestScan();
342 }
343
WaitForScan(const std::string & type,const base::Closure & callback)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();
349 }
350
ConnectToBestWifiNetwork()351 void NetworkStateHandler::ConnectToBestWifiNetwork() {
352 NET_LOG_USER("ConnectToBestWifiNetwork", "");
353 WaitForScan(shill::kTypeWifi,
354 base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices,
355 shill_property_handler_->AsWeakPtr()));
356 }
357
RequestUpdateForNetwork(const std::string & service_path)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);
366 }
367
ClearLastErrorForNetwork(const std::string & 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();
373 }
374
SetCheckPortalList(const std::string & check_portal_list)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);
379 }
380
GetEAPForEthernet(const std::string & service_path)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;
387 }
388 if (network->type() != shill::kTypeEthernet) {
389 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path);
390 return NULL;
391 }
392 if (!network->IsConnectedState())
393 return NULL;
394
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;
406 }
407 if (!device->eap_authentication_completed())
408 return NULL;
409
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;
423 }
424 return list.front();
425 }
426
427 //------------------------------------------------------------------------------
428 // ShillPropertyHandler::Delegate overrides
429
UpdateManagedList(ManagedState::ManagedType type,const base::ListValue & entries)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;
444 }
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;
456 }
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;
462 }
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);
468 }
469 list_entries.insert(path);
470 }
471 // Delete any remaining entries in managed_map.
472 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
473 }
474
ProfileListChanged()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());
483 }
484 }
485
UpdateManagedStateProperties(ManagedState::ManagedType type,const std::string & path,const base::DictionaryValue & properties)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;
496 }
497 managed->set_update_received();
498
499 std::string desc = GetManagedStateLogType(managed) + " Properties Received";
500 NET_LOG_DEBUG(desc, GetLogName(managed));
501
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());
509 }
510 managed->InitialPropertiesReceived(properties);
511 }
512 managed->set_update_requested(false);
513 }
514
UpdateNetworkStateProperties(NetworkState * network,const base::DictionaryValue & properties)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;
525 }
526 network_property_updated |= network->InitialPropertiesReceived(properties);
527 UpdateGuid(network);
528 network_list_sorted_ = false;
529
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);
537 }
538 }
539
UpdateNetworkServiceProperty(const std::string & service_path,const std::string & key,const base::Value & value)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;
553
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);
561 }
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;
577 }
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;
586 }
587 NET_LOG_LEVEL(log_level, log_event, detail);
588 }
589 }
590
591 // All property updates signal 'NetworkPropertiesUpdated'.
592 NotifyNetworkPropertiesUpdated(network);
593
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);
598 }
599
UpdateDeviceProperty(const std::string & device_path,const std::string & key,const base::Value & value)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;
608
609 std::string detail = device->name() + "." + key;
610 detail += " = " + network_event_log::ValueAsString(value);
611 NET_LOG_EVENT("DevicePropertyUpdated", detail);
612
613 NotifyDeviceListChanged();
614
615 if (key == shill::kScanningProperty && device->scanning() == false)
616 ScanCompleted(device->type());
617 if (key == shill::kEapAuthenticationCompletedProperty) {
618 // Notify a change for each Ethernet service using this device.
619 NetworkStateList ethernet_services;
620 GetNetworkListByType(NetworkTypePattern::Ethernet(),
621 false /* configured_only */,
622 false /* visible_only */,
623 0 /* no limit */,
624 ðernet_services);
625 for (NetworkStateList::const_iterator it = ethernet_services.begin();
626 it != ethernet_services.end(); ++it) {
627 const NetworkState* ethernet_service = *it;
628 if (ethernet_service->update_received() ||
629 ethernet_service->device_path() != device->path()) {
630 continue;
631 }
632 RequestUpdateForNetwork(ethernet_service->path());
633 }
634 }
635 }
636
UpdateIPConfigProperties(ManagedState::ManagedType type,const std::string & path,const std::string & ip_config_path,const base::DictionaryValue & properties)637 void NetworkStateHandler::UpdateIPConfigProperties(
638 ManagedState::ManagedType type,
639 const std::string& path,
640 const std::string& ip_config_path,
641 const base::DictionaryValue& properties) {
642 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
643 NetworkState* network = GetModifiableNetworkState(path);
644 if (!network)
645 return;
646 network->IPConfigPropertiesChanged(properties);
647 if (network->path() == default_network_path_)
648 NotifyDefaultNetworkChanged(network);
649 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
650 DeviceState* device = GetModifiableDeviceState(path);
651 if (!device)
652 return;
653 device->IPConfigPropertiesChanged(ip_config_path, properties);
654 if (!default_network_path_.empty()) {
655 const NetworkState* default_network =
656 GetNetworkState(default_network_path_);
657 if (default_network && default_network->device_path() == path)
658 NotifyDefaultNetworkChanged(default_network);
659 }
660 }
661 }
662
CheckPortalListChanged(const std::string & check_portal_list)663 void NetworkStateHandler::CheckPortalListChanged(
664 const std::string& check_portal_list) {
665 check_portal_list_ = check_portal_list;
666 }
667
TechnologyListChanged()668 void NetworkStateHandler::TechnologyListChanged() {
669 // Eventually we would like to replace Technology state with Device state.
670 // For now, treat technology state changes as device list changes.
671 NotifyDeviceListChanged();
672 }
673
ManagedStateListChanged(ManagedState::ManagedType type)674 void NetworkStateHandler::ManagedStateListChanged(
675 ManagedState::ManagedType type) {
676 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
677 SortNetworkList();
678 UpdateNetworkStats();
679 // Notify observers that the list of networks has changed.
680 NET_LOG_EVENT("NOTIFY:NetworkListChanged",
681 base::StringPrintf("Size:%" PRIuS, network_list_.size()));
682 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
683 NetworkListChanged());
684 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
685 std::string devices;
686 for (ManagedStateList::const_iterator iter = device_list_.begin();
687 iter != device_list_.end(); ++iter) {
688 if (iter != device_list_.begin())
689 devices += ", ";
690 devices += (*iter)->name();
691 }
692 NET_LOG_EVENT("DeviceList", devices);
693 NotifyDeviceListChanged();
694 } else {
695 NOTREACHED();
696 }
697 }
698
SortNetworkList()699 void NetworkStateHandler::SortNetworkList() {
700 // Note: usually active networks will precede inactive networks, however
701 // this may briefly be untrue during state transitions (e.g. a network may
702 // transition to idle before the list is updated).
703 ManagedStateList active, non_wifi_visible, wifi_visible, hidden, new_networks;
704 for (ManagedStateList::iterator iter = network_list_.begin();
705 iter != network_list_.end(); ++iter) {
706 NetworkState* network = (*iter)->AsNetworkState();
707 if (!network->update_received()) {
708 new_networks.push_back(network);
709 continue;
710 }
711 if (network->IsConnectedState() || network->IsConnectingState()) {
712 active.push_back(network);
713 continue;
714 }
715 if (network->visible()) {
716 if (NetworkTypePattern::WiFi().MatchesType(network->type()))
717 wifi_visible.push_back(network);
718 else
719 non_wifi_visible.push_back(network);
720 } else {
721 hidden.push_back(network);
722 }
723 }
724 network_list_.clear();
725 network_list_.insert(network_list_.end(), active.begin(), active.end());
726 network_list_.insert(
727 network_list_.end(), non_wifi_visible.begin(), non_wifi_visible.end());
728 network_list_.insert(
729 network_list_.end(), wifi_visible.begin(), wifi_visible.end());
730 network_list_.insert(network_list_.end(), hidden.begin(), hidden.end());
731 network_list_.insert(
732 network_list_.end(), new_networks.begin(), new_networks.end());
733 network_list_sorted_ = true;
734 }
735
UpdateNetworkStats()736 void NetworkStateHandler::UpdateNetworkStats() {
737 size_t shared = 0, unshared = 0, visible = 0;
738 for (ManagedStateList::iterator iter = network_list_.begin();
739 iter != network_list_.end(); ++iter) {
740 NetworkState* network = (*iter)->AsNetworkState();
741 if (network->visible())
742 ++visible;
743 if (network->IsInProfile()) {
744 if (network->IsPrivate())
745 ++unshared;
746 else
747 ++shared;
748 }
749 }
750 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", visible);
751 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared);
752 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared);
753 }
754
DefaultNetworkServiceChanged(const std::string & service_path)755 void NetworkStateHandler::DefaultNetworkServiceChanged(
756 const std::string& service_path) {
757 // Shill uses '/' for empty service path values; check explicitly for that.
758 const char* kEmptyServicePath = "/";
759 std::string new_service_path =
760 (service_path != kEmptyServicePath) ? service_path : "";
761 if (new_service_path == default_network_path_)
762 return;
763
764 default_network_path_ = service_path;
765 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_);
766 const NetworkState* network = NULL;
767 if (!default_network_path_.empty()) {
768 network = GetNetworkState(default_network_path_);
769 if (!network) {
770 // If NetworkState is not available yet, do not notify observers here,
771 // they will be notified when the state is received.
772 NET_LOG_DEBUG("Default NetworkState not available",
773 default_network_path_);
774 return;
775 }
776 }
777 if (network && !network->IsConnectedState()) {
778 NET_LOG_ERROR(
779 "DefaultNetwork is not connected: " + network->connection_state(),
780 network->path());
781 }
782 NotifyDefaultNetworkChanged(network);
783 }
784
785 //------------------------------------------------------------------------------
786 // Private methods
787
UpdateGuid(NetworkState * network)788 void NetworkStateHandler::UpdateGuid(NetworkState* network) {
789 std::string specifier = network->GetSpecifier();
790 DCHECK(!specifier.empty());
791 if (!network->guid().empty()) {
792 // If the network is saved in a profile, remove the entry from the map.
793 // Otherwise ensure that the entry matches the specified GUID. (e.g. in
794 // case a visible network with a specified guid gets configured with a
795 // new guid).
796 if (network->IsInProfile())
797 specifier_guid_map_.erase(specifier);
798 else
799 specifier_guid_map_[specifier] = network->guid();
800 return;
801 }
802 // Ensure that the NetworkState has a valid GUID.
803 std::string guid;
804 SpecifierGuidMap::iterator iter = specifier_guid_map_.find(specifier);
805 if (iter != specifier_guid_map_.end()) {
806 guid = iter->second;
807 } else {
808 guid = base::GenerateGUID();
809 specifier_guid_map_[specifier] = guid;
810 }
811 network->SetGuid(guid);
812 }
813
NotifyDeviceListChanged()814 void NetworkStateHandler::NotifyDeviceListChanged() {
815 NET_LOG_DEBUG("NOTIFY:DeviceListChanged",
816 base::StringPrintf("Size:%" PRIuS, device_list_.size()));
817 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
818 DeviceListChanged());
819 }
820
GetModifiableDeviceState(const std::string & device_path) const821 DeviceState* NetworkStateHandler::GetModifiableDeviceState(
822 const std::string& device_path) const {
823 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
824 if (!managed)
825 return NULL;
826 return managed->AsDeviceState();
827 }
828
GetModifiableNetworkState(const std::string & service_path) const829 NetworkState* NetworkStateHandler::GetModifiableNetworkState(
830 const std::string& service_path) const {
831 ManagedState* managed =
832 GetModifiableManagedState(&network_list_, service_path);
833 if (!managed)
834 return NULL;
835 return managed->AsNetworkState();
836 }
837
GetModifiableManagedState(const ManagedStateList * managed_list,const std::string & path) const838 ManagedState* NetworkStateHandler::GetModifiableManagedState(
839 const ManagedStateList* managed_list,
840 const std::string& path) const {
841 for (ManagedStateList::const_iterator iter = managed_list->begin();
842 iter != managed_list->end(); ++iter) {
843 ManagedState* managed = *iter;
844 if (managed->path() == path)
845 return managed;
846 }
847 return NULL;
848 }
849
GetManagedList(ManagedState::ManagedType type)850 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
851 ManagedState::ManagedType type) {
852 switch (type) {
853 case ManagedState::MANAGED_TYPE_NETWORK:
854 return &network_list_;
855 case ManagedState::MANAGED_TYPE_DEVICE:
856 return &device_list_;
857 }
858 NOTREACHED();
859 return NULL;
860 }
861
OnNetworkConnectionStateChanged(NetworkState * network)862 void NetworkStateHandler::OnNetworkConnectionStateChanged(
863 NetworkState* network) {
864 DCHECK(network);
865 std::string event = "NetworkConnectionStateChanged";
866 if (network->path() == default_network_path_) {
867 event = "Default" + event;
868 if (!network->IsConnectedState()) {
869 NET_LOG_EVENT(
870 "DefaultNetwork is not connected: " + network->connection_state(),
871 network->path());
872 default_network_path_.clear();
873 SortNetworkList();
874 NotifyDefaultNetworkChanged(NULL);
875 }
876 }
877 NET_LOG_EVENT("NOTIFY:" + event + ": " + network->connection_state(),
878 GetLogName(network));
879 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
880 NetworkConnectionStateChanged(network));
881 if (network->path() == default_network_path_)
882 NotifyDefaultNetworkChanged(network);
883 }
884
NotifyDefaultNetworkChanged(const NetworkState * default_network)885 void NetworkStateHandler::NotifyDefaultNetworkChanged(
886 const NetworkState* default_network) {
887 NET_LOG_EVENT("NOTIFY:DefaultNetworkChanged", GetLogName(default_network));
888 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
889 DefaultNetworkChanged(default_network));
890 }
891
NotifyNetworkPropertiesUpdated(const NetworkState * network)892 void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
893 const NetworkState* network) {
894 NET_LOG_DEBUG("NOTIFY:NetworkPropertiesUpdated", GetLogName(network));
895 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
896 NetworkPropertiesUpdated(network));
897 }
898
ScanCompleted(const std::string & type)899 void NetworkStateHandler::ScanCompleted(const std::string& type) {
900 size_t num_callbacks = scan_complete_callbacks_.count(type);
901 NET_LOG_EVENT("ScanCompleted",
902 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks));
903 if (num_callbacks == 0)
904 return;
905 ScanCallbackList& callback_list = scan_complete_callbacks_[type];
906 for (ScanCallbackList::iterator iter = callback_list.begin();
907 iter != callback_list.end(); ++iter) {
908 (*iter).Run();
909 }
910 scan_complete_callbacks_.erase(type);
911 }
912
GetTechnologyForType(const NetworkTypePattern & type) const913 std::string NetworkStateHandler::GetTechnologyForType(
914 const NetworkTypePattern& type) const {
915 if (type.MatchesType(shill::kTypeEthernet))
916 return shill::kTypeEthernet;
917
918 if (type.MatchesType(shill::kTypeWifi))
919 return shill::kTypeWifi;
920
921 if (type.Equals(NetworkTypePattern::Wimax()))
922 return shill::kTypeWimax;
923
924 // Prefer Wimax over Cellular only if it's available.
925 if (type.MatchesType(shill::kTypeWimax) &&
926 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
927 return shill::kTypeWimax;
928 }
929
930 if (type.MatchesType(shill::kTypeCellular))
931 return shill::kTypeCellular;
932
933 NOTREACHED();
934 return std::string();
935 }
936
GetTechnologiesForType(const NetworkTypePattern & type) const937 ScopedVector<std::string> NetworkStateHandler::GetTechnologiesForType(
938 const NetworkTypePattern& type) const {
939 ScopedVector<std::string> technologies;
940 if (type.MatchesType(shill::kTypeEthernet))
941 technologies.push_back(new std::string(shill::kTypeEthernet));
942 if (type.MatchesType(shill::kTypeWifi))
943 technologies.push_back(new std::string(shill::kTypeWifi));
944 if (type.MatchesType(shill::kTypeWimax))
945 technologies.push_back(new std::string(shill::kTypeWimax));
946 if (type.MatchesType(shill::kTypeCellular))
947 technologies.push_back(new std::string(shill::kTypeCellular));
948 if (type.MatchesType(shill::kTypeBluetooth))
949 technologies.push_back(new std::string(shill::kTypeBluetooth));
950 if (type.MatchesType(shill::kTypeVPN))
951 technologies.push_back(new std::string(shill::kTypeVPN));
952
953 CHECK_GT(technologies.size(), 0ul);
954 return technologies.Pass();
955 }
956
957 } // namespace chromeos
958