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