• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(), &ethernet_services);
626     for (NetworkStateList::const_iterator it = ethernet_services.begin();
627          it != ethernet_services.end(); ++it) {
628       const NetworkState* ethernet_service = *it;
629       if (ethernet_service->update_received() ||
630           ethernet_service->device_path() != device->path()) {
631         continue;
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