Home | History | Annotate | Download | only in network
      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/stl_util.h"
     11 #include "base/strings/string_util.h"
     12 #include "base/strings/stringprintf.h"
     13 #include "base/values.h"
     14 #include "chromeos/network/device_state.h"
     15 #include "chromeos/network/favorite_state.h"
     16 #include "chromeos/network/managed_state.h"
     17 #include "chromeos/network/network_event_log.h"
     18 #include "chromeos/network/network_state.h"
     19 #include "chromeos/network/network_state_handler_observer.h"
     20 #include "chromeos/network/shill_property_handler.h"
     21 #include "third_party/cros_system_api/dbus/service_constants.h"
     22 
     23 namespace chromeos {
     24 
     25 namespace {
     26 
     27 // Returns true if |network->type()| == |match_type|, or it matches one of the
     28 // following special match types:
     29 // * kMatchTypeDefault matches any network (i.e. the first instance)
     30 // * kMatchTypeNonVirtual matches non virtual networks
     31 // * kMatchTypeWireless matches wireless networks
     32 // * kMatchTypeMobile matches cellular or wimax networks
     33 bool ManagedStateMatchesType(const ManagedState* managed,
     34                              const std::string& match_type) {
     35   const std::string& type = managed->type();
     36   if (match_type == NetworkStateHandler::kMatchTypeDefault)
     37     return true;
     38   if (match_type == type)
     39     return true;
     40   if (match_type == NetworkStateHandler::kMatchTypeNonVirtual &&
     41       type != flimflam::kTypeVPN) {
     42     return true;
     43   }
     44   if (match_type == NetworkStateHandler::kMatchTypeWireless &&
     45       type != flimflam::kTypeEthernet && type != flimflam::kTypeVPN) {
     46     return true;
     47   }
     48   if (match_type == NetworkStateHandler::kMatchTypeMobile &&
     49       (type == flimflam::kTypeCellular || type == flimflam::kTypeWimax)) {
     50     return true;
     51   }
     52   return false;
     53 }
     54 
     55 bool ConnectionStateChanged(NetworkState* network,
     56                             const std::string& prev_connection_state) {
     57   return (network->connection_state() != prev_connection_state) &&
     58          (network->connection_state() != flimflam::kStateIdle ||
     59           !prev_connection_state.empty());
     60 }
     61 
     62 std::string GetManagedStateLogType(const ManagedState* state) {
     63   switch (state->managed_type()) {
     64     case ManagedState::MANAGED_TYPE_NETWORK:
     65       return "Network";
     66     case ManagedState::MANAGED_TYPE_FAVORITE:
     67       return "Favorite";
     68     case ManagedState::MANAGED_TYPE_DEVICE:
     69       return "Device";
     70   }
     71   NOTREACHED();
     72   return "";
     73 }
     74 
     75 std::string GetManagedStateLogName(const ManagedState* state) {
     76   if (!state)
     77     return "None";
     78   return base::StringPrintf("%s (%s)", state->name().c_str(),
     79                             state->path().c_str());
     80 }
     81 
     82 }  // namespace
     83 
     84 const char NetworkStateHandler::kMatchTypeDefault[] = "default";
     85 const char NetworkStateHandler::kMatchTypeWireless[] = "wireless";
     86 const char NetworkStateHandler::kMatchTypeMobile[] = "mobile";
     87 const char NetworkStateHandler::kMatchTypeNonVirtual[] = "non-virtual";
     88 const char NetworkStateHandler::kDefaultCheckPortalList[] =
     89     "ethernet,wifi,cellular";
     90 
     91 NetworkStateHandler::NetworkStateHandler() {
     92 }
     93 
     94 NetworkStateHandler::~NetworkStateHandler() {
     95   STLDeleteContainerPointers(network_list_.begin(), network_list_.end());
     96   STLDeleteContainerPointers(favorite_list_.begin(), favorite_list_.end());
     97   STLDeleteContainerPointers(device_list_.begin(), device_list_.end());
     98 }
     99 
    100 void NetworkStateHandler::InitShillPropertyHandler() {
    101   shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
    102   shill_property_handler_->Init();
    103 }
    104 
    105 // static
    106 NetworkStateHandler* NetworkStateHandler::InitializeForTest() {
    107   NetworkStateHandler* handler = new NetworkStateHandler();
    108   handler->InitShillPropertyHandler();
    109   return handler;
    110 }
    111 
    112 void NetworkStateHandler::AddObserver(
    113     NetworkStateHandlerObserver* observer,
    114     const tracked_objects::Location& from_here) {
    115   observers_.AddObserver(observer);
    116   network_event_log::internal::AddEntry(
    117       from_here.file_name(), from_here.line_number(),
    118       network_event_log::LOG_LEVEL_DEBUG,
    119       "NetworkStateHandler::AddObserver", "");
    120 }
    121 
    122 void NetworkStateHandler::RemoveObserver(
    123     NetworkStateHandlerObserver* observer,
    124     const tracked_objects::Location& from_here) {
    125   observers_.RemoveObserver(observer);
    126   network_event_log::internal::AddEntry(
    127       from_here.file_name(), from_here.line_number(),
    128       network_event_log::LOG_LEVEL_DEBUG,
    129       "NetworkStateHandler::RemoveObserver", "");
    130 }
    131 
    132 void NetworkStateHandler::UpdateManagerProperties() {
    133   NET_LOG_USER("UpdateManagerProperties", "");
    134   shill_property_handler_->UpdateManagerProperties();
    135 }
    136 
    137 NetworkStateHandler::TechnologyState NetworkStateHandler::GetTechnologyState(
    138     const std::string& type) const {
    139   std::string technology = GetTechnologyForType(type);
    140   TechnologyState state;
    141   if (shill_property_handler_->IsTechnologyEnabled(technology))
    142     state = TECHNOLOGY_ENABLED;
    143   else if (shill_property_handler_->IsTechnologyEnabling(technology))
    144     state = TECHNOLOGY_ENABLING;
    145   else if (shill_property_handler_->IsTechnologyUninitialized(technology))
    146     state = TECHNOLOGY_UNINITIALIZED;
    147   else if (shill_property_handler_->IsTechnologyAvailable(technology))
    148     state = TECHNOLOGY_AVAILABLE;
    149   else
    150     state = TECHNOLOGY_UNAVAILABLE;
    151   VLOG(2) << "GetTechnologyState: " << type << " = " << state;
    152   return state;
    153 }
    154 
    155 void NetworkStateHandler::SetTechnologyEnabled(
    156     const std::string& type,
    157     bool enabled,
    158     const network_handler::ErrorCallback& error_callback) {
    159   std::string technology = GetTechnologyForType(type);
    160   NET_LOG_USER("SetTechnologyEnabled",
    161                base::StringPrintf("%s:%d", technology.c_str(), enabled));
    162   shill_property_handler_->SetTechnologyEnabled(
    163       technology, enabled, error_callback);
    164   // Signal Technology state changed -> ENABLING
    165   NotifyManagerPropertyChanged();
    166 }
    167 
    168 const DeviceState* NetworkStateHandler::GetDeviceState(
    169     const std::string& device_path) const {
    170   return GetModifiableDeviceState(device_path);
    171 }
    172 
    173 const DeviceState* NetworkStateHandler::GetDeviceStateByType(
    174     const std::string& type) const {
    175   for (ManagedStateList::const_iterator iter = device_list_.begin();
    176        iter != device_list_.end(); ++iter) {
    177     ManagedState* device = *iter;
    178     if (ManagedStateMatchesType(device, type))
    179       return device->AsDeviceState();
    180   }
    181   return NULL;
    182 }
    183 
    184 bool NetworkStateHandler::GetScanningByType(const std::string& type) const {
    185   for (ManagedStateList::const_iterator iter = device_list_.begin();
    186        iter != device_list_.end(); ++iter) {
    187     const DeviceState* device = (*iter)->AsDeviceState();
    188     DCHECK(device);
    189     if (ManagedStateMatchesType(device, type) && device->scanning())
    190       return true;
    191   }
    192   return false;
    193 }
    194 
    195 const NetworkState* NetworkStateHandler::GetNetworkState(
    196     const std::string& service_path) const {
    197   return GetModifiableNetworkState(service_path);
    198 }
    199 
    200 const NetworkState* NetworkStateHandler::DefaultNetwork() const {
    201   if (network_list_.empty())
    202     return NULL;
    203   const NetworkState* network = network_list_.front()->AsNetworkState();
    204   DCHECK(network);
    205   if (!network->IsConnectedState())
    206     return NULL;
    207   return network;
    208 }
    209 
    210 const NetworkState* NetworkStateHandler::ConnectedNetworkByType(
    211     const std::string& type) const {
    212   for (ManagedStateList::const_iterator iter = network_list_.begin();
    213        iter != network_list_.end(); ++iter) {
    214     const NetworkState* network = (*iter)->AsNetworkState();
    215     DCHECK(network);
    216     if (!network->IsConnectedState())
    217       break;  // Connected networks are listed first.
    218     if (ManagedStateMatchesType(network, type))
    219       return network;
    220   }
    221   return NULL;
    222 }
    223 
    224 const NetworkState* NetworkStateHandler::ConnectingNetworkByType(
    225     const std::string& type) const {
    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->IsConnectedState())
    231       continue;
    232     if (!network->IsConnectingState())
    233       break;  // Connected and connecting networks are listed first.
    234     if (ManagedStateMatchesType(network, type))
    235       return network;
    236   }
    237   return NULL;
    238 }
    239 
    240 const NetworkState* NetworkStateHandler::FirstNetworkByType(
    241     const std::string& type) const {
    242   for (ManagedStateList::const_iterator iter = network_list_.begin();
    243        iter != network_list_.end(); ++iter) {
    244     const NetworkState* network = (*iter)->AsNetworkState();
    245     DCHECK(network);
    246     if (ManagedStateMatchesType(network, type))
    247       return network;
    248   }
    249   return NULL;
    250 }
    251 
    252 std::string NetworkStateHandler::HardwareAddressForType(
    253     const std::string& type) const {
    254   std::string result;
    255   const NetworkState* network = ConnectedNetworkByType(type);
    256   if (network) {
    257     const DeviceState* device = GetDeviceState(network->device_path());
    258     if (device)
    259       result = device->mac_address();
    260   }
    261   StringToUpperASCII(&result);
    262   return result;
    263 }
    264 
    265 std::string NetworkStateHandler::FormattedHardwareAddressForType(
    266     const std::string& type) const {
    267   std::string address = HardwareAddressForType(type);
    268   if (address.size() % 2 != 0)
    269     return address;
    270   std::string result;
    271   for (size_t i = 0; i < address.size(); ++i) {
    272     if ((i != 0) && (i % 2 == 0))
    273       result.push_back(':');
    274     result.push_back(address[i]);
    275   }
    276   return result;
    277 }
    278 
    279 void NetworkStateHandler::GetNetworkList(NetworkStateList* list) const {
    280   DCHECK(list);
    281   list->clear();
    282   for (ManagedStateList::const_iterator iter = network_list_.begin();
    283        iter != network_list_.end(); ++iter) {
    284     if (!(*iter)->update_received())
    285       continue;
    286     const NetworkState* network = (*iter)->AsNetworkState();
    287     DCHECK(network);
    288     list->push_back(network);
    289   }
    290 }
    291 
    292 void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const {
    293   DCHECK(list);
    294   list->clear();
    295   for (ManagedStateList::const_iterator iter = device_list_.begin();
    296        iter != device_list_.end(); ++iter) {
    297     if (!(*iter)->update_received())
    298       continue;
    299     const DeviceState* device = (*iter)->AsDeviceState();
    300     DCHECK(device);
    301     list->push_back(device);
    302   }
    303 }
    304 
    305 void NetworkStateHandler::GetFavoriteList(FavoriteStateList* list) const {
    306   DCHECK(list);
    307   FavoriteStateList result;
    308   list->clear();
    309   for (ManagedStateList::const_iterator iter = favorite_list_.begin();
    310        iter != favorite_list_.end(); ++iter) {
    311     if (!(*iter)->update_received())
    312       continue;
    313     const FavoriteState* favorite = (*iter)->AsFavoriteState();
    314     DCHECK(favorite);
    315     if (favorite->is_favorite())
    316       list->push_back(favorite);
    317   }
    318 }
    319 
    320 const FavoriteState* NetworkStateHandler::GetFavoriteState(
    321     const std::string& service_path) const {
    322   ManagedState* managed =
    323       GetModifiableManagedState(&favorite_list_, service_path);
    324   if (!managed)
    325     return NULL;
    326   return managed->AsFavoriteState();
    327 }
    328 
    329 void NetworkStateHandler::RequestScan() const {
    330   NET_LOG_USER("RequestScan", "");
    331   shill_property_handler_->RequestScan();
    332 }
    333 
    334 void NetworkStateHandler::WaitForScan(const std::string& type,
    335                                       const base::Closure& callback) {
    336   scan_complete_callbacks_[type].push_back(callback);
    337   if (!GetScanningByType(type))
    338     RequestScan();
    339 }
    340 
    341 void NetworkStateHandler::ConnectToBestWifiNetwork() {
    342   NET_LOG_USER("ConnectToBestWifiNetwork", "");
    343   WaitForScan(flimflam::kTypeWifi,
    344               base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices,
    345                          shill_property_handler_->AsWeakPtr()));
    346 }
    347 
    348 bool NetworkStateHandler::RequestUpdateForNetwork(
    349     const std::string& service_path) {
    350   NetworkState* network = GetModifiableNetworkState(service_path);
    351   if (!network)
    352     return false;  // Only request an update for known networks.
    353   network->set_update_requested(true);
    354   NET_LOG_EVENT("RequestUpdate", service_path);
    355   shill_property_handler_->RequestProperties(
    356       ManagedState::MANAGED_TYPE_NETWORK, service_path);
    357   return true;
    358 }
    359 
    360 void NetworkStateHandler::RequestUpdateForAllNetworks() {
    361   NET_LOG_EVENT("RequestUpdateForAllNetworks", "");
    362   for (ManagedStateList::iterator iter = network_list_.begin();
    363        iter != network_list_.end(); ++iter) {
    364     ManagedState* network = *iter;
    365     network->set_update_requested(true);
    366     shill_property_handler_->RequestProperties(
    367         ManagedState::MANAGED_TYPE_NETWORK, network->path());
    368   }
    369 }
    370 
    371 void NetworkStateHandler::SetCheckPortalList(
    372     const std::string& check_portal_list) {
    373   NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
    374   shill_property_handler_->SetCheckPortalList(check_portal_list);
    375 }
    376 
    377 void NetworkStateHandler::GetNetworkStatePropertiesForTest(
    378     base::DictionaryValue* dictionary) const {
    379   for (ManagedStateList::const_iterator iter = network_list_.begin();
    380        iter != network_list_.end(); ++iter) {
    381     base::DictionaryValue* network_dict = new base::DictionaryValue;
    382     (*iter)->AsNetworkState()->GetProperties(network_dict);
    383     dictionary->SetWithoutPathExpansion((*iter)->path(), network_dict);
    384   }
    385 }
    386 
    387 //------------------------------------------------------------------------------
    388 // ShillPropertyHandler::Delegate overrides
    389 
    390 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type,
    391                                             const base::ListValue& entries) {
    392   ManagedStateList* managed_list = GetManagedList(type);
    393   NET_LOG_DEBUG(base::StringPrintf("UpdateManagedList:%d", type),
    394                 base::StringPrintf("%" PRIuS, entries.GetSize()));
    395   // Create a map of existing entries. Assumes all entries in |managed_list|
    396   // are unique.
    397   std::map<std::string, ManagedState*> managed_map;
    398   for (ManagedStateList::iterator iter = managed_list->begin();
    399        iter != managed_list->end(); ++iter) {
    400     ManagedState* managed = *iter;
    401     DCHECK(!ContainsKey(managed_map, managed->path()));
    402     managed_map[managed->path()] = managed;
    403   }
    404   // Clear the list (pointers are temporarily owned by managed_map).
    405   managed_list->clear();
    406   // Updates managed_list and request updates for new entries.
    407   std::set<std::string> list_entries;
    408   for (base::ListValue::const_iterator iter = entries.begin();
    409        iter != entries.end(); ++iter) {
    410     std::string path;
    411     (*iter)->GetAsString(&path);
    412     if (path.empty()) {
    413       LOG(ERROR) << "Empty path in list";
    414       continue;
    415     }
    416     std::map<std::string, ManagedState*>::iterator found =
    417         managed_map.find(path);
    418     ManagedState* managed;
    419     if (found == managed_map.end()) {
    420       if (list_entries.count(path) != 0) {
    421         LOG(ERROR) << "Duplicate entry in list: " << path;
    422         continue;
    423       }
    424       managed = ManagedState::Create(type, path);
    425       managed_list->push_back(managed);
    426     } else {
    427       managed = found->second;
    428       managed_list->push_back(managed);
    429       managed_map.erase(found);
    430     }
    431     list_entries.insert(path);
    432   }
    433   // Delete any remaining entries in managed_map.
    434   STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
    435 }
    436 
    437 void NetworkStateHandler::ProfileListChanged() {
    438   NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
    439   for (ManagedStateList::iterator iter = network_list_.begin();
    440        iter != network_list_.end(); ++iter) {
    441     shill_property_handler_->RequestProperties(
    442         ManagedState::MANAGED_TYPE_NETWORK, (*iter)->path());
    443   }
    444 }
    445 
    446 void NetworkStateHandler::UpdateManagedStateProperties(
    447     ManagedState::ManagedType type,
    448     const std::string& path,
    449     const base::DictionaryValue& properties) {
    450   ManagedStateList* managed_list = GetManagedList(type);
    451   ManagedState* managed = GetModifiableManagedState(managed_list, path);
    452   if (!managed) {
    453     if (type != ManagedState::MANAGED_TYPE_FAVORITE) {
    454       LOG(ERROR) << "GetPropertiesCallback: " << path << " Not found!";
    455       return;
    456     }
    457     // A Favorite may not have been created yet if it was added later (e.g.
    458     // through ConfigureService) since ServiceCompleteList updates are not
    459     // emitted. Add and update the state here.
    460     managed = new FavoriteState(path);
    461     managed_list->push_back(managed);
    462   }
    463   managed->set_update_received();
    464 
    465   std::string desc = GetManagedStateLogType(managed) + " PropertiesReceived";
    466   NET_LOG_DEBUG(desc, GetManagedStateLogName(managed));
    467 
    468   if (type == ManagedState::MANAGED_TYPE_NETWORK) {
    469     UpdateNetworkStateProperties(managed->AsNetworkState(), properties);
    470   } else {
    471     // Device, Favorite
    472     for (base::DictionaryValue::Iterator iter(properties);
    473          !iter.IsAtEnd(); iter.Advance()) {
    474       managed->PropertyChanged(iter.key(), iter.value());
    475     }
    476     managed->InitialPropertiesReceived(properties);
    477   }
    478   managed->set_update_requested(false);
    479 }
    480 
    481 void NetworkStateHandler::UpdateNetworkStateProperties(
    482     NetworkState* network,
    483     const base::DictionaryValue& properties) {
    484   DCHECK(network);
    485   bool network_property_updated = false;
    486   std::string prev_connection_state = network->connection_state();
    487   for (base::DictionaryValue::Iterator iter(properties);
    488        !iter.IsAtEnd(); iter.Advance()) {
    489     if (network->PropertyChanged(iter.key(), iter.value()))
    490       network_property_updated = true;
    491   }
    492   network_property_updated |= network->InitialPropertiesReceived(properties);
    493   // Notify observers of NetworkState changes.
    494   if (network_property_updated || network->update_requested()) {
    495     // Signal connection state changed after all properties have been updated.
    496     if (ConnectionStateChanged(network, prev_connection_state))
    497       OnNetworkConnectionStateChanged(network);
    498     NetworkPropertiesUpdated(network);
    499   }
    500 }
    501 
    502 void NetworkStateHandler::UpdateNetworkServiceProperty(
    503     const std::string& service_path,
    504     const std::string& key,
    505     const base::Value& value) {
    506   // Update any associated FavoriteState.
    507   ManagedState* favorite =
    508       GetModifiableManagedState(&favorite_list_, service_path);
    509   if (favorite)
    510     favorite->PropertyChanged(key, value);
    511 
    512   // Update the NetworkState.
    513   NetworkState* network = GetModifiableNetworkState(service_path);
    514   if (!network)
    515     return;
    516   std::string prev_connection_state = network->connection_state();
    517   std::string prev_profile_path = network->profile_path();
    518   if (!network->PropertyChanged(key, value))
    519     return;
    520 
    521   if (key == flimflam::kStateProperty) {
    522     if (ConnectionStateChanged(network, prev_connection_state)) {
    523       OnNetworkConnectionStateChanged(network);
    524       // If the connection state changes, other properties such as IPConfig
    525       // may have changed, so request a full update.
    526       RequestUpdateForNetwork(service_path);
    527     }
    528   } else {
    529     bool noisy_property =
    530         key == flimflam::kSignalStrengthProperty ||
    531         key == shill::kWifiFrequencyListProperty;
    532     if (network->path() == default_network_path_ && !noisy_property) {
    533       // Wifi SignalStrength and WifiFrequencyList updates are too noisy, so
    534       // don't trigger default network updates for those changes.
    535       OnDefaultNetworkChanged();
    536     }
    537     if (prev_profile_path.empty() && !network->profile_path().empty()) {
    538       // If added to a Profile, request a full update so that a FavoriteState
    539       // gets created.
    540       RequestUpdateForNetwork(service_path);
    541     }
    542     if (!noisy_property) {
    543       std::string detail = network->name() + "." + key;
    544       detail += " = " + network_event_log::ValueAsString(value);
    545       network_event_log::LogLevel log_level;
    546       if (key == flimflam::kErrorProperty ||
    547           key == shill::kErrorDetailsProperty) {
    548         log_level = network_event_log::LOG_LEVEL_ERROR;
    549       } else {
    550         log_level = network_event_log::LOG_LEVEL_EVENT;
    551       }
    552       NET_LOG_LEVEL(log_level, "NetworkPropertyUpdated", detail);
    553     }
    554   }
    555   NetworkPropertiesUpdated(network);
    556 }
    557 
    558 void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path,
    559                                                const std::string& key,
    560                                                const base::Value& value) {
    561   DeviceState* device = GetModifiableDeviceState(device_path);
    562   if (!device)
    563     return;
    564   if (!device->PropertyChanged(key, value))
    565     return;
    566 
    567   std::string detail = device->name() + "." + key;
    568   detail += " = " + network_event_log::ValueAsString(value);
    569   NET_LOG_EVENT("DevicePropertyUpdated", detail);
    570 
    571   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
    572                     DeviceListChanged());
    573 
    574   if (key == flimflam::kScanningProperty && device->scanning() == false)
    575     ScanCompleted(device->type());
    576 }
    577 
    578 void NetworkStateHandler::CheckPortalListChanged(
    579     const std::string& check_portal_list) {
    580   check_portal_list_ = check_portal_list;
    581 }
    582 
    583 void NetworkStateHandler::NotifyManagerPropertyChanged() {
    584   NET_LOG_DEBUG("NotifyManagerPropertyChanged", "");
    585   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
    586                     NetworkManagerChanged());
    587 }
    588 
    589 void NetworkStateHandler::ManagedStateListChanged(
    590     ManagedState::ManagedType type) {
    591   if (type == ManagedState::MANAGED_TYPE_NETWORK) {
    592     // Notify observers that the list of networks has changed.
    593     NET_LOG_EVENT("NetworkListChanged",
    594                   base::StringPrintf("Size:%" PRIuS, network_list_.size()));
    595     FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
    596                       NetworkListChanged());
    597     // The list order may have changed, so check if the default network changed.
    598     if (CheckDefaultNetworkChanged())
    599       OnDefaultNetworkChanged();
    600   } else if (type == ManagedState::MANAGED_TYPE_FAVORITE) {
    601     NET_LOG_DEBUG("FavoriteListChanged",
    602                   base::StringPrintf("Size:%" PRIuS, favorite_list_.size()));
    603     // The FavoriteState list only changes when the NetworkState list changes,
    604     // so no need to signal observers here again.
    605   } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
    606     NET_LOG_DEBUG("DeviceListChanged",
    607                   base::StringPrintf("Size:%" PRIuS, device_list_.size()));
    608     FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
    609                       DeviceListChanged());
    610   } else {
    611     NOTREACHED();
    612   }
    613 }
    614 
    615 //------------------------------------------------------------------------------
    616 // Private methods
    617 
    618 DeviceState* NetworkStateHandler::GetModifiableDeviceState(
    619     const std::string& device_path) const {
    620   ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
    621   if (!managed)
    622     return NULL;
    623   return managed->AsDeviceState();
    624 }
    625 
    626 NetworkState* NetworkStateHandler::GetModifiableNetworkState(
    627     const std::string& service_path) const {
    628   ManagedState* managed =
    629       GetModifiableManagedState(&network_list_, service_path);
    630   if (!managed)
    631     return NULL;
    632   return managed->AsNetworkState();
    633 }
    634 
    635 ManagedState* NetworkStateHandler::GetModifiableManagedState(
    636     const ManagedStateList* managed_list,
    637     const std::string& path) const {
    638   for (ManagedStateList::const_iterator iter = managed_list->begin();
    639        iter != managed_list->end(); ++iter) {
    640     ManagedState* managed = *iter;
    641     if (managed->path() == path)
    642       return managed;
    643   }
    644   return NULL;
    645 }
    646 
    647 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
    648     ManagedState::ManagedType type) {
    649   switch (type) {
    650     case ManagedState::MANAGED_TYPE_NETWORK:
    651       return &network_list_;
    652     case ManagedState::MANAGED_TYPE_FAVORITE:
    653       return &favorite_list_;
    654     case ManagedState::MANAGED_TYPE_DEVICE:
    655       return &device_list_;
    656   }
    657   NOTREACHED();
    658   return NULL;
    659 }
    660 
    661 void NetworkStateHandler::OnNetworkConnectionStateChanged(
    662     NetworkState* network) {
    663   DCHECK(network);
    664   NET_LOG_EVENT("NetworkConnectionStateChanged", base::StringPrintf(
    665       "%s:%s", GetManagedStateLogName(network).c_str(),
    666       network->connection_state().c_str()));
    667   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
    668                     NetworkConnectionStateChanged(network));
    669   if (CheckDefaultNetworkChanged() || network->path() == default_network_path_)
    670     OnDefaultNetworkChanged();
    671 }
    672 
    673 bool NetworkStateHandler::CheckDefaultNetworkChanged() {
    674   std::string new_default_network_path;
    675   const NetworkState* new_default_network = DefaultNetwork();
    676   if (new_default_network)
    677     new_default_network_path = new_default_network->path();
    678   if (new_default_network_path == default_network_path_)
    679     return false;
    680   default_network_path_ = new_default_network_path;
    681   return true;
    682 }
    683 
    684 void NetworkStateHandler::OnDefaultNetworkChanged() {
    685   const NetworkState* default_network = DefaultNetwork();
    686   NET_LOG_EVENT("DefaultNetworkChanged",
    687                 GetManagedStateLogName(default_network));
    688   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
    689                     DefaultNetworkChanged(default_network));
    690 }
    691 
    692 void NetworkStateHandler::NetworkPropertiesUpdated(
    693     const NetworkState* network) {
    694   FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
    695                     NetworkPropertiesUpdated(network));
    696 }
    697 
    698 void NetworkStateHandler::ScanCompleted(const std::string& type) {
    699   size_t num_callbacks = scan_complete_callbacks_.count(type);
    700   NET_LOG_EVENT("ScanCompleted",
    701                 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks));
    702   if (num_callbacks == 0)
    703     return;
    704   ScanCallbackList& callback_list = scan_complete_callbacks_[type];
    705   for (ScanCallbackList::iterator iter = callback_list.begin();
    706        iter != callback_list.end(); ++iter) {
    707     (*iter).Run();
    708   }
    709   scan_complete_callbacks_.erase(type);
    710 }
    711 
    712 std::string NetworkStateHandler::GetTechnologyForType(
    713     const std::string& type) const {
    714   if (type == kMatchTypeMobile) {
    715     if (shill_property_handler_->IsTechnologyAvailable(flimflam::kTypeWimax))
    716       return flimflam::kTypeWimax;
    717     else
    718       return flimflam::kTypeCellular;
    719   }
    720   if (type == kMatchTypeDefault || type == kMatchTypeNonVirtual ||
    721       type == kMatchTypeWireless) {
    722     NOTREACHED();
    723     return flimflam::kTypeWifi;
    724   }
    725   return type;
    726 }
    727 
    728 }  // namespace chromeos
    729