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