15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/network_state_handler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/format_macros.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/guid.h"
107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/location.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h"
12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/metrics/histogram.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/device_state.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/managed_state.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/network/network_event_log.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/network_state.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/network_state_handler_observer.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/shill_property_handler.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochnamespace chromeos {
262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochbool ConnectionStateChanged(NetworkState* network,
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            const std::string& prev_connection_state) {
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return (network->connection_state() != prev_connection_state) &&
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)         (network->connection_state() != shill::kStateIdle ||
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          !prev_connection_state.empty());
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochstd::string GetManagedStateLogType(const ManagedState* state) {
372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  switch (state->managed_type()) {
382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    case ManagedState::MANAGED_TYPE_NETWORK:
392385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      return "Network";
402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    case ManagedState::MANAGED_TYPE_DEVICE:
412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      return "Device";
422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
432385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  NOTREACHED();
442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return "";
452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)std::string GetLogName(const ManagedState* state) {
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!state)
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return "None";
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return base::StringPrintf("%s (%s)", state->name().c_str(),
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            state->path().c_str());
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char NetworkStateHandler::kDefaultCheckPortalList[] =
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    "ethernet,wifi,cellular";
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)NetworkStateHandler::NetworkStateHandler()
606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    : network_list_sorted_(false) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkStateHandler::~NetworkStateHandler() {
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, IsShuttingDown());
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPointers(network_list_.begin(), network_list_.end());
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPointers(device_list_.begin(), device_list_.end());
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NetworkStateHandler::InitShillPropertyHandler() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shill_property_handler_->Init();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)NetworkStateHandler* NetworkStateHandler::InitializeForTest() {
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NetworkStateHandler* handler = new NetworkStateHandler();
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  handler->InitShillPropertyHandler();
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return handler;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void NetworkStateHandler::AddObserver(
827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    NetworkStateHandlerObserver* observer,
837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const tracked_objects::Location& from_here) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.AddObserver(observer);
857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  network_event_log::internal::AddEntry(
867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      from_here.file_name(), from_here.line_number(),
877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      network_event_log::LOG_LEVEL_DEBUG,
887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      "NetworkStateHandler::AddObserver", "");
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkStateHandler::RemoveObserver(
927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    NetworkStateHandlerObserver* observer,
937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const tracked_objects::Location& from_here) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.RemoveObserver(observer);
957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  network_event_log::internal::AddEntry(
967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      from_here.file_name(), from_here.line_number(),
977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      network_event_log::LOG_LEVEL_DEBUG,
987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      "NetworkStateHandler::RemoveObserver", "");
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)NetworkStateHandler::TechnologyState NetworkStateHandler::GetTechnologyState(
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const NetworkTypePattern& type) const {
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string technology = GetTechnologyForType(type);
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TechnologyState state;
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (shill_property_handler_->IsTechnologyEnabled(technology))
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state = TECHNOLOGY_ENABLED;
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else if (shill_property_handler_->IsTechnologyEnabling(technology))
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state = TECHNOLOGY_ENABLING;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else if (shill_property_handler_->IsTechnologyUninitialized(technology))
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state = TECHNOLOGY_UNINITIALIZED;
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else if (shill_property_handler_->IsTechnologyAvailable(technology))
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state = TECHNOLOGY_AVAILABLE;
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state = TECHNOLOGY_UNAVAILABLE;
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  VLOG(2) << "GetTechnologyState: " << type.ToDebugString() << " = " << state;
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return state;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NetworkStateHandler::SetTechnologyEnabled(
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const NetworkTypePattern& type,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool enabled,
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const network_handler::ErrorCallback& error_callback) {
1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ScopedVector<std::string> technologies = GetTechnologiesForType(type);
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (ScopedVector<std::string>::iterator it = technologies.begin();
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      it != technologies.end(); ++it) {
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    std::string* technology = *it;
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(technology);
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!shill_property_handler_->IsTechnologyAvailable(*technology))
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      continue;
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    NET_LOG_USER("SetTechnologyEnabled",
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 base::StringPrintf("%s:%d", technology->c_str(), enabled));
1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    shill_property_handler_->SetTechnologyEnabled(
1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        *technology, enabled, error_callback);
1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
135d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Signal Device/Technology state changed.
136d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  NotifyDeviceListChanged();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const DeviceState* NetworkStateHandler::GetDeviceState(
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& device_path) const {
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const DeviceState* device = GetModifiableDeviceState(device_path);
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (device && !device->update_received())
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return device;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const DeviceState* NetworkStateHandler::GetDeviceStateByType(
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const NetworkTypePattern& type) const {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ManagedStateList::const_iterator iter = device_list_.begin();
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != device_list_.end(); ++iter) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ManagedState* device = *iter;
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!device->update_received())
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      continue;
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (device->Matches(type))
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return device->AsDeviceState();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool NetworkStateHandler::GetScanningByType(
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const NetworkTypePattern& type) const {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ManagedStateList::const_iterator iter = device_list_.begin();
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != device_list_.end(); ++iter) {
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DeviceState* device = (*iter)->AsDeviceState();
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(device);
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!device->update_received())
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      continue;
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (device->Matches(type) && device->scanning())
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const NetworkState* NetworkStateHandler::GetNetworkState(
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& service_path) const {
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const NetworkState* network = GetModifiableNetworkState(service_path);
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (network && !network->update_received())
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return network;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const NetworkState* NetworkStateHandler::DefaultNetwork() const {
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (default_network_path_.empty())
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetNetworkState(default_network_path_);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const NetworkState* NetworkStateHandler::ConnectedNetworkByType(
18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const NetworkTypePattern& type) const {
1906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Active networks are always listed first by Shill so no need to sort.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ManagedStateList::const_iterator iter = network_list_.begin();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != network_list_.end(); ++iter) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const NetworkState* network = (*iter)->AsNetworkState();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(network);
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!network->update_received())
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      continue;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!network->IsConnectedState())
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;  // Connected networks are listed first.
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (network->Matches(type))
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return network;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const NetworkState* NetworkStateHandler::ConnectingNetworkByType(
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const NetworkTypePattern& type) const {
2076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Active networks are always listed first by Shill so no need to sort.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ManagedStateList::const_iterator iter = network_list_.begin();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != network_list_.end(); ++iter) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const NetworkState* network = (*iter)->AsNetworkState();
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(network);
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!network->update_received() || network->IsConnectedState())
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!network->IsConnectingState())
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;  // Connected and connecting networks are listed first.
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (network->Matches(type))
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return network;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return NULL;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const NetworkState* NetworkStateHandler::FirstNetworkByType(
2236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const NetworkTypePattern& type) {
2246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (!network_list_sorted_)
2256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    SortNetworkList();  // Sort to ensure visible networks are listed first.
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ManagedStateList::const_iterator iter = network_list_.begin();
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != network_list_.end(); ++iter) {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const NetworkState* network = (*iter)->AsNetworkState();
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(network);
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!network->update_received())
23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      continue;
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!network->visible())
2336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      break;
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (network->Matches(type))
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return network;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string NetworkStateHandler::FormattedHardwareAddressForType(
24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const NetworkTypePattern& type) const {
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const DeviceState* device = NULL;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const NetworkState* network = ConnectedNetworkByType(type);
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (network)
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    device = GetDeviceState(network->device_path());
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  else
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    device = GetDeviceStateByType(type);
24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!device)
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return std::string();
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return network_util::FormattedMacAddress(device->mac_address());
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void NetworkStateHandler::GetVisibleNetworkListByType(
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const NetworkTypePattern& type,
2556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    NetworkStateList* list) {
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GetNetworkListByType(type,
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       false /* configured_only */,
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       true /* visible_only */,
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       0 /* no limit */,
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       list);
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void NetworkStateHandler::GetVisibleNetworkList(NetworkStateList* list) {
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GetVisibleNetworkListByType(NetworkTypePattern::Default(), list);
265424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
266424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type,
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                               bool configured_only,
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                               bool visible_only,
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                               int limit,
2716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                               NetworkStateList* list) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(list);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  list->clear();
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int count = 0;
2756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Sort the network list if necessary.
2766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (!network_list_sorted_)
2776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    SortNetworkList();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ManagedStateList::const_iterator iter = network_list_.begin();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != network_list_.end(); ++iter) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const NetworkState* network = (*iter)->AsNetworkState();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(network);
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!network->update_received() || !network->Matches(type))
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continue;
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (configured_only && !network->IsInProfile())
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continue;
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (visible_only && !network->visible())
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continue;
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    list->push_back(network);
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (limit > 0 && ++count >= limit)
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const NetworkState* NetworkStateHandler::GetNetworkStateFromServicePath(
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& service_path,
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool configured_only) const {
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ManagedState* managed =
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GetModifiableManagedState(&network_list_, service_path);
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!managed)
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return NULL;
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const NetworkState* network = managed->AsNetworkState();
302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(network);
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!network->update_received() ||
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      (configured_only && !network->IsInProfile())) {
3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return network;
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const NetworkState* NetworkStateHandler::GetNetworkStateFromGuid(
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& guid) const {
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!guid.empty());
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (ManagedStateList::const_iterator iter = network_list_.begin();
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       iter != network_list_.end(); ++iter) {
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const NetworkState* network = (*iter)->AsNetworkState();
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (network->guid() == guid)
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return network;
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return NULL;
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const {
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GetDeviceListByType(NetworkTypePattern::Default(), list);
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type,
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                              DeviceStateList* list) const {
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(list);
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  list->clear();
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (ManagedStateList::const_iterator iter = device_list_.begin();
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       iter != device_list_.end(); ++iter) {
332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const DeviceState* device = (*iter)->AsDeviceState();
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK(device);
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (device->update_received() && device->Matches(type))
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      list->push_back(device);
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NetworkStateHandler::RequestScan() const {
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NET_LOG_USER("RequestScan", "");
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  shill_property_handler_->RequestScan();
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NetworkStateHandler::WaitForScan(const std::string& type,
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const base::Closure& callback) {
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scan_complete_callbacks_[type].push_back(callback);
34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!GetScanningByType(NetworkTypePattern::Primitive(type)))
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RequestScan();
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NetworkStateHandler::ConnectToBestWifiNetwork() {
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NET_LOG_USER("ConnectToBestWifiNetwork", "");
35368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  WaitForScan(shill::kTypeWifi,
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices,
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         shill_property_handler_->AsWeakPtr()));
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void NetworkStateHandler::RequestUpdateForNetwork(
35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& service_path) {
36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NetworkState* network = GetModifiableNetworkState(service_path);
3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (network)
3623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    network->set_update_requested(true);
36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NET_LOG_EVENT("RequestUpdate", service_path);
36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  shill_property_handler_->RequestProperties(
36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      ManagedState::MANAGED_TYPE_NETWORK, service_path);
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
36790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NetworkStateHandler::ClearLastErrorForNetwork(
369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& service_path) {
370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NetworkState* network = GetModifiableNetworkState(service_path);
371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (network)
372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    network->clear_last_error();
373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void NetworkStateHandler::SetCheckPortalList(
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& check_portal_list) {
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  shill_property_handler_->SetCheckPortalList(check_portal_list);
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const NetworkState* NetworkStateHandler::GetEAPForEthernet(
3826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    const std::string& service_path) {
3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const NetworkState* network = GetNetworkState(service_path);
3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!network) {
3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path);
3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (network->type() != shill::kTypeEthernet) {
3894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path);
3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
3914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!network->IsConnectedState())
3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // The same EAP service is shared for all ethernet services/devices.
3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // However EAP is used/enabled per device and only if the connection was
3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // successfully established.
3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const DeviceState* device = GetDeviceState(network->device_path());
3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!device) {
4004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    NET_LOG_ERROR(
4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        "GetEAPForEthernet",
4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::StringPrintf("Unknown device %s of connected ethernet service %s",
4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           network->device_path().c_str(),
4044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           service_path.c_str()));
4054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!device->eap_authentication_completed())
4084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
410f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NetworkStateList list;
411f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GetNetworkListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap),
412f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       true /* configured_only */,
413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       false /* visible_only */,
414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       1 /* limit */,
415f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       &list);
4164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (list.empty()) {
4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    NET_LOG_ERROR("GetEAPForEthernet",
4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                  base::StringPrintf(
4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                      "Ethernet service %s connected using EAP, but no "
4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                      "EAP service found.",
4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                      service_path.c_str()));
4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return list.front();
4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ShillPropertyHandler::Delegate overrides
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type,
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const base::ListValue& entries) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ManagedStateList* managed_list = GetManagedList(type);
433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NET_LOG_DEBUG("UpdateManagedList: " + ManagedState::TypeToString(type),
434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                base::StringPrintf("%" PRIuS, entries.GetSize()));
4357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Create a map of existing entries. Assumes all entries in |managed_list|
4367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // are unique.
437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  typedef std::map<std::string, ManagedState*> ManagedMap;
438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ManagedMap managed_map;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ManagedStateList::iterator iter = managed_list->begin();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != managed_list->end(); ++iter) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ManagedState* managed = *iter;
4427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DCHECK(!ContainsKey(managed_map, managed->path()));
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    managed_map[managed->path()] = managed;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Clear the list (pointers are temporarily owned by managed_map).
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  managed_list->clear();
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Updates managed_list and request updates for new entries.
4487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::set<std::string> list_entries;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (base::ListValue::const_iterator iter = entries.begin();
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != entries.end(); ++iter) {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string path;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*iter)->GetAsString(&path);
453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (path.empty() || path == shill::kFlimflamServicePath) {
454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path);
4557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      continue;
4567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
457f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ManagedMap::iterator found = managed_map.find(path);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (found == managed_map.end()) {
4597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if (list_entries.count(path) != 0) {
460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        NET_LOG_ERROR("Duplicate entry in list", path);
4617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        continue;
4627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      }
463f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ManagedState* managed = ManagedState::Create(type, path);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      managed_list->push_back(managed);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
466f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      managed_list->push_back(found->second);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      managed_map.erase(found);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    list_entries.insert(path);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
471ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Delete any remaining entries in managed_map.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NetworkStateHandler::ProfileListChanged() {
47690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (ManagedStateList::iterator iter = network_list_.begin();
478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       iter != network_list_.end(); ++iter) {
479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    NetworkState* network = (*iter)->AsNetworkState();
480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK(network);
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    shill_property_handler_->RequestProperties(
482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        ManagedState::MANAGED_TYPE_NETWORK, network->path());
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkStateHandler::UpdateManagedStateProperties(
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ManagedState::ManagedType type,
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& path,
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue& properties) {
4902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ManagedStateList* managed_list = GetManagedList(type);
4912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ManagedState* managed = GetModifiableManagedState(managed_list, path);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!managed) {
493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // The network has been removed from the list of networks.
494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path);
495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
4962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
4972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  managed->set_update_received();
4982385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
499effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  std::string desc = GetManagedStateLogType(managed) + " Properties Received";
500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NET_LOG_DEBUG(desc, GetLogName(managed));
5012385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
5022385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (type == ManagedState::MANAGED_TYPE_NETWORK) {
5032385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    UpdateNetworkStateProperties(managed->AsNetworkState(), properties);
5042385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  } else {
505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Device
5062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    for (base::DictionaryValue::Iterator iter(properties);
5072385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch         !iter.IsAtEnd(); iter.Advance()) {
5082385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      managed->PropertyChanged(iter.key(), iter.value());
5092385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    }
5102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    managed->InitialPropertiesReceived(properties);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5122385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  managed->set_update_requested(false);
5132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
5142385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
5152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid NetworkStateHandler::UpdateNetworkStateProperties(
5162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    NetworkState* network,
5172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const base::DictionaryValue& properties) {
5182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DCHECK(network);
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool network_property_updated = false;
5202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  std::string prev_connection_state = network->connection_state();
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (base::DictionaryValue::Iterator iter(properties);
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       !iter.IsAtEnd(); iter.Advance()) {
5232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    if (network->PropertyChanged(iter.key(), iter.value()))
5242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      network_property_updated = true;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  network_property_updated |= network->InitialPropertiesReceived(properties);
5276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  UpdateGuid(network);
5286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  network_list_sorted_ = false;
5296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
5302385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Notify observers of NetworkState changes.
5312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (network_property_updated || network->update_requested()) {
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Signal connection state changed after all properties have been updated.
5332385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    if (ConnectionStateChanged(network, prev_connection_state))
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OnNetworkConnectionStateChanged(network);
535f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    NET_LOG_EVENT("NetworkPropertiesUpdated", GetLogName(network));
536a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NotifyNetworkPropertiesUpdated(network);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkStateHandler::UpdateNetworkServiceProperty(
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& service_path,
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& key,
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Value& value) {
5444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool changed = false;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkState* network = GetModifiableNetworkState(service_path);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!network)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string prev_connection_state = network->connection_state();
549ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string prev_profile_path = network->profile_path();
5504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  changed |= network->PropertyChanged(key, value);
5514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!changed)
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (key == shill::kStateProperty || key == shill::kVisibleProperty) {
5556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    network_list_sorted_ = false;
556ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (ConnectionStateChanged(network, prev_connection_state)) {
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      OnNetworkConnectionStateChanged(network);
558ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // If the connection state changes, other properties such as IPConfig
559ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // may have changed, so request a full update.
560ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      RequestUpdateForNetwork(service_path);
561ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
5634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    std::string value_str;
5644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    value.GetAsString(&value_str);
5654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Some property changes are noisy and not interesting:
5664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // * Wifi SignalStrength
5674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // * WifiFrequencyList updates
5684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // * Device property changes to "/" (occurs before a service is removed)
5694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (key != shill::kSignalStrengthProperty &&
5704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        key != shill::kWifiFrequencyListProperty &&
5714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        (key != shill::kDeviceProperty || value_str != "/")) {
572a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      std::string log_event = "NetworkPropertyUpdated";
5734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Trigger a default network update for interesting changes only.
574a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (network->path() == default_network_path_) {
575a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        NotifyDefaultNetworkChanged(network);
576a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        log_event = "Default" + log_event;
577a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Log event.
579ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      std::string detail = network->name() + "." + key;
580ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      detail += " = " + network_event_log::ValueAsString(value);
581ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      network_event_log::LogLevel log_level;
58268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) {
583ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        log_level = network_event_log::LOG_LEVEL_ERROR;
584ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      } else {
585ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        log_level = network_event_log::LOG_LEVEL_EVENT;
586ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
587a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NET_LOG_LEVEL(log_level, log_event, detail);
588ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
5904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // All property updates signal 'NetworkPropertiesUpdated'.
592a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NotifyNetworkPropertiesUpdated(network);
5934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
594f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If added to a Profile, request a full update so that a NetworkState
5954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // gets created.
5964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (prev_profile_path.empty() && !network->profile_path().empty())
5974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    RequestUpdateForNetwork(service_path);
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path,
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               const std::string& key,
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               const base::Value& value) {
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DeviceState* device = GetModifiableDeviceState(device_path);
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!device)
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!device->PropertyChanged(key, value))
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string detail = device->name() + "." + key;
61090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  detail += " = " + network_event_log::ValueAsString(value);
61190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NET_LOG_EVENT("DevicePropertyUpdated", detail);
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
613d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  NotifyDeviceListChanged();
614116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  NotifyDevicePropertiesUpdated(device);
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
61668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (key == shill::kScanningProperty && device->scanning() == false)
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ScanCompleted(device->type());
6184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (key == shill::kEapAuthenticationCompletedProperty) {
6194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Notify a change for each Ethernet service using this device.
6204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    NetworkStateList ethernet_services;
621f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    GetNetworkListByType(NetworkTypePattern::Ethernet(),
622f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         false /* configured_only */,
623f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         false /* visible_only */,
624f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         0 /* no limit */,
625f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         &ethernet_services);
6264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (NetworkStateList::const_iterator it = ethernet_services.begin();
6274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         it != ethernet_services.end(); ++it) {
6284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const NetworkState* ethernet_service = *it;
6294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (ethernet_service->update_received() ||
6304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          ethernet_service->device_path() != device->path()) {
6314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        continue;
6324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
6334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      RequestUpdateForNetwork(ethernet_service->path());
6344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
6354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
638010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void NetworkStateHandler::UpdateIPConfigProperties(
639010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ManagedState::ManagedType type,
640010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::string& path,
641010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::string& ip_config_path,
642010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const base::DictionaryValue& properties)  {
643010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (type == ManagedState::MANAGED_TYPE_NETWORK) {
644010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    NetworkState* network = GetModifiableNetworkState(path);
645010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!network)
646010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
647010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    network->IPConfigPropertiesChanged(properties);
648116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    NotifyNetworkPropertiesUpdated(network);
649f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (network->path() == default_network_path_)
650f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      NotifyDefaultNetworkChanged(network);
651010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
652010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DeviceState* device = GetModifiableDeviceState(path);
653010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!device)
654010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return;
655010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    device->IPConfigPropertiesChanged(ip_config_path, properties);
656116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    NotifyDevicePropertiesUpdated(device);
657f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!default_network_path_.empty()) {
658f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      const NetworkState* default_network =
659f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          GetNetworkState(default_network_path_);
660f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (default_network && default_network->device_path() == path)
661f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        NotifyDefaultNetworkChanged(default_network);
662f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
663010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
664010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
665010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void NetworkStateHandler::CheckPortalListChanged(
667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& check_portal_list) {
668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  check_portal_list_ = check_portal_list;
669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
671d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void NetworkStateHandler::TechnologyListChanged() {
672d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Eventually we would like to replace Technology state with Device state.
673d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // For now, treat technology state changes as device list changes.
674d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  NotifyDeviceListChanged();
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkStateHandler::ManagedStateListChanged(
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ManagedState::ManagedType type) {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == ManagedState::MANAGED_TYPE_NETWORK) {
6806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    SortNetworkList();
6816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    UpdateNetworkStats();
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Notify observers that the list of networks has changed.
683f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    NET_LOG_EVENT("NOTIFY:NetworkListChanged",
684a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  base::StringPrintf("Size:%" PRIuS, network_list_.size()));
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      NetworkListChanged());
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
688cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::string devices;
689cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (ManagedStateList::const_iterator iter = device_list_.begin();
690cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         iter != device_list_.end(); ++iter) {
691cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (iter != device_list_.begin())
692cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        devices += ", ";
693cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      devices += (*iter)->name();
694cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
695f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    NET_LOG_EVENT("DeviceList", devices);
696d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    NotifyDeviceListChanged();
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void NetworkStateHandler::SortNetworkList() {
703116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Note: usually active networks will precede inactive networks, however
704116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // this may briefly be untrue during state transitions (e.g. a network may
705116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // transition to idle before the list is updated).
7066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  ManagedStateList active, non_wifi_visible, wifi_visible, hidden, new_networks;
7076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (ManagedStateList::iterator iter = network_list_.begin();
7086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)       iter != network_list_.end(); ++iter) {
7096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    NetworkState* network = (*iter)->AsNetworkState();
7106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (!network->update_received()) {
7116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      new_networks.push_back(network);
7126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      continue;
7136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
7146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (network->IsConnectedState() || network->IsConnectingState()) {
7156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      active.push_back(network);
7166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      continue;
7176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
7186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (network->visible()) {
7196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      if (NetworkTypePattern::WiFi().MatchesType(network->type()))
7206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        wifi_visible.push_back(network);
7216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      else
7226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        non_wifi_visible.push_back(network);
7236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    } else {
7246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      hidden.push_back(network);
7256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
7266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
7276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  network_list_.clear();
7286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  network_list_.insert(network_list_.end(), active.begin(), active.end());
7296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  network_list_.insert(
7306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      network_list_.end(), non_wifi_visible.begin(), non_wifi_visible.end());
7316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  network_list_.insert(
7326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      network_list_.end(), wifi_visible.begin(), wifi_visible.end());
7336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  network_list_.insert(network_list_.end(), hidden.begin(), hidden.end());
7346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  network_list_.insert(
7356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      network_list_.end(), new_networks.begin(), new_networks.end());
7366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  network_list_sorted_ = true;
7376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
7386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
7396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void NetworkStateHandler::UpdateNetworkStats() {
7406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  size_t shared = 0, unshared = 0, visible = 0;
7416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (ManagedStateList::iterator iter = network_list_.begin();
7426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)       iter != network_list_.end(); ++iter) {
7436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    NetworkState* network = (*iter)->AsNetworkState();
7446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (network->visible())
7456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      ++visible;
7466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (network->IsInProfile()) {
7476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      if (network->IsPrivate())
7486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        ++unshared;
7496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      else
7506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        ++shared;
7516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
7526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
7536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS_100("Networks.Visible", visible);
7546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared);
7556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared);
7566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
7576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
758a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NetworkStateHandler::DefaultNetworkServiceChanged(
759a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& service_path) {
760a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Shill uses '/' for empty service path values; check explicitly for that.
761a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const char* kEmptyServicePath = "/";
762f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string new_service_path =
763f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      (service_path != kEmptyServicePath) ? service_path : "";
764f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (new_service_path == default_network_path_)
765f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
766f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
767f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  default_network_path_ = service_path;
768a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_);
769a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const NetworkState* network = NULL;
770a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!default_network_path_.empty()) {
771a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    network = GetNetworkState(default_network_path_);
772a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!network) {
773a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // If NetworkState is not available yet, do not notify observers here,
774a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // they will be notified when the state is received.
775a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NET_LOG_DEBUG("Default NetworkState not available",
776a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    default_network_path_);
777a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
778a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
779a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
780a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (network && !network->IsConnectedState()) {
781a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NET_LOG_ERROR(
782a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        "DefaultNetwork is not connected: " + network->connection_state(),
783a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        network->path());
784a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
785a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NotifyDefaultNetworkChanged(network);
786a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
787a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Private methods
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
791f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void NetworkStateHandler::UpdateGuid(NetworkState* network) {
792f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string specifier = network->GetSpecifier();
793f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(!specifier.empty());
794f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!network->guid().empty()) {
795f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // If the network is saved in a profile, remove the entry from the map.
796f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Otherwise ensure that the entry matches the specified GUID. (e.g. in
797f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // case a visible network with a specified guid gets configured with a
798f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // new guid).
799f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (network->IsInProfile())
800f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      specifier_guid_map_.erase(specifier);
801f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    else
802f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      specifier_guid_map_[specifier] = network->guid();
803f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
804f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
805f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Ensure that the NetworkState has a valid GUID.
806f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string guid;
807f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  SpecifierGuidMap::iterator iter = specifier_guid_map_.find(specifier);
808f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (iter != specifier_guid_map_.end()) {
809f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    guid = iter->second;
810f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
811f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    guid = base::GenerateGUID();
812f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    specifier_guid_map_[specifier] = guid;
813cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
814f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  network->SetGuid(guid);
815cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
816cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
817d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void NetworkStateHandler::NotifyDeviceListChanged() {
818f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NET_LOG_DEBUG("NOTIFY:DeviceListChanged",
819d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                base::StringPrintf("Size:%" PRIuS, device_list_.size()));
820d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
821d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    DeviceListChanged());
822d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
823d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceState* NetworkStateHandler::GetModifiableDeviceState(
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& device_path) const {
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!managed)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return managed->AsDeviceState();
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkState* NetworkStateHandler::GetModifiableNetworkState(
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& service_path) const {
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ManagedState* managed =
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetModifiableManagedState(&network_list_, service_path);
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!managed)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return managed->AsNetworkState();
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ManagedState* NetworkStateHandler::GetModifiableManagedState(
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ManagedStateList* managed_list,
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& path) const {
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ManagedStateList::const_iterator iter = managed_list->begin();
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != managed_list->end(); ++iter) {
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ManagedState* managed = *iter;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (managed->path() == path)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return managed;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ManagedState::ManagedType type) {
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ManagedState::MANAGED_TYPE_NETWORK:
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &network_list_;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ManagedState::MANAGED_TYPE_DEVICE:
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &device_list_;
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NetworkStateHandler::OnNetworkConnectionStateChanged(
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NetworkState* network) {
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(network);
868a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string event = "NetworkConnectionStateChanged";
869a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (network->path() == default_network_path_) {
870a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    event = "Default" + event;
871a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!network->IsConnectedState()) {
872116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      NET_LOG_EVENT(
873a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          "DefaultNetwork is not connected: " + network->connection_state(),
874a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          network->path());
875116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      default_network_path_.clear();
876116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SortNetworkList();
877116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      NotifyDefaultNetworkChanged(NULL);
878a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
879a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
880f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NET_LOG_EVENT("NOTIFY:" + event + ": " + network->connection_state(),
881f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                GetLogName(network));
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    NetworkConnectionStateChanged(network));
884a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (network->path() == default_network_path_)
885a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NotifyDefaultNetworkChanged(network);
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
888a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NetworkStateHandler::NotifyDefaultNetworkChanged(
889a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const NetworkState* default_network) {
890f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NET_LOG_EVENT("NOTIFY:DefaultNetworkChanged", GetLogName(default_network));
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    DefaultNetworkChanged(default_network));
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
895a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const NetworkState* network) {
897f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NET_LOG_DEBUG("NOTIFY:NetworkPropertiesUpdated", GetLogName(network));
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    NetworkPropertiesUpdated(network));
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
902116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid NetworkStateHandler::NotifyDevicePropertiesUpdated(
903116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const DeviceState* device) {
904116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  NET_LOG_DEBUG("NOTIFY:DevicePropertiesUpdated", GetLogName(device));
905116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
906116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    DevicePropertiesUpdated(device));
907116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
908116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
909c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NetworkStateHandler::ScanCompleted(const std::string& type) {
910c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t num_callbacks = scan_complete_callbacks_.count(type);
91190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NET_LOG_EVENT("ScanCompleted",
912a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks));
913c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (num_callbacks == 0)
914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
915c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ScanCallbackList& callback_list = scan_complete_callbacks_[type];
916c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (ScanCallbackList::iterator iter = callback_list.begin();
917c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       iter != callback_list.end(); ++iter) {
918c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    (*iter).Run();
919c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
920c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scan_complete_callbacks_.erase(type);
921c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
922c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
923c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string NetworkStateHandler::GetTechnologyForType(
92458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const NetworkTypePattern& type) const {
92568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (type.MatchesType(shill::kTypeEthernet))
92668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return shill::kTypeEthernet;
92758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
92868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (type.MatchesType(shill::kTypeWifi))
92968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return shill::kTypeWifi;
93058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
93158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (type.Equals(NetworkTypePattern::Wimax()))
93268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return shill::kTypeWimax;
93358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
93458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Prefer Wimax over Cellular only if it's available.
93568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (type.MatchesType(shill::kTypeWimax) &&
93668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) {
93768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return shill::kTypeWimax;
938c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
93958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
94068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (type.MatchesType(shill::kTypeCellular))
94168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return shill::kTypeCellular;
94258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
94358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NOTREACHED();
94458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return std::string();
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuScopedVector<std::string> NetworkStateHandler::GetTechnologiesForType(
9485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const NetworkTypePattern& type) const {
9495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ScopedVector<std::string> technologies;
9505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (type.MatchesType(shill::kTypeEthernet))
9515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    technologies.push_back(new std::string(shill::kTypeEthernet));
9525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (type.MatchesType(shill::kTypeWifi))
9535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    technologies.push_back(new std::string(shill::kTypeWifi));
9545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (type.MatchesType(shill::kTypeWimax))
9555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    technologies.push_back(new std::string(shill::kTypeWimax));
9565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (type.MatchesType(shill::kTypeCellular))
9575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    technologies.push_back(new std::string(shill::kTypeCellular));
9585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (type.MatchesType(shill::kTypeBluetooth))
9595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    technologies.push_back(new std::string(shill::kTypeBluetooth));
9605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (type.MatchesType(shill::kTypeVPN))
9615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    technologies.push_back(new std::string(shill::kTypeVPN));
9625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
9635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_GT(technologies.size(), 0ul);
9645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return technologies.Pass();
9655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
9665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
968