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