a78b6eebdaaa0044a1bbf463d11933531cc54307
[platform/framework/web/crosswalk.git] / src / chromeos / network / network_state_handler.cc
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
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
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
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
59 NetworkStateHandler::NetworkStateHandler()
60     : network_list_sorted_(false) {
61 }
62
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
69 void NetworkStateHandler::InitShillPropertyHandler() {
70   shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
71   shill_property_handler_->Init();
72 }
73
74 // static
75 NetworkStateHandler* NetworkStateHandler::InitializeForTest() {
76   NetworkStateHandler* handler = new NetworkStateHandler();
77   handler->InitShillPropertyHandler();
78   return handler;
79 }
80
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
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
101 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
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
139 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
147 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
160 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
174 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
182 const NetworkState* NetworkStateHandler::DefaultNetwork() const {
183   if (default_network_path_.empty())
184     return NULL;
185   return GetNetworkState(default_network_path_);
186 }
187
188 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
205 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
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
240 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
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
263 void NetworkStateHandler::GetVisibleNetworkList(NetworkStateList* list) {
264   GetVisibleNetworkListByType(NetworkTypePattern::Default(), list);
265 }
266
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
294 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
310 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
322 void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const {
323   GetDeviceListByType(NetworkTypePattern::Default(), list);
324 }
325
326 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
339 void NetworkStateHandler::RequestScan() const {
340   NET_LOG_USER("RequestScan", "");
341   shill_property_handler_->RequestScan();
342 }
343
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
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
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
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
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
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
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
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
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
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
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
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   NotifyDevicePropertiesUpdated(device);
615
616   if (key == shill::kScanningProperty && device->scanning() == false)
617     ScanCompleted(device->type());
618   if (key == shill::kEapAuthenticationCompletedProperty) {
619     // Notify a change for each Ethernet service using this device.
620     NetworkStateList ethernet_services;
621     GetNetworkListByType(NetworkTypePattern::Ethernet(),
622                          false /* configured_only */,
623                          false /* visible_only */,
624                          0 /* no limit */,
625                          &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
638 void NetworkStateHandler::UpdateIPConfigProperties(
639     ManagedState::ManagedType type,
640     const std::string& path,
641     const std::string& ip_config_path,
642     const base::DictionaryValue& properties)  {
643   if (type == ManagedState::MANAGED_TYPE_NETWORK) {
644     NetworkState* network = GetModifiableNetworkState(path);
645     if (!network)
646       return;
647     network->IPConfigPropertiesChanged(properties);
648     NotifyNetworkPropertiesUpdated(network);
649     if (network->path() == default_network_path_)
650       NotifyDefaultNetworkChanged(network);
651   } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
652     DeviceState* device = GetModifiableDeviceState(path);
653     if (!device)
654       return;
655     device->IPConfigPropertiesChanged(ip_config_path, properties);
656     NotifyDevicePropertiesUpdated(device);
657     if (!default_network_path_.empty()) {
658       const NetworkState* default_network =
659           GetNetworkState(default_network_path_);
660       if (default_network && default_network->device_path() == path)
661         NotifyDefaultNetworkChanged(default_network);
662     }
663   }
664 }
665
666 void NetworkStateHandler::CheckPortalListChanged(
667     const std::string& check_portal_list) {
668   check_portal_list_ = check_portal_list;
669 }
670
671 void NetworkStateHandler::TechnologyListChanged() {
672   // Eventually we would like to replace Technology state with Device state.
673   // For now, treat technology state changes as device list changes.
674   NotifyDeviceListChanged();
675 }
676
677 void NetworkStateHandler::ManagedStateListChanged(
678     ManagedState::ManagedType type) {
679   if (type == ManagedState::MANAGED_TYPE_NETWORK) {
680     SortNetworkList();
681     UpdateNetworkStats();
682     // Notify observers that the list of networks has changed.
683     NET_LOG_EVENT("NOTIFY:NetworkListChanged",
684                   base::StringPrintf("Size:%" PRIuS, network_list_.size()));
685     FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
686                       NetworkListChanged());
687   } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
688     std::string devices;
689     for (ManagedStateList::const_iterator iter = device_list_.begin();
690          iter != device_list_.end(); ++iter) {
691       if (iter != device_list_.begin())
692         devices += ", ";
693       devices += (*iter)->name();
694     }
695     NET_LOG_EVENT("DeviceList", devices);
696     NotifyDeviceListChanged();
697   } else {
698     NOTREACHED();
699   }
700 }
701
702 void NetworkStateHandler::SortNetworkList() {
703   // Note: usually active networks will precede inactive networks, however
704   // this may briefly be untrue during state transitions (e.g. a network may
705   // transition to idle before the list is updated).
706   ManagedStateList active, non_wifi_visible, wifi_visible, hidden, new_networks;
707   for (ManagedStateList::iterator iter = network_list_.begin();
708        iter != network_list_.end(); ++iter) {
709     NetworkState* network = (*iter)->AsNetworkState();
710     if (!network->update_received()) {
711       new_networks.push_back(network);
712       continue;
713     }
714     if (network->IsConnectedState() || network->IsConnectingState()) {
715       active.push_back(network);
716       continue;
717     }
718     if (network->visible()) {
719       if (NetworkTypePattern::WiFi().MatchesType(network->type()))
720         wifi_visible.push_back(network);
721       else
722         non_wifi_visible.push_back(network);
723     } else {
724       hidden.push_back(network);
725     }
726   }
727   network_list_.clear();
728   network_list_.insert(network_list_.end(), active.begin(), active.end());
729   network_list_.insert(
730       network_list_.end(), non_wifi_visible.begin(), non_wifi_visible.end());
731   network_list_.insert(
732       network_list_.end(), wifi_visible.begin(), wifi_visible.end());
733   network_list_.insert(network_list_.end(), hidden.begin(), hidden.end());
734   network_list_.insert(
735       network_list_.end(), new_networks.begin(), new_networks.end());
736   network_list_sorted_ = true;
737 }
738
739 void NetworkStateHandler::UpdateNetworkStats() {
740   size_t shared = 0, unshared = 0, visible = 0;
741   for (ManagedStateList::iterator iter = network_list_.begin();
742        iter != network_list_.end(); ++iter) {
743     NetworkState* network = (*iter)->AsNetworkState();
744     if (network->visible())
745       ++visible;
746     if (network->IsInProfile()) {
747       if (network->IsPrivate())
748         ++unshared;
749       else
750         ++shared;
751     }
752   }
753   UMA_HISTOGRAM_COUNTS_100("Networks.Visible", visible);
754   UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared);
755   UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared);
756 }
757
758 void NetworkStateHandler::DefaultNetworkServiceChanged(
759     const std::string& service_path) {
760   // Shill uses '/' for empty service path values; check explicitly for that.
761   const char* kEmptyServicePath = "/";
762   std::string new_service_path =
763       (service_path != kEmptyServicePath) ? service_path : "";
764   if (new_service_path == default_network_path_)
765     return;
766
767   default_network_path_ = service_path;
768   NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_);
769   const NetworkState* network = NULL;
770   if (!default_network_path_.empty()) {
771     network = GetNetworkState(default_network_path_);
772     if (!network) {
773       // If NetworkState is not available yet, do not notify observers here,
774       // they will be notified when the state is received.
775       NET_LOG_DEBUG("Default NetworkState not available",
776                     default_network_path_);
777       return;
778     }
779   }
780   if (network && !network->IsConnectedState()) {
781     NET_LOG_ERROR(
782         "DefaultNetwork is not connected: " + network->connection_state(),
783         network->path());
784   }
785   NotifyDefaultNetworkChanged(network);
786 }
787
788 //------------------------------------------------------------------------------
789 // Private methods
790
791 void NetworkStateHandler::UpdateGuid(NetworkState* network) {
792   std::string specifier = network->GetSpecifier();
793   DCHECK(!specifier.empty());
794   if (!network->guid().empty()) {
795     // If the network is saved in a profile, remove the entry from the map.
796     // Otherwise ensure that the entry matches the specified GUID. (e.g. in
797     // case a visible network with a specified guid gets configured with a
798     // new guid).
799     if (network->IsInProfile())
800       specifier_guid_map_.erase(specifier);
801     else
802       specifier_guid_map_[specifier] = network->guid();
803     return;
804   }
805   // Ensure that the NetworkState has a valid GUID.
806   std::string guid;
807   SpecifierGuidMap::iterator iter = specifier_guid_map_.find(specifier);
808   if (iter != specifier_guid_map_.end()) {
809     guid = iter->second;
810   } else {
811     guid = base::GenerateGUID();
812     specifier_guid_map_[specifier] = guid;
813   }
814   network->SetGuid(guid);
815 }
816
817 void NetworkStateHandler::NotifyDeviceListChanged() {
818   NET_LOG_DEBUG("NOTIFY:DeviceListChanged",
819                 base::StringPrintf("Size:%" PRIuS, device_list_.size()));
820   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
821                     DeviceListChanged());
822 }
823
824 DeviceState* NetworkStateHandler::GetModifiableDeviceState(
825     const std::string& device_path) const {
826   ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
827   if (!managed)
828     return NULL;
829   return managed->AsDeviceState();
830 }
831
832 NetworkState* NetworkStateHandler::GetModifiableNetworkState(
833     const std::string& service_path) const {
834   ManagedState* managed =
835       GetModifiableManagedState(&network_list_, service_path);
836   if (!managed)
837     return NULL;
838   return managed->AsNetworkState();
839 }
840
841 ManagedState* NetworkStateHandler::GetModifiableManagedState(
842     const ManagedStateList* managed_list,
843     const std::string& path) const {
844   for (ManagedStateList::const_iterator iter = managed_list->begin();
845        iter != managed_list->end(); ++iter) {
846     ManagedState* managed = *iter;
847     if (managed->path() == path)
848       return managed;
849   }
850   return NULL;
851 }
852
853 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
854     ManagedState::ManagedType type) {
855   switch (type) {
856     case ManagedState::MANAGED_TYPE_NETWORK:
857       return &network_list_;
858     case ManagedState::MANAGED_TYPE_DEVICE:
859       return &device_list_;
860   }
861   NOTREACHED();
862   return NULL;
863 }
864
865 void NetworkStateHandler::OnNetworkConnectionStateChanged(
866     NetworkState* network) {
867   DCHECK(network);
868   std::string event = "NetworkConnectionStateChanged";
869   if (network->path() == default_network_path_) {
870     event = "Default" + event;
871     if (!network->IsConnectedState()) {
872       NET_LOG_EVENT(
873           "DefaultNetwork is not connected: " + network->connection_state(),
874           network->path());
875       default_network_path_.clear();
876       SortNetworkList();
877       NotifyDefaultNetworkChanged(NULL);
878     }
879   }
880   NET_LOG_EVENT("NOTIFY:" + event + ": " + network->connection_state(),
881                 GetLogName(network));
882   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
883                     NetworkConnectionStateChanged(network));
884   if (network->path() == default_network_path_)
885     NotifyDefaultNetworkChanged(network);
886 }
887
888 void NetworkStateHandler::NotifyDefaultNetworkChanged(
889     const NetworkState* default_network) {
890   NET_LOG_EVENT("NOTIFY:DefaultNetworkChanged", GetLogName(default_network));
891   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
892                     DefaultNetworkChanged(default_network));
893 }
894
895 void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
896     const NetworkState* network) {
897   NET_LOG_DEBUG("NOTIFY:NetworkPropertiesUpdated", GetLogName(network));
898   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
899                     NetworkPropertiesUpdated(network));
900 }
901
902 void NetworkStateHandler::NotifyDevicePropertiesUpdated(
903     const DeviceState* device) {
904   NET_LOG_DEBUG("NOTIFY:DevicePropertiesUpdated", GetLogName(device));
905   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
906                     DevicePropertiesUpdated(device));
907 }
908
909 void NetworkStateHandler::ScanCompleted(const std::string& type) {
910   size_t num_callbacks = scan_complete_callbacks_.count(type);
911   NET_LOG_EVENT("ScanCompleted",
912                 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks));
913   if (num_callbacks == 0)
914     return;
915   ScanCallbackList& callback_list = scan_complete_callbacks_[type];
916   for (ScanCallbackList::iterator iter = callback_list.begin();
917        iter != callback_list.end(); ++iter) {
918     (*iter).Run();
919   }
920   scan_complete_callbacks_.erase(type);
921 }
922
923 std::string NetworkStateHandler::GetTechnologyForType(
924     const NetworkTypePattern& type) const {
925   if (type.MatchesType(shill::kTypeEthernet))
926     return shill::kTypeEthernet;
927
928   if (type.MatchesType(shill::kTypeWifi))
929     return shill::kTypeWifi;
930
931   if (type.Equals(NetworkTypePattern::Wimax()))
932     return shill::kTypeWimax;
933
934   // Prefer Wimax over Cellular only if it's available.
935   if (type.MatchesType(shill::kTypeWimax) &&
936       shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
937     return shill::kTypeWimax;
938   }
939
940   if (type.MatchesType(shill::kTypeCellular))
941     return shill::kTypeCellular;
942
943   NOTREACHED();
944   return std::string();
945 }
946
947 ScopedVector<std::string> NetworkStateHandler::GetTechnologiesForType(
948     const NetworkTypePattern& type) const {
949   ScopedVector<std::string> technologies;
950   if (type.MatchesType(shill::kTypeEthernet))
951     technologies.push_back(new std::string(shill::kTypeEthernet));
952   if (type.MatchesType(shill::kTypeWifi))
953     technologies.push_back(new std::string(shill::kTypeWifi));
954   if (type.MatchesType(shill::kTypeWimax))
955     technologies.push_back(new std::string(shill::kTypeWimax));
956   if (type.MatchesType(shill::kTypeCellular))
957     technologies.push_back(new std::string(shill::kTypeCellular));
958   if (type.MatchesType(shill::kTypeBluetooth))
959     technologies.push_back(new std::string(shill::kTypeBluetooth));
960   if (type.MatchesType(shill::kTypeVPN))
961     technologies.push_back(new std::string(shill::kTypeVPN));
962
963   CHECK_GT(technologies.size(), 0ul);
964   return technologies.Pass();
965 }
966
967 }  // namespace chromeos