network_state_handler.cc revision 2385ea399aae016c0806a4f9ef3c9cfe3d2a39df
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
23namespace chromeos {
24
25namespace {
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
33bool 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
55bool 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
62std::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
75std::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
84const char NetworkStateHandler::kMatchTypeDefault[] = "default";
85const char NetworkStateHandler::kMatchTypeWireless[] = "wireless";
86const char NetworkStateHandler::kMatchTypeMobile[] = "mobile";
87const char NetworkStateHandler::kMatchTypeNonVirtual[] = "non-virtual";
88const char NetworkStateHandler::kDefaultCheckPortalList[] =
89    "ethernet,wifi,cellular";
90
91NetworkStateHandler::NetworkStateHandler() {
92}
93
94NetworkStateHandler::~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
100void NetworkStateHandler::InitShillPropertyHandler() {
101  shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
102  shill_property_handler_->Init();
103}
104
105// static
106NetworkStateHandler* NetworkStateHandler::InitializeForTest() {
107  NetworkStateHandler* handler = new NetworkStateHandler();
108  handler->InitShillPropertyHandler();
109  return handler;
110}
111
112void 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
122void 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
132void NetworkStateHandler::UpdateManagerProperties() {
133  NET_LOG_USER("UpdateManagerProperties", "");
134  shill_property_handler_->UpdateManagerProperties();
135}
136
137NetworkStateHandler::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
155void 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
168const DeviceState* NetworkStateHandler::GetDeviceState(
169    const std::string& device_path) const {
170  return GetModifiableDeviceState(device_path);
171}
172
173const 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
184bool 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
195const NetworkState* NetworkStateHandler::GetNetworkState(
196    const std::string& service_path) const {
197  return GetModifiableNetworkState(service_path);
198}
199
200const 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
210const 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
224const 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
240const 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
252std::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
265std::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
279void 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
292void 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
305void 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
320const 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
329void NetworkStateHandler::RequestScan() const {
330  NET_LOG_USER("RequestScan", "");
331  shill_property_handler_->RequestScan();
332}
333
334void 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
341void NetworkStateHandler::ConnectToBestWifiNetwork() {
342  NET_LOG_USER("ConnectToBestWifiNetwork", "");
343  WaitForScan(flimflam::kTypeWifi,
344              base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices,
345                         shill_property_handler_->AsWeakPtr()));
346}
347
348bool 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
360void 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
371void NetworkStateHandler::SetConnectingNetwork(
372    const std::string& service_path) {
373  connecting_network_ = service_path;
374  const NetworkState* network = GetNetworkState(service_path);
375  if (network)
376    NET_LOG_EVENT("SetConnectingNetwork", GetManagedStateLogName(network));
377  else
378    NET_LOG_ERROR("SetConnectingNetwork to unknown network", service_path);
379}
380
381void NetworkStateHandler::SetCheckPortalList(
382    const std::string& check_portal_list) {
383  NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
384  shill_property_handler_->SetCheckPortalList(check_portal_list);
385}
386
387void NetworkStateHandler::GetNetworkStatePropertiesForTest(
388    base::DictionaryValue* dictionary) const {
389  for (ManagedStateList::const_iterator iter = network_list_.begin();
390       iter != network_list_.end(); ++iter) {
391    base::DictionaryValue* network_dict = new base::DictionaryValue;
392    (*iter)->AsNetworkState()->GetProperties(network_dict);
393    dictionary->SetWithoutPathExpansion((*iter)->path(), network_dict);
394  }
395}
396
397//------------------------------------------------------------------------------
398// ShillPropertyHandler::Delegate overrides
399
400void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type,
401                                            const base::ListValue& entries) {
402  ManagedStateList* managed_list = GetManagedList(type);
403  NET_LOG_DEBUG(base::StringPrintf("UpdateManagedList:%d", type),
404                base::StringPrintf("%" PRIuS, entries.GetSize()));
405  // Create a map of existing entries. Assumes all entries in |managed_list|
406  // are unique.
407  std::map<std::string, ManagedState*> managed_map;
408  for (ManagedStateList::iterator iter = managed_list->begin();
409       iter != managed_list->end(); ++iter) {
410    ManagedState* managed = *iter;
411    DCHECK(!ContainsKey(managed_map, managed->path()));
412    managed_map[managed->path()] = managed;
413  }
414  // Clear the list (pointers are temporarily owned by managed_map).
415  managed_list->clear();
416  // Updates managed_list and request updates for new entries.
417  std::set<std::string> list_entries;
418  for (base::ListValue::const_iterator iter = entries.begin();
419       iter != entries.end(); ++iter) {
420    std::string path;
421    (*iter)->GetAsString(&path);
422    if (path.empty()) {
423      LOG(ERROR) << "Empty path in list";
424      continue;
425    }
426    std::map<std::string, ManagedState*>::iterator found =
427        managed_map.find(path);
428    ManagedState* managed;
429    if (found == managed_map.end()) {
430      if (list_entries.count(path) != 0) {
431        LOG(ERROR) << "Duplicate entry in list: " << path;
432        continue;
433      }
434      managed = ManagedState::Create(type, path);
435      managed_list->push_back(managed);
436    } else {
437      managed = found->second;
438      managed_list->push_back(managed);
439      managed_map.erase(found);
440    }
441    list_entries.insert(path);
442  }
443  // Delete any remaning entries in managed_map.
444  STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
445}
446
447void NetworkStateHandler::ProfileListChanged() {
448  NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
449  for (ManagedStateList::iterator iter = network_list_.begin();
450       iter != network_list_.end(); ++iter) {
451    shill_property_handler_->RequestProperties(
452        ManagedState::MANAGED_TYPE_NETWORK, (*iter)->path());
453  }
454}
455
456void NetworkStateHandler::UpdateManagedStateProperties(
457    ManagedState::ManagedType type,
458    const std::string& path,
459    const base::DictionaryValue& properties) {
460  ManagedStateList* managed_list = GetManagedList(type);
461  ManagedState* managed = GetModifiableManagedState(managed_list, path);
462  if (!managed) {
463    if (type != ManagedState::MANAGED_TYPE_FAVORITE) {
464      LOG(ERROR) << "GetPropertiesCallback: " << path << " Not found!";
465      return;
466    }
467    // A Favorite may not have been created yet if it was added later (e.g.
468    // through ConfigureService) since ServiceCompleteList updates are not
469    // emitted. Add and update the state here.
470    managed = new FavoriteState(path);
471    managed_list->push_back(managed);
472  }
473  managed->set_update_received();
474
475  std::string desc = GetManagedStateLogType(managed) + " PropertiesReceived";
476  NET_LOG_DEBUG(desc, GetManagedStateLogName(managed));
477
478  if (type == ManagedState::MANAGED_TYPE_NETWORK) {
479    UpdateNetworkStateProperties(managed->AsNetworkState(), properties);
480  } else {
481    // Device, Favorite
482    for (base::DictionaryValue::Iterator iter(properties);
483         !iter.IsAtEnd(); iter.Advance()) {
484      managed->PropertyChanged(iter.key(), iter.value());
485    }
486    managed->InitialPropertiesReceived(properties);
487  }
488  managed->set_update_requested(false);
489}
490
491void NetworkStateHandler::UpdateNetworkStateProperties(
492    NetworkState* network,
493    const base::DictionaryValue& properties) {
494  DCHECK(network);
495  bool network_property_updated = false;
496  std::string prev_connection_state = network->connection_state();
497  for (base::DictionaryValue::Iterator iter(properties);
498       !iter.IsAtEnd(); iter.Advance()) {
499    if (network->PropertyChanged(iter.key(), iter.value()))
500      network_property_updated = true;
501  }
502  network_property_updated |= network->InitialPropertiesReceived(properties);
503  // Notify observers of NetworkState changes.
504  if (network_property_updated || network->update_requested()) {
505    // Signal connection state changed after all properties have been updated.
506    if (ConnectionStateChanged(network, prev_connection_state))
507      OnNetworkConnectionStateChanged(network);
508    NetworkPropertiesUpdated(network);
509  }
510}
511
512void NetworkStateHandler::UpdateNetworkServiceProperty(
513    const std::string& service_path,
514    const std::string& key,
515    const base::Value& value) {
516  // Update any associated FavoriteState.
517  ManagedState* favorite =
518      GetModifiableManagedState(&favorite_list_, service_path);
519  if (favorite)
520    favorite->PropertyChanged(key, value);
521
522  // Update the NetworkState.
523  NetworkState* network = GetModifiableNetworkState(service_path);
524  if (!network)
525    return;
526  std::string prev_connection_state = network->connection_state();
527  if (!network->PropertyChanged(key, value))
528    return;
529
530  if (key == flimflam::kStateProperty) {
531    if (ConnectionStateChanged(network, prev_connection_state))
532      OnNetworkConnectionStateChanged(network);
533  } else {
534    if (network->path() == default_network_path_ &&
535        key != flimflam::kSignalStrengthProperty &&
536        key != shill::kWifiFrequencyListProperty) {
537      // WiFi SignalStrength and WifiFrequencyList updates are too noisy, so
538      // don't trigger default network updates for those changes.
539      OnDefaultNetworkChanged();
540    }
541    std::string detail = network->name() + "." + key;
542    detail += " = " + network_event_log::ValueAsString(value);
543    network_event_log::LogLevel log_level = network_event_log::LOG_LEVEL_EVENT;
544    if (key == flimflam::kErrorProperty || key == shill::kErrorDetailsProperty)
545      log_level = network_event_log::LOG_LEVEL_ERROR;
546    else if (key == flimflam::kSignalStrengthProperty ||
547             key == shill::kWifiFrequencyListProperty)
548      log_level = network_event_log::LOG_LEVEL_DEBUG;
549    NET_LOG_LEVEL(log_level, "NetworkPropertyUpdated", detail);
550  }
551  NetworkPropertiesUpdated(network);
552}
553
554void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path,
555                                               const std::string& key,
556                                               const base::Value& value) {
557  DeviceState* device = GetModifiableDeviceState(device_path);
558  if (!device)
559    return;
560  if (!device->PropertyChanged(key, value))
561    return;
562
563  std::string detail = device->name() + "." + key;
564  detail += " = " + network_event_log::ValueAsString(value);
565  NET_LOG_EVENT("DevicePropertyUpdated", detail);
566
567  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
568                    DeviceListChanged());
569
570  if (key == flimflam::kScanningProperty && device->scanning() == false)
571    ScanCompleted(device->type());
572}
573
574void NetworkStateHandler::CheckPortalListChanged(
575    const std::string& check_portal_list) {
576  check_portal_list_ = check_portal_list;
577}
578
579void NetworkStateHandler::NotifyManagerPropertyChanged() {
580  NET_LOG_DEBUG("NotifyManagerPropertyChanged", "");
581  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
582                    NetworkManagerChanged());
583}
584
585void NetworkStateHandler::ManagedStateListChanged(
586    ManagedState::ManagedType type) {
587  if (type == ManagedState::MANAGED_TYPE_NETWORK) {
588    // Notify observers that the list of networks has changed.
589    NET_LOG_EVENT("NetworkListChanged",
590                  base::StringPrintf("Size:%" PRIuS, network_list_.size()));
591    FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
592                      NetworkListChanged());
593    // The list order may have changed, so check if the default network changed.
594    if (CheckDefaultNetworkChanged())
595      OnDefaultNetworkChanged();
596  } else if (type == ManagedState::MANAGED_TYPE_FAVORITE) {
597    NET_LOG_DEBUG("FavoriteListChanged",
598                  base::StringPrintf("Size:%" PRIuS, favorite_list_.size()));
599    FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
600                      NetworkListChanged());
601  } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
602    NET_LOG_DEBUG("DeviceListChanged",
603                  base::StringPrintf("Size:%" PRIuS, device_list_.size()));
604    FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
605                      DeviceListChanged());
606  } else {
607    NOTREACHED();
608  }
609}
610
611//------------------------------------------------------------------------------
612// Private methods
613
614DeviceState* NetworkStateHandler::GetModifiableDeviceState(
615    const std::string& device_path) const {
616  ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
617  if (!managed)
618    return NULL;
619  return managed->AsDeviceState();
620}
621
622NetworkState* NetworkStateHandler::GetModifiableNetworkState(
623    const std::string& service_path) const {
624  ManagedState* managed =
625      GetModifiableManagedState(&network_list_, service_path);
626  if (!managed)
627    return NULL;
628  return managed->AsNetworkState();
629}
630
631ManagedState* NetworkStateHandler::GetModifiableManagedState(
632    const ManagedStateList* managed_list,
633    const std::string& path) const {
634  for (ManagedStateList::const_iterator iter = managed_list->begin();
635       iter != managed_list->end(); ++iter) {
636    ManagedState* managed = *iter;
637    if (managed->path() == path)
638      return managed;
639  }
640  return NULL;
641}
642
643NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
644    ManagedState::ManagedType type) {
645  switch (type) {
646    case ManagedState::MANAGED_TYPE_NETWORK:
647      return &network_list_;
648    case ManagedState::MANAGED_TYPE_FAVORITE:
649      return &favorite_list_;
650    case ManagedState::MANAGED_TYPE_DEVICE:
651      return &device_list_;
652  }
653  NOTREACHED();
654  return NULL;
655}
656
657void NetworkStateHandler::OnNetworkConnectionStateChanged(
658    NetworkState* network) {
659  DCHECK(network);
660  NET_LOG_EVENT("NetworkConnectionStateChanged", base::StringPrintf(
661      "%s:%s", GetManagedStateLogName(network).c_str(),
662      network->connection_state().c_str()));
663  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
664                    NetworkConnectionStateChanged(network));
665  if (CheckDefaultNetworkChanged() || network->path() == default_network_path_)
666    OnDefaultNetworkChanged();
667}
668
669bool NetworkStateHandler::CheckDefaultNetworkChanged() {
670  std::string new_default_network_path;
671  const NetworkState* new_default_network = DefaultNetwork();
672  if (new_default_network)
673    new_default_network_path = new_default_network->path();
674  if (new_default_network_path == default_network_path_)
675    return false;
676  default_network_path_ = new_default_network_path;
677  return true;
678}
679
680void NetworkStateHandler::OnDefaultNetworkChanged() {
681  const NetworkState* default_network = DefaultNetwork();
682  NET_LOG_EVENT("DefaultNetworkChanged",
683                GetManagedStateLogName(default_network));
684  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
685                    DefaultNetworkChanged(default_network));
686}
687
688void NetworkStateHandler::NetworkPropertiesUpdated(
689    const NetworkState* network) {
690  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
691                    NetworkPropertiesUpdated(network));
692  // If |connecting_network_| transitions to a non-idle, non-connecting state,
693  // clear it *after* signalling observers.
694  if (network->path() == connecting_network_ &&
695      !network->IsConnectingState() &&
696      network->connection_state() != flimflam::kStateIdle) {
697    connecting_network_.clear();
698    NET_LOG_EVENT("ClearConnectingNetwork", base::StringPrintf(
699        "%s:%s", GetManagedStateLogName(network).c_str(),
700        network->connection_state().c_str()));
701  }
702}
703
704void NetworkStateHandler::ScanCompleted(const std::string& type) {
705  size_t num_callbacks = scan_complete_callbacks_.count(type);
706  NET_LOG_EVENT("ScanCompleted",
707                base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks));
708  if (num_callbacks == 0)
709    return;
710  ScanCallbackList& callback_list = scan_complete_callbacks_[type];
711  for (ScanCallbackList::iterator iter = callback_list.begin();
712       iter != callback_list.end(); ++iter) {
713    (*iter).Run();
714  }
715  scan_complete_callbacks_.erase(type);
716}
717
718std::string NetworkStateHandler::GetTechnologyForType(
719    const std::string& type) const {
720  if (type == kMatchTypeMobile) {
721    if (shill_property_handler_->IsTechnologyAvailable(flimflam::kTypeWimax))
722      return flimflam::kTypeWimax;
723    else
724      return flimflam::kTypeCellular;
725  }
726  if (type == kMatchTypeDefault || type == kMatchTypeNonVirtual ||
727      type == kMatchTypeWireless) {
728    NOTREACHED();
729    return flimflam::kTypeWifi;
730  }
731  return type;
732}
733
734}  // namespace chromeos
735