Update To 11.40.268.0
[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 void NetworkStateHandler::SetWakeOnLanEnabled(bool enabled) {
382   NET_LOG_EVENT("SetWakeOnLanEnabled",
383                 base::StringPrintf("%s", enabled ? "true" : "false"));
384   shill_property_handler_->SetWakeOnLanEnabled(enabled);
385 }
386
387 const NetworkState* NetworkStateHandler::GetEAPForEthernet(
388     const std::string& service_path) {
389   const NetworkState* network = GetNetworkState(service_path);
390   if (!network) {
391     NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path);
392     return NULL;
393   }
394   if (network->type() != shill::kTypeEthernet) {
395     NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path);
396     return NULL;
397   }
398   if (!network->IsConnectedState())
399     return NULL;
400
401   // The same EAP service is shared for all ethernet services/devices.
402   // However EAP is used/enabled per device and only if the connection was
403   // successfully established.
404   const DeviceState* device = GetDeviceState(network->device_path());
405   if (!device) {
406     NET_LOG_ERROR(
407         "GetEAPForEthernet",
408         base::StringPrintf("Unknown device %s of connected ethernet service %s",
409                            network->device_path().c_str(),
410                            service_path.c_str()));
411     return NULL;
412   }
413   if (!device->eap_authentication_completed())
414     return NULL;
415
416   NetworkStateList list;
417   GetNetworkListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap),
418                        true /* configured_only */,
419                        false /* visible_only */,
420                        1 /* limit */,
421                        &list);
422   if (list.empty()) {
423     NET_LOG_ERROR("GetEAPForEthernet",
424                   base::StringPrintf(
425                       "Ethernet service %s connected using EAP, but no "
426                       "EAP service found.",
427                       service_path.c_str()));
428     return NULL;
429   }
430   return list.front();
431 }
432
433 //------------------------------------------------------------------------------
434 // ShillPropertyHandler::Delegate overrides
435
436 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type,
437                                             const base::ListValue& entries) {
438   ManagedStateList* managed_list = GetManagedList(type);
439   NET_LOG_DEBUG("UpdateManagedList: " + ManagedState::TypeToString(type),
440                 base::StringPrintf("%" PRIuS, entries.GetSize()));
441   // Create a map of existing entries. Assumes all entries in |managed_list|
442   // are unique.
443   typedef std::map<std::string, ManagedState*> ManagedMap;
444   ManagedMap managed_map;
445   for (ManagedStateList::iterator iter = managed_list->begin();
446        iter != managed_list->end(); ++iter) {
447     ManagedState* managed = *iter;
448     DCHECK(!ContainsKey(managed_map, managed->path()));
449     managed_map[managed->path()] = managed;
450   }
451   // Clear the list (pointers are temporarily owned by managed_map).
452   managed_list->clear();
453   // Updates managed_list and request updates for new entries.
454   std::set<std::string> list_entries;
455   for (base::ListValue::const_iterator iter = entries.begin();
456        iter != entries.end(); ++iter) {
457     std::string path;
458     (*iter)->GetAsString(&path);
459     if (path.empty() || path == shill::kFlimflamServicePath) {
460       NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path);
461       continue;
462     }
463     ManagedMap::iterator found = managed_map.find(path);
464     if (found == managed_map.end()) {
465       if (list_entries.count(path) != 0) {
466         NET_LOG_ERROR("Duplicate entry in list", path);
467         continue;
468       }
469       ManagedState* managed = ManagedState::Create(type, path);
470       managed_list->push_back(managed);
471     } else {
472       managed_list->push_back(found->second);
473       managed_map.erase(found);
474     }
475     list_entries.insert(path);
476   }
477   // Delete any remaining entries in managed_map.
478   STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
479 }
480
481 void NetworkStateHandler::ProfileListChanged() {
482   NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
483   for (ManagedStateList::iterator iter = network_list_.begin();
484        iter != network_list_.end(); ++iter) {
485     NetworkState* network = (*iter)->AsNetworkState();
486     DCHECK(network);
487     shill_property_handler_->RequestProperties(
488         ManagedState::MANAGED_TYPE_NETWORK, network->path());
489   }
490 }
491
492 void NetworkStateHandler::UpdateManagedStateProperties(
493     ManagedState::ManagedType type,
494     const std::string& path,
495     const base::DictionaryValue& properties) {
496   ManagedStateList* managed_list = GetManagedList(type);
497   ManagedState* managed = GetModifiableManagedState(managed_list, path);
498   if (!managed) {
499     // The network has been removed from the list of networks.
500     NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path);
501     return;
502   }
503   managed->set_update_received();
504
505   std::string desc = GetManagedStateLogType(managed) + " Properties Received";
506   NET_LOG_DEBUG(desc, GetLogName(managed));
507
508   if (type == ManagedState::MANAGED_TYPE_NETWORK) {
509     UpdateNetworkStateProperties(managed->AsNetworkState(), properties);
510   } else {
511     // Device
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
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   UpdateGuid(network);
534   network_list_sorted_ = false;
535
536   // Notify observers of NetworkState changes.
537   if (network_property_updated || network->update_requested()) {
538     // Signal connection state changed after all properties have been updated.
539     if (ConnectionStateChanged(network, prev_connection_state))
540       OnNetworkConnectionStateChanged(network);
541     NET_LOG_EVENT("NetworkPropertiesUpdated", GetLogName(network));
542     NotifyNetworkPropertiesUpdated(network);
543   }
544 }
545
546 void NetworkStateHandler::UpdateNetworkServiceProperty(
547     const std::string& service_path,
548     const std::string& key,
549     const base::Value& value) {
550   bool changed = false;
551   NetworkState* network = GetModifiableNetworkState(service_path);
552   if (!network)
553     return;
554   std::string prev_connection_state = network->connection_state();
555   std::string prev_profile_path = network->profile_path();
556   changed |= network->PropertyChanged(key, value);
557   if (!changed)
558     return;
559
560   if (key == shill::kStateProperty || key == shill::kVisibleProperty) {
561     network_list_sorted_ = false;
562     if (ConnectionStateChanged(network, prev_connection_state)) {
563       OnNetworkConnectionStateChanged(network);
564       // If the connection state changes, other properties such as IPConfig
565       // may have changed, so request a full update.
566       RequestUpdateForNetwork(service_path);
567     }
568   } else {
569     std::string value_str;
570     value.GetAsString(&value_str);
571     // Some property changes are noisy and not interesting:
572     // * Wifi SignalStrength
573     // * WifiFrequencyList updates
574     // * Device property changes to "/" (occurs before a service is removed)
575     if (key != shill::kSignalStrengthProperty &&
576         key != shill::kWifiFrequencyListProperty &&
577         (key != shill::kDeviceProperty || value_str != "/")) {
578       std::string log_event = "NetworkPropertyUpdated";
579       // Trigger a default network update for interesting changes only.
580       if (network->path() == default_network_path_) {
581         NotifyDefaultNetworkChanged(network);
582         log_event = "Default" + log_event;
583       }
584       // Log event.
585       std::string detail = network->name() + "." + key;
586       detail += " = " + network_event_log::ValueAsString(value);
587       network_event_log::LogLevel log_level;
588       if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) {
589         log_level = network_event_log::LOG_LEVEL_ERROR;
590       } else {
591         log_level = network_event_log::LOG_LEVEL_EVENT;
592       }
593       NET_LOG_LEVEL(log_level, log_event, detail);
594     }
595   }
596
597   // All property updates signal 'NetworkPropertiesUpdated'.
598   NotifyNetworkPropertiesUpdated(network);
599
600   // If added to a Profile, request a full update so that a NetworkState
601   // gets created.
602   if (prev_profile_path.empty() && !network->profile_path().empty())
603     RequestUpdateForNetwork(service_path);
604 }
605
606 void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path,
607                                                const std::string& key,
608                                                const base::Value& value) {
609   DeviceState* device = GetModifiableDeviceState(device_path);
610   if (!device)
611     return;
612   if (!device->PropertyChanged(key, value))
613     return;
614
615   std::string detail = device->name() + "." + key;
616   detail += " = " + network_event_log::ValueAsString(value);
617   NET_LOG_EVENT("DevicePropertyUpdated", detail);
618
619   NotifyDeviceListChanged();
620   NotifyDevicePropertiesUpdated(device);
621
622   if (key == shill::kScanningProperty && device->scanning() == false)
623     ScanCompleted(device->type());
624   if (key == shill::kEapAuthenticationCompletedProperty) {
625     // Notify a change for each Ethernet service using this device.
626     NetworkStateList ethernet_services;
627     GetNetworkListByType(NetworkTypePattern::Ethernet(),
628                          false /* configured_only */,
629                          false /* visible_only */,
630                          0 /* no limit */,
631                          &ethernet_services);
632     for (NetworkStateList::const_iterator it = ethernet_services.begin();
633          it != ethernet_services.end(); ++it) {
634       const NetworkState* ethernet_service = *it;
635       if (ethernet_service->update_received() ||
636           ethernet_service->device_path() != device->path()) {
637         continue;
638       }
639       RequestUpdateForNetwork(ethernet_service->path());
640     }
641   }
642 }
643
644 void NetworkStateHandler::UpdateIPConfigProperties(
645     ManagedState::ManagedType type,
646     const std::string& path,
647     const std::string& ip_config_path,
648     const base::DictionaryValue& properties)  {
649   if (type == ManagedState::MANAGED_TYPE_NETWORK) {
650     NetworkState* network = GetModifiableNetworkState(path);
651     if (!network)
652       return;
653     network->IPConfigPropertiesChanged(properties);
654     NotifyNetworkPropertiesUpdated(network);
655     if (network->path() == default_network_path_)
656       NotifyDefaultNetworkChanged(network);
657   } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
658     DeviceState* device = GetModifiableDeviceState(path);
659     if (!device)
660       return;
661     device->IPConfigPropertiesChanged(ip_config_path, properties);
662     NotifyDevicePropertiesUpdated(device);
663     if (!default_network_path_.empty()) {
664       const NetworkState* default_network =
665           GetNetworkState(default_network_path_);
666       if (default_network && default_network->device_path() == path)
667         NotifyDefaultNetworkChanged(default_network);
668     }
669   }
670 }
671
672 void NetworkStateHandler::CheckPortalListChanged(
673     const std::string& check_portal_list) {
674   check_portal_list_ = check_portal_list;
675 }
676
677 void NetworkStateHandler::TechnologyListChanged() {
678   // Eventually we would like to replace Technology state with Device state.
679   // For now, treat technology state changes as device list changes.
680   NotifyDeviceListChanged();
681 }
682
683 void NetworkStateHandler::ManagedStateListChanged(
684     ManagedState::ManagedType type) {
685   if (type == ManagedState::MANAGED_TYPE_NETWORK) {
686     SortNetworkList();
687     UpdateNetworkStats();
688     // Notify observers that the list of networks has changed.
689     NET_LOG_EVENT("NOTIFY:NetworkListChanged",
690                   base::StringPrintf("Size:%" PRIuS, network_list_.size()));
691     FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
692                       NetworkListChanged());
693   } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
694     std::string devices;
695     for (ManagedStateList::const_iterator iter = device_list_.begin();
696          iter != device_list_.end(); ++iter) {
697       if (iter != device_list_.begin())
698         devices += ", ";
699       devices += (*iter)->name();
700     }
701     NET_LOG_EVENT("DeviceList", devices);
702     NotifyDeviceListChanged();
703   } else {
704     NOTREACHED();
705   }
706 }
707
708 void NetworkStateHandler::SortNetworkList() {
709   // Note: usually active networks will precede inactive networks, however
710   // this may briefly be untrue during state transitions (e.g. a network may
711   // transition to idle before the list is updated).
712   ManagedStateList active, non_wifi_visible, wifi_visible, hidden, new_networks;
713   for (ManagedStateList::iterator iter = network_list_.begin();
714        iter != network_list_.end(); ++iter) {
715     NetworkState* network = (*iter)->AsNetworkState();
716     if (!network->update_received()) {
717       new_networks.push_back(network);
718       continue;
719     }
720     if (network->IsConnectedState() || network->IsConnectingState()) {
721       active.push_back(network);
722       continue;
723     }
724     if (network->visible()) {
725       if (NetworkTypePattern::WiFi().MatchesType(network->type()))
726         wifi_visible.push_back(network);
727       else
728         non_wifi_visible.push_back(network);
729     } else {
730       hidden.push_back(network);
731     }
732   }
733   network_list_.clear();
734   network_list_.insert(network_list_.end(), active.begin(), active.end());
735   network_list_.insert(
736       network_list_.end(), non_wifi_visible.begin(), non_wifi_visible.end());
737   network_list_.insert(
738       network_list_.end(), wifi_visible.begin(), wifi_visible.end());
739   network_list_.insert(network_list_.end(), hidden.begin(), hidden.end());
740   network_list_.insert(
741       network_list_.end(), new_networks.begin(), new_networks.end());
742   network_list_sorted_ = true;
743 }
744
745 void NetworkStateHandler::UpdateNetworkStats() {
746   size_t shared = 0, unshared = 0, visible = 0;
747   for (ManagedStateList::iterator iter = network_list_.begin();
748        iter != network_list_.end(); ++iter) {
749     NetworkState* network = (*iter)->AsNetworkState();
750     if (network->visible())
751       ++visible;
752     if (network->IsInProfile()) {
753       if (network->IsPrivate())
754         ++unshared;
755       else
756         ++shared;
757     }
758   }
759   UMA_HISTOGRAM_COUNTS_100("Networks.Visible", visible);
760   UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared);
761   UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared);
762 }
763
764 void NetworkStateHandler::DefaultNetworkServiceChanged(
765     const std::string& service_path) {
766   // Shill uses '/' for empty service path values; check explicitly for that.
767   const char* kEmptyServicePath = "/";
768   std::string new_service_path =
769       (service_path != kEmptyServicePath) ? service_path : "";
770   if (new_service_path == default_network_path_)
771     return;
772
773   default_network_path_ = service_path;
774   NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_);
775   const NetworkState* network = NULL;
776   if (!default_network_path_.empty()) {
777     network = GetNetworkState(default_network_path_);
778     if (!network) {
779       // If NetworkState is not available yet, do not notify observers here,
780       // they will be notified when the state is received.
781       NET_LOG_DEBUG("Default NetworkState not available",
782                     default_network_path_);
783       return;
784     }
785   }
786   if (network && !network->IsConnectedState()) {
787     NET_LOG_ERROR(
788         "DefaultNetwork is not connected: " + network->connection_state(),
789         network->path());
790   }
791   NotifyDefaultNetworkChanged(network);
792 }
793
794 //------------------------------------------------------------------------------
795 // Private methods
796
797 void NetworkStateHandler::UpdateGuid(NetworkState* network) {
798   std::string specifier = network->GetSpecifier();
799   DCHECK(!specifier.empty());
800   if (!network->guid().empty()) {
801     // If the network is saved in a profile, remove the entry from the map.
802     // Otherwise ensure that the entry matches the specified GUID. (e.g. in
803     // case a visible network with a specified guid gets configured with a
804     // new guid).
805     if (network->IsInProfile())
806       specifier_guid_map_.erase(specifier);
807     else
808       specifier_guid_map_[specifier] = network->guid();
809     return;
810   }
811   // Ensure that the NetworkState has a valid GUID.
812   std::string guid;
813   SpecifierGuidMap::iterator iter = specifier_guid_map_.find(specifier);
814   if (iter != specifier_guid_map_.end()) {
815     guid = iter->second;
816   } else {
817     guid = base::GenerateGUID();
818     specifier_guid_map_[specifier] = guid;
819   }
820   network->SetGuid(guid);
821 }
822
823 void NetworkStateHandler::NotifyDeviceListChanged() {
824   NET_LOG_DEBUG("NOTIFY:DeviceListChanged",
825                 base::StringPrintf("Size:%" PRIuS, device_list_.size()));
826   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
827                     DeviceListChanged());
828 }
829
830 DeviceState* NetworkStateHandler::GetModifiableDeviceState(
831     const std::string& device_path) const {
832   ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
833   if (!managed)
834     return NULL;
835   return managed->AsDeviceState();
836 }
837
838 NetworkState* NetworkStateHandler::GetModifiableNetworkState(
839     const std::string& service_path) const {
840   ManagedState* managed =
841       GetModifiableManagedState(&network_list_, service_path);
842   if (!managed)
843     return NULL;
844   return managed->AsNetworkState();
845 }
846
847 ManagedState* NetworkStateHandler::GetModifiableManagedState(
848     const ManagedStateList* managed_list,
849     const std::string& path) const {
850   for (ManagedStateList::const_iterator iter = managed_list->begin();
851        iter != managed_list->end(); ++iter) {
852     ManagedState* managed = *iter;
853     if (managed->path() == path)
854       return managed;
855   }
856   return NULL;
857 }
858
859 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
860     ManagedState::ManagedType type) {
861   switch (type) {
862     case ManagedState::MANAGED_TYPE_NETWORK:
863       return &network_list_;
864     case ManagedState::MANAGED_TYPE_DEVICE:
865       return &device_list_;
866   }
867   NOTREACHED();
868   return NULL;
869 }
870
871 void NetworkStateHandler::OnNetworkConnectionStateChanged(
872     NetworkState* network) {
873   DCHECK(network);
874   std::string event = "NetworkConnectionStateChanged";
875   if (network->path() == default_network_path_) {
876     event = "Default" + event;
877     if (!network->IsConnectedState()) {
878       NET_LOG_EVENT(
879           "DefaultNetwork is not connected: " + network->connection_state(),
880           network->path());
881       default_network_path_.clear();
882       SortNetworkList();
883       NotifyDefaultNetworkChanged(NULL);
884     }
885   }
886   NET_LOG_EVENT("NOTIFY:" + event + ": " + network->connection_state(),
887                 GetLogName(network));
888   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
889                     NetworkConnectionStateChanged(network));
890   if (network->path() == default_network_path_)
891     NotifyDefaultNetworkChanged(network);
892 }
893
894 void NetworkStateHandler::NotifyDefaultNetworkChanged(
895     const NetworkState* default_network) {
896   NET_LOG_EVENT("NOTIFY:DefaultNetworkChanged", GetLogName(default_network));
897   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
898                     DefaultNetworkChanged(default_network));
899 }
900
901 void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
902     const NetworkState* network) {
903   NET_LOG_DEBUG("NOTIFY:NetworkPropertiesUpdated", GetLogName(network));
904   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
905                     NetworkPropertiesUpdated(network));
906 }
907
908 void NetworkStateHandler::NotifyDevicePropertiesUpdated(
909     const DeviceState* device) {
910   NET_LOG_DEBUG("NOTIFY:DevicePropertiesUpdated", GetLogName(device));
911   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
912                     DevicePropertiesUpdated(device));
913 }
914
915 void NetworkStateHandler::ScanCompleted(const std::string& type) {
916   size_t num_callbacks = scan_complete_callbacks_.count(type);
917   NET_LOG_EVENT("ScanCompleted",
918                 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks));
919   if (num_callbacks == 0)
920     return;
921   ScanCallbackList& callback_list = scan_complete_callbacks_[type];
922   for (ScanCallbackList::iterator iter = callback_list.begin();
923        iter != callback_list.end(); ++iter) {
924     (*iter).Run();
925   }
926   scan_complete_callbacks_.erase(type);
927 }
928
929 std::string NetworkStateHandler::GetTechnologyForType(
930     const NetworkTypePattern& type) const {
931   if (type.MatchesType(shill::kTypeEthernet))
932     return shill::kTypeEthernet;
933
934   if (type.MatchesType(shill::kTypeWifi))
935     return shill::kTypeWifi;
936
937   if (type.Equals(NetworkTypePattern::Wimax()))
938     return shill::kTypeWimax;
939
940   // Prefer Wimax over Cellular only if it's available.
941   if (type.MatchesType(shill::kTypeWimax) &&
942       shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
943     return shill::kTypeWimax;
944   }
945
946   if (type.MatchesType(shill::kTypeCellular))
947     return shill::kTypeCellular;
948
949   NOTREACHED();
950   return std::string();
951 }
952
953 ScopedVector<std::string> NetworkStateHandler::GetTechnologiesForType(
954     const NetworkTypePattern& type) const {
955   ScopedVector<std::string> technologies;
956   if (type.MatchesType(shill::kTypeEthernet))
957     technologies.push_back(new std::string(shill::kTypeEthernet));
958   if (type.MatchesType(shill::kTypeWifi))
959     technologies.push_back(new std::string(shill::kTypeWifi));
960   if (type.MatchesType(shill::kTypeWimax))
961     technologies.push_back(new std::string(shill::kTypeWimax));
962   if (type.MatchesType(shill::kTypeCellular))
963     technologies.push_back(new std::string(shill::kTypeCellular));
964   if (type.MatchesType(shill::kTypeBluetooth))
965     technologies.push_back(new std::string(shill::kTypeBluetooth));
966   if (type.MatchesType(shill::kTypeVPN))
967     technologies.push_back(new std::string(shill::kTypeVPN));
968
969   CHECK_GT(technologies.size(), 0ul);
970   return technologies.Pass();
971 }
972
973 }  // namespace chromeos