• 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/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                          &ethernet_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