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/location.h"
10 #include "base/metrics/histogram.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/values.h"
15 #include "chromeos/network/device_state.h"
16 #include "chromeos/network/favorite_state.h"
17 #include "chromeos/network/managed_state.h"
18 #include "chromeos/network/network_event_log.h"
19 #include "chromeos/network/network_state.h"
20 #include "chromeos/network/network_state_handler_observer.h"
21 #include "chromeos/network/shill_property_handler.h"
22 #include "chromeos/network/shill_property_util.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_FAVORITE:
41 return "Favorite";
42 case ManagedState::MANAGED_TYPE_DEVICE:
43 return "Device";
44 }
45 NOTREACHED();
46 return "";
47 }
48
GetManagedStateLogName(const ManagedState * state)49 std::string GetManagedStateLogName(const ManagedState* state) {
50 if (!state)
51 return "None";
52 return base::StringPrintf("%s (%s)", state->name().c_str(),
53 state->path().c_str());
54 }
55
56 } // namespace
57
58 const char NetworkStateHandler::kDefaultCheckPortalList[] =
59 "ethernet,wifi,cellular";
60
NetworkStateHandler()61 NetworkStateHandler::NetworkStateHandler() {
62 }
63
~NetworkStateHandler()64 NetworkStateHandler::~NetworkStateHandler() {
65 STLDeleteContainerPointers(network_list_.begin(), network_list_.end());
66 STLDeleteContainerPointers(favorite_list_.begin(), favorite_list_.end());
67 STLDeleteContainerPointers(device_list_.begin(), device_list_.end());
68 }
69
InitShillPropertyHandler()70 void NetworkStateHandler::InitShillPropertyHandler() {
71 shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
72 shill_property_handler_->Init();
73 }
74
75 // static
InitializeForTest()76 NetworkStateHandler* NetworkStateHandler::InitializeForTest() {
77 NetworkStateHandler* handler = new NetworkStateHandler();
78 handler->InitShillPropertyHandler();
79 return handler;
80 }
81
AddObserver(NetworkStateHandlerObserver * observer,const tracked_objects::Location & from_here)82 void NetworkStateHandler::AddObserver(
83 NetworkStateHandlerObserver* observer,
84 const tracked_objects::Location& from_here) {
85 observers_.AddObserver(observer);
86 network_event_log::internal::AddEntry(
87 from_here.file_name(), from_here.line_number(),
88 network_event_log::LOG_LEVEL_DEBUG,
89 "NetworkStateHandler::AddObserver", "");
90 }
91
RemoveObserver(NetworkStateHandlerObserver * observer,const tracked_objects::Location & from_here)92 void NetworkStateHandler::RemoveObserver(
93 NetworkStateHandlerObserver* observer,
94 const tracked_objects::Location& from_here) {
95 observers_.RemoveObserver(observer);
96 network_event_log::internal::AddEntry(
97 from_here.file_name(), from_here.line_number(),
98 network_event_log::LOG_LEVEL_DEBUG,
99 "NetworkStateHandler::RemoveObserver", "");
100 }
101
UpdateManagerProperties()102 void NetworkStateHandler::UpdateManagerProperties() {
103 NET_LOG_USER("UpdateManagerProperties", "");
104 shill_property_handler_->UpdateManagerProperties();
105 }
106
GetTechnologyState(const NetworkTypePattern & type) const107 NetworkStateHandler::TechnologyState NetworkStateHandler::GetTechnologyState(
108 const NetworkTypePattern& type) const {
109 std::string technology = GetTechnologyForType(type);
110 TechnologyState state;
111 if (shill_property_handler_->IsTechnologyEnabled(technology))
112 state = TECHNOLOGY_ENABLED;
113 else if (shill_property_handler_->IsTechnologyEnabling(technology))
114 state = TECHNOLOGY_ENABLING;
115 else if (shill_property_handler_->IsTechnologyUninitialized(technology))
116 state = TECHNOLOGY_UNINITIALIZED;
117 else if (shill_property_handler_->IsTechnologyAvailable(technology))
118 state = TECHNOLOGY_AVAILABLE;
119 else
120 state = TECHNOLOGY_UNAVAILABLE;
121 VLOG(2) << "GetTechnologyState: " << type.ToDebugString() << " = " << state;
122 return state;
123 }
124
SetTechnologyEnabled(const NetworkTypePattern & type,bool enabled,const network_handler::ErrorCallback & error_callback)125 void NetworkStateHandler::SetTechnologyEnabled(
126 const NetworkTypePattern& type,
127 bool enabled,
128 const network_handler::ErrorCallback& error_callback) {
129 std::string technology = GetTechnologyForType(type);
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 // Signal Device/Technology state changed.
135 NotifyDeviceListChanged();
136 }
137
GetDeviceState(const std::string & device_path) const138 const DeviceState* NetworkStateHandler::GetDeviceState(
139 const std::string& device_path) const {
140 const DeviceState* device = GetModifiableDeviceState(device_path);
141 if (device && !device->update_received())
142 return NULL;
143 return device;
144 }
145
GetDeviceStateByType(const NetworkTypePattern & type) const146 const DeviceState* NetworkStateHandler::GetDeviceStateByType(
147 const NetworkTypePattern& type) const {
148 for (ManagedStateList::const_iterator iter = device_list_.begin();
149 iter != device_list_.end(); ++iter) {
150 ManagedState* device = *iter;
151 if (!device->update_received())
152 continue;
153 if (device->Matches(type))
154 return device->AsDeviceState();
155 }
156 return NULL;
157 }
158
GetScanningByType(const NetworkTypePattern & type) const159 bool NetworkStateHandler::GetScanningByType(
160 const NetworkTypePattern& type) const {
161 for (ManagedStateList::const_iterator iter = device_list_.begin();
162 iter != device_list_.end(); ++iter) {
163 const DeviceState* device = (*iter)->AsDeviceState();
164 DCHECK(device);
165 if (!device->update_received())
166 continue;
167 if (device->Matches(type) && device->scanning())
168 return true;
169 }
170 return false;
171 }
172
GetNetworkState(const std::string & service_path) const173 const NetworkState* NetworkStateHandler::GetNetworkState(
174 const std::string& service_path) const {
175 const NetworkState* network = GetModifiableNetworkState(service_path);
176 if (network && !network->update_received())
177 return NULL;
178 return network;
179 }
180
DefaultNetwork() const181 const NetworkState* NetworkStateHandler::DefaultNetwork() const {
182 if (network_list_.empty())
183 return NULL;
184 const NetworkState* network = network_list_.front()->AsNetworkState();
185 DCHECK(network);
186 if (!network->update_received() || !network->IsConnectedState())
187 return NULL;
188 return network;
189 }
190
DefaultFavoriteNetwork() const191 const FavoriteState* NetworkStateHandler::DefaultFavoriteNetwork() const {
192 const NetworkState* default_network = DefaultNetwork();
193 if (!default_network)
194 return NULL;
195 const FavoriteState* default_favorite =
196 GetFavoriteState(default_network->path());
197 DCHECK(default_favorite);
198 DCHECK(default_favorite->update_received());
199 return default_favorite;
200 }
201
ConnectedNetworkByType(const NetworkTypePattern & type) const202 const NetworkState* NetworkStateHandler::ConnectedNetworkByType(
203 const NetworkTypePattern& type) const {
204 for (ManagedStateList::const_iterator iter = network_list_.begin();
205 iter != network_list_.end(); ++iter) {
206 const NetworkState* network = (*iter)->AsNetworkState();
207 DCHECK(network);
208 if (!network->update_received())
209 continue;
210 if (!network->IsConnectedState())
211 break; // Connected networks are listed first.
212 if (network->Matches(type))
213 return network;
214 }
215 return NULL;
216 }
217
ConnectingNetworkByType(const NetworkTypePattern & type) const218 const NetworkState* NetworkStateHandler::ConnectingNetworkByType(
219 const NetworkTypePattern& type) const {
220 for (ManagedStateList::const_iterator iter = network_list_.begin();
221 iter != network_list_.end(); ++iter) {
222 const NetworkState* network = (*iter)->AsNetworkState();
223 DCHECK(network);
224 if (!network->update_received() || network->IsConnectedState())
225 continue;
226 if (!network->IsConnectingState())
227 break; // Connected and connecting networks are listed first.
228 if (network->Matches(type))
229 return network;
230 }
231 return NULL;
232 }
233
FirstNetworkByType(const NetworkTypePattern & type) const234 const NetworkState* NetworkStateHandler::FirstNetworkByType(
235 const NetworkTypePattern& type) const {
236 for (ManagedStateList::const_iterator iter = network_list_.begin();
237 iter != network_list_.end(); ++iter) {
238 const NetworkState* network = (*iter)->AsNetworkState();
239 DCHECK(network);
240 if (!network->update_received())
241 continue;
242 if (network->Matches(type))
243 return network;
244 }
245 return NULL;
246 }
247
FormattedHardwareAddressForType(const NetworkTypePattern & type) const248 std::string NetworkStateHandler::FormattedHardwareAddressForType(
249 const NetworkTypePattern& type) const {
250 const DeviceState* device = NULL;
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 device->GetFormattedMacAddress();
259 }
260
GetNetworkList(NetworkStateList * list) const261 void NetworkStateHandler::GetNetworkList(NetworkStateList* list) const {
262 GetNetworkListByType(NetworkTypePattern::Default(), list);
263 }
264
GetNetworkListByType(const NetworkTypePattern & type,NetworkStateList * list) const265 void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type,
266 NetworkStateList* list) const {
267 DCHECK(list);
268 list->clear();
269 for (ManagedStateList::const_iterator iter = network_list_.begin();
270 iter != network_list_.end(); ++iter) {
271 const NetworkState* network = (*iter)->AsNetworkState();
272 DCHECK(network);
273 if (network->update_received() && network->Matches(type))
274 list->push_back(network);
275 }
276 }
277
GetDeviceList(DeviceStateList * list) const278 void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const {
279 GetDeviceListByType(NetworkTypePattern::Default(), list);
280 }
281
GetDeviceListByType(const NetworkTypePattern & type,DeviceStateList * list) const282 void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type,
283 DeviceStateList* list) const {
284 DCHECK(list);
285 list->clear();
286 for (ManagedStateList::const_iterator iter = device_list_.begin();
287 iter != device_list_.end(); ++iter) {
288 const DeviceState* device = (*iter)->AsDeviceState();
289 DCHECK(device);
290 if (device->update_received() && device->Matches(type))
291 list->push_back(device);
292 }
293 }
294
GetFavoriteList(FavoriteStateList * list) const295 void NetworkStateHandler::GetFavoriteList(FavoriteStateList* list) const {
296 GetFavoriteListByType(NetworkTypePattern::Default(), list);
297 }
298
GetFavoriteListByType(const NetworkTypePattern & type,FavoriteStateList * list) const299 void NetworkStateHandler::GetFavoriteListByType(const NetworkTypePattern& type,
300 FavoriteStateList* list) const {
301 DCHECK(list);
302 FavoriteStateList result;
303 list->clear();
304 for (ManagedStateList::const_iterator iter = favorite_list_.begin();
305 iter != favorite_list_.end(); ++iter) {
306 const FavoriteState* favorite = (*iter)->AsFavoriteState();
307 DCHECK(favorite);
308 if (favorite->update_received() && favorite->is_favorite() &&
309 favorite->Matches(type)) {
310 list->push_back(favorite);
311 }
312 }
313 }
314
GetFavoriteState(const std::string & service_path) const315 const FavoriteState* NetworkStateHandler::GetFavoriteState(
316 const std::string& service_path) const {
317 ManagedState* managed =
318 GetModifiableManagedState(&favorite_list_, service_path);
319 if (!managed)
320 return NULL;
321 if (managed && !managed->update_received())
322 return NULL;
323 return managed->AsFavoriteState();
324 }
325
RequestScan() const326 void NetworkStateHandler::RequestScan() const {
327 NET_LOG_USER("RequestScan", "");
328 shill_property_handler_->RequestScan();
329 }
330
WaitForScan(const std::string & type,const base::Closure & callback)331 void NetworkStateHandler::WaitForScan(const std::string& type,
332 const base::Closure& callback) {
333 scan_complete_callbacks_[type].push_back(callback);
334 if (!GetScanningByType(NetworkTypePattern::Primitive(type)))
335 RequestScan();
336 }
337
ConnectToBestWifiNetwork()338 void NetworkStateHandler::ConnectToBestWifiNetwork() {
339 NET_LOG_USER("ConnectToBestWifiNetwork", "");
340 WaitForScan(shill::kTypeWifi,
341 base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices,
342 shill_property_handler_->AsWeakPtr()));
343 }
344
RequestUpdateForNetwork(const std::string & service_path)345 void NetworkStateHandler::RequestUpdateForNetwork(
346 const std::string& service_path) {
347 NetworkState* network = GetModifiableNetworkState(service_path);
348 if (network)
349 network->set_update_requested(true);
350 NET_LOG_EVENT("RequestUpdate", service_path);
351 shill_property_handler_->RequestProperties(
352 ManagedState::MANAGED_TYPE_NETWORK, service_path);
353 }
354
RequestUpdateForAllNetworks()355 void NetworkStateHandler::RequestUpdateForAllNetworks() {
356 NET_LOG_EVENT("RequestUpdateForAllNetworks", "");
357 for (ManagedStateList::iterator iter = network_list_.begin();
358 iter != network_list_.end(); ++iter) {
359 ManagedState* network = *iter;
360 network->set_update_requested(true);
361 shill_property_handler_->RequestProperties(
362 ManagedState::MANAGED_TYPE_NETWORK, network->path());
363 }
364 }
365
SetCheckPortalList(const std::string & check_portal_list)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);
370 }
371
GetEAPForEthernet(const std::string & service_path) const372 const FavoriteState* NetworkStateHandler::GetEAPForEthernet(
373 const std::string& service_path) const {
374 const NetworkState* network = GetNetworkState(service_path);
375 if (!network) {
376 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path);
377 return NULL;
378 }
379 if (network->type() != shill::kTypeEthernet) {
380 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path);
381 return NULL;
382 }
383 if (!network->IsConnectedState())
384 return NULL;
385
386 // The same EAP service is shared for all ethernet services/devices.
387 // However EAP is used/enabled per device and only if the connection was
388 // successfully established.
389 const DeviceState* device = GetDeviceState(network->device_path());
390 if (!device) {
391 NET_LOG_ERROR(
392 "GetEAPForEthernet",
393 base::StringPrintf("Unknown device %s of connected ethernet service %s",
394 network->device_path().c_str(),
395 service_path.c_str()));
396 return NULL;
397 }
398 if (!device->eap_authentication_completed())
399 return NULL;
400
401 FavoriteStateList list;
402 GetFavoriteListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap),
403 &list);
404 if (list.empty()) {
405 NET_LOG_ERROR("GetEAPForEthernet",
406 base::StringPrintf(
407 "Ethernet service %s connected using EAP, but no "
408 "EAP service found.",
409 service_path.c_str()));
410 return NULL;
411 }
412 DCHECK(list.size() == 1);
413 return list.front();
414 }
415
GetNetworkStatePropertiesForTest(base::DictionaryValue * dictionary) const416 void NetworkStateHandler::GetNetworkStatePropertiesForTest(
417 base::DictionaryValue* dictionary) const {
418 for (ManagedStateList::const_iterator iter = network_list_.begin();
419 iter != network_list_.end(); ++iter) {
420 base::DictionaryValue* network_dict = new base::DictionaryValue;
421 (*iter)->AsNetworkState()->GetProperties(network_dict);
422 dictionary->SetWithoutPathExpansion((*iter)->path(), network_dict);
423 }
424 }
425
426 //------------------------------------------------------------------------------
427 // ShillPropertyHandler::Delegate overrides
428
UpdateManagedList(ManagedState::ManagedType type,const base::ListValue & entries)429 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type,
430 const base::ListValue& entries) {
431 ManagedStateList* managed_list = GetManagedList(type);
432 NET_LOG_DEBUG(base::StringPrintf("UpdateManagedList:%d", type),
433 base::StringPrintf("%" PRIuS, entries.GetSize()));
434 // Create a map of existing entries. Assumes all entries in |managed_list|
435 // are unique.
436 std::map<std::string, ManagedState*> managed_map;
437 for (ManagedStateList::iterator iter = managed_list->begin();
438 iter != managed_list->end(); ++iter) {
439 ManagedState* managed = *iter;
440 DCHECK(!ContainsKey(managed_map, managed->path()));
441 managed_map[managed->path()] = managed;
442 }
443 // Clear the list (pointers are temporarily owned by managed_map).
444 managed_list->clear();
445 // Updates managed_list and request updates for new entries.
446 std::set<std::string> list_entries;
447 for (base::ListValue::const_iterator iter = entries.begin();
448 iter != entries.end(); ++iter) {
449 std::string path;
450 (*iter)->GetAsString(&path);
451 if (path.empty() || path == shill::kFlimflamServicePath) {
452 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path);
453 continue;
454 }
455 std::map<std::string, ManagedState*>::iterator found =
456 managed_map.find(path);
457 ManagedState* managed;
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 managed = ManagedState::Create(type, path);
464 managed_list->push_back(managed);
465 } else {
466 managed = found->second;
467 managed_list->push_back(managed);
468 managed_map.erase(found);
469 }
470 list_entries.insert(path);
471 }
472 // Delete any remaining entries in managed_map.
473 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
474 }
475
ProfileListChanged()476 void NetworkStateHandler::ProfileListChanged() {
477 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
478 for (ManagedStateList::iterator iter = network_list_.begin();
479 iter != network_list_.end(); ++iter) {
480 shill_property_handler_->RequestProperties(
481 ManagedState::MANAGED_TYPE_NETWORK, (*iter)->path());
482 }
483 }
484
UpdateManagedStateProperties(ManagedState::ManagedType type,const std::string & path,const base::DictionaryValue & properties)485 void NetworkStateHandler::UpdateManagedStateProperties(
486 ManagedState::ManagedType type,
487 const std::string& path,
488 const base::DictionaryValue& properties) {
489 ManagedStateList* managed_list = GetManagedList(type);
490 ManagedState* managed = GetModifiableManagedState(managed_list, path);
491 if (!managed) {
492 if (type != ManagedState::MANAGED_TYPE_FAVORITE) {
493 // The network has been removed from the list of visible networks.
494 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path);
495 return;
496 }
497 // A Favorite may not have been created yet if it was added later (e.g.
498 // through ConfigureService) since ServiceCompleteList updates are not
499 // emitted. Add and update the state here.
500 managed = new FavoriteState(path);
501 managed_list->push_back(managed);
502 }
503 managed->set_update_received();
504
505 std::string desc = GetManagedStateLogType(managed) + " PropertiesReceived";
506 NET_LOG_DEBUG(desc, GetManagedStateLogName(managed));
507
508 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
509 UpdateNetworkStateProperties(managed->AsNetworkState(), properties);
510 } else {
511 // Device, Favorite
512 for (base::DictionaryValue::Iterator iter(properties);
513 !iter.IsAtEnd(); iter.Advance()) {
514 managed->PropertyChanged(iter.key(), iter.value());
515 }
516 managed->InitialPropertiesReceived(properties);
517 }
518 managed->set_update_requested(false);
519 }
520
UpdateNetworkStateProperties(NetworkState * network,const base::DictionaryValue & properties)521 void NetworkStateHandler::UpdateNetworkStateProperties(
522 NetworkState* network,
523 const base::DictionaryValue& properties) {
524 DCHECK(network);
525 bool network_property_updated = false;
526 std::string prev_connection_state = network->connection_state();
527 for (base::DictionaryValue::Iterator iter(properties);
528 !iter.IsAtEnd(); iter.Advance()) {
529 if (network->PropertyChanged(iter.key(), iter.value()))
530 network_property_updated = true;
531 }
532 network_property_updated |= network->InitialPropertiesReceived(properties);
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 OnNetworkConnectionStateChanged(network);
538 NetworkPropertiesUpdated(network);
539 }
540 }
541
UpdateNetworkServiceProperty(const std::string & service_path,const std::string & key,const base::Value & value)542 void NetworkStateHandler::UpdateNetworkServiceProperty(
543 const std::string& service_path,
544 const std::string& key,
545 const base::Value& value) {
546 // Update any associated FavoriteState.
547 ManagedState* favorite =
548 GetModifiableManagedState(&favorite_list_, service_path);
549 bool changed = false;
550 if (favorite)
551 changed |= favorite->PropertyChanged(key, value);
552
553 // Update the NetworkState.
554 NetworkState* network = GetModifiableNetworkState(service_path);
555 if (!network)
556 return;
557 std::string prev_connection_state = network->connection_state();
558 std::string prev_profile_path = network->profile_path();
559 changed |= network->PropertyChanged(key, value);
560 if (!changed)
561 return;
562
563 if (key == shill::kStateProperty) {
564 if (ConnectionStateChanged(network, prev_connection_state)) {
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);
569 }
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 // Trigger a default network update for interesting changes only.
581 if (network->path() == default_network_path_)
582 OnDefaultNetworkChanged();
583 // Log interesting event.
584 std::string detail = network->name() + "." + key;
585 detail += " = " + network_event_log::ValueAsString(value);
586 network_event_log::LogLevel log_level;
587 if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) {
588 log_level = network_event_log::LOG_LEVEL_ERROR;
589 } else {
590 log_level = network_event_log::LOG_LEVEL_EVENT;
591 }
592 NET_LOG_LEVEL(log_level, "NetworkPropertyUpdated", detail);
593 }
594 }
595
596 // All property updates signal 'NetworkPropertiesUpdated'.
597 NetworkPropertiesUpdated(network);
598
599 // If added to a Profile, request a full update so that a FavoriteState
600 // gets created.
601 if (prev_profile_path.empty() && !network->profile_path().empty())
602 RequestUpdateForNetwork(service_path);
603 }
604
UpdateDeviceProperty(const std::string & device_path,const std::string & key,const base::Value & value)605 void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path,
606 const std::string& key,
607 const base::Value& value) {
608 DeviceState* device = GetModifiableDeviceState(device_path);
609 if (!device)
610 return;
611 if (!device->PropertyChanged(key, value))
612 return;
613
614 std::string detail = device->name() + "." + key;
615 detail += " = " + network_event_log::ValueAsString(value);
616 NET_LOG_EVENT("DevicePropertyUpdated", detail);
617
618 NotifyDeviceListChanged();
619
620 if (key == shill::kScanningProperty && device->scanning() == false)
621 ScanCompleted(device->type());
622 if (key == shill::kEapAuthenticationCompletedProperty) {
623 // Notify a change for each Ethernet service using this device.
624 NetworkStateList ethernet_services;
625 GetNetworkListByType(NetworkTypePattern::Ethernet(), ðernet_services);
626 for (NetworkStateList::const_iterator it = ethernet_services.begin();
627 it != ethernet_services.end(); ++it) {
628 const NetworkState* ethernet_service = *it;
629 if (ethernet_service->update_received() ||
630 ethernet_service->device_path() != device->path()) {
631 continue;
632 }
633 RequestUpdateForNetwork(ethernet_service->path());
634 }
635 }
636 }
637
CheckPortalListChanged(const std::string & check_portal_list)638 void NetworkStateHandler::CheckPortalListChanged(
639 const std::string& check_portal_list) {
640 check_portal_list_ = check_portal_list;
641 }
642
TechnologyListChanged()643 void NetworkStateHandler::TechnologyListChanged() {
644 // Eventually we would like to replace Technology state with Device state.
645 // For now, treat technology state changes as device list changes.
646 NotifyDeviceListChanged();
647 }
648
ManagedStateListChanged(ManagedState::ManagedType type)649 void NetworkStateHandler::ManagedStateListChanged(
650 ManagedState::ManagedType type) {
651 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
652 // Notify observers that the list of networks has changed.
653 NET_LOG_EVENT("NetworkListChanged",
654 base::StringPrintf("Size:%" PRIuS, network_list_.size()));
655 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
656 NetworkListChanged());
657 // The list order may have changed, so check if the default network changed.
658 if (CheckDefaultNetworkChanged())
659 OnDefaultNetworkChanged();
660 // Update UMA stats.
661 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", network_list_.size());
662 } else if (type == ManagedState::MANAGED_TYPE_FAVORITE) {
663 NET_LOG_DEBUG("FavoriteListChanged",
664 base::StringPrintf("Size:%" PRIuS, favorite_list_.size()));
665 // The FavoriteState list only changes when the NetworkState list changes,
666 // so no need to signal observers here again.
667
668 // Update UMA stats.
669 size_t shared = 0, unshared = 0;
670 for (ManagedStateList::iterator iter = favorite_list_.begin();
671 iter != favorite_list_.end(); ++iter) {
672 FavoriteState* favorite = (*iter)->AsFavoriteState();
673 if (!favorite->is_favorite())
674 continue;
675 if (favorite->IsPrivate())
676 ++unshared;
677 else
678 ++shared;
679 }
680 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared);
681 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared);
682 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
683 NotifyDeviceListChanged();
684 } else {
685 NOTREACHED();
686 }
687 }
688
689 //------------------------------------------------------------------------------
690 // Private methods
691
NotifyDeviceListChanged()692 void NetworkStateHandler::NotifyDeviceListChanged() {
693 NET_LOG_DEBUG("NotifyDeviceListChanged",
694 base::StringPrintf("Size:%" PRIuS, device_list_.size()));
695 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
696 DeviceListChanged());
697 }
698
GetModifiableDeviceState(const std::string & device_path) const699 DeviceState* NetworkStateHandler::GetModifiableDeviceState(
700 const std::string& device_path) const {
701 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
702 if (!managed)
703 return NULL;
704 return managed->AsDeviceState();
705 }
706
GetModifiableNetworkState(const std::string & service_path) const707 NetworkState* NetworkStateHandler::GetModifiableNetworkState(
708 const std::string& service_path) const {
709 ManagedState* managed =
710 GetModifiableManagedState(&network_list_, service_path);
711 if (!managed)
712 return NULL;
713 return managed->AsNetworkState();
714 }
715
GetModifiableManagedState(const ManagedStateList * managed_list,const std::string & path) const716 ManagedState* NetworkStateHandler::GetModifiableManagedState(
717 const ManagedStateList* managed_list,
718 const std::string& path) const {
719 for (ManagedStateList::const_iterator iter = managed_list->begin();
720 iter != managed_list->end(); ++iter) {
721 ManagedState* managed = *iter;
722 if (managed->path() == path)
723 return managed;
724 }
725 return NULL;
726 }
727
GetManagedList(ManagedState::ManagedType type)728 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
729 ManagedState::ManagedType type) {
730 switch (type) {
731 case ManagedState::MANAGED_TYPE_NETWORK:
732 return &network_list_;
733 case ManagedState::MANAGED_TYPE_FAVORITE:
734 return &favorite_list_;
735 case ManagedState::MANAGED_TYPE_DEVICE:
736 return &device_list_;
737 }
738 NOTREACHED();
739 return NULL;
740 }
741
OnNetworkConnectionStateChanged(NetworkState * network)742 void NetworkStateHandler::OnNetworkConnectionStateChanged(
743 NetworkState* network) {
744 DCHECK(network);
745 NET_LOG_EVENT("NetworkConnectionStateChanged", base::StringPrintf(
746 "%s:%s", GetManagedStateLogName(network).c_str(),
747 network->connection_state().c_str()));
748 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
749 NetworkConnectionStateChanged(network));
750 if (CheckDefaultNetworkChanged() || network->path() == default_network_path_)
751 OnDefaultNetworkChanged();
752 }
753
CheckDefaultNetworkChanged()754 bool NetworkStateHandler::CheckDefaultNetworkChanged() {
755 std::string new_default_network_path;
756 const NetworkState* new_default_network = DefaultNetwork();
757 if (new_default_network)
758 new_default_network_path = new_default_network->path();
759 if (new_default_network_path == default_network_path_)
760 return false;
761 default_network_path_ = new_default_network_path;
762 return true;
763 }
764
OnDefaultNetworkChanged()765 void NetworkStateHandler::OnDefaultNetworkChanged() {
766 const NetworkState* default_network = DefaultNetwork();
767 NET_LOG_EVENT("DefaultNetworkChanged",
768 GetManagedStateLogName(default_network));
769 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
770 DefaultNetworkChanged(default_network));
771 }
772
NetworkPropertiesUpdated(const NetworkState * network)773 void NetworkStateHandler::NetworkPropertiesUpdated(
774 const NetworkState* network) {
775 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
776 NetworkPropertiesUpdated(network));
777 }
778
ScanCompleted(const std::string & type)779 void NetworkStateHandler::ScanCompleted(const std::string& type) {
780 size_t num_callbacks = scan_complete_callbacks_.count(type);
781 NET_LOG_EVENT("ScanCompleted",
782 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks));
783 if (num_callbacks == 0)
784 return;
785 ScanCallbackList& callback_list = scan_complete_callbacks_[type];
786 for (ScanCallbackList::iterator iter = callback_list.begin();
787 iter != callback_list.end(); ++iter) {
788 (*iter).Run();
789 }
790 scan_complete_callbacks_.erase(type);
791 }
792
GetTechnologyForType(const NetworkTypePattern & type) const793 std::string NetworkStateHandler::GetTechnologyForType(
794 const NetworkTypePattern& type) const {
795 if (type.MatchesType(shill::kTypeEthernet))
796 return shill::kTypeEthernet;
797
798 if (type.MatchesType(shill::kTypeWifi))
799 return shill::kTypeWifi;
800
801 if (type.Equals(NetworkTypePattern::Wimax()))
802 return shill::kTypeWimax;
803
804 // Prefer Wimax over Cellular only if it's available.
805 if (type.MatchesType(shill::kTypeWimax) &&
806 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
807 return shill::kTypeWimax;
808 }
809
810 if (type.MatchesType(shill::kTypeCellular))
811 return shill::kTypeCellular;
812
813 NOTREACHED();
814 return std::string();
815 }
816
817 } // namespace chromeos
818