network_state_handler.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chromeos/network/network_state_handler.h"
6
7#include "base/stl_util.h"
8#include "base/string_util.h"
9#include "base/values.h"
10#include "chromeos/network/device_state.h"
11#include "chromeos/network/managed_state.h"
12#include "chromeos/network/network_state.h"
13#include "chromeos/network/network_state_handler_observer.h"
14#include "chromeos/network/shill_property_handler.h"
15#include "third_party/cros_system_api/dbus/service_constants.h"
16
17namespace chromeos {
18
19NetworkStateHandler::NetworkStateHandler() {
20}
21
22NetworkStateHandler::~NetworkStateHandler() {
23  STLDeleteContainerPointers(network_list_.begin(), network_list_.end());
24  STLDeleteContainerPointers(device_list_.begin(), device_list_.end());
25}
26
27void NetworkStateHandler::Init() {
28  shill_property_handler_.reset(new internal::ShillPropertyHandler(this));
29  shill_property_handler_->Init();
30}
31
32void NetworkStateHandler::AddObserver(NetworkStateHandlerObserver* observer) {
33  observers_.AddObserver(observer);
34}
35
36void NetworkStateHandler::RemoveObserver(
37    NetworkStateHandlerObserver* observer) {
38  observers_.RemoveObserver(observer);
39}
40
41bool NetworkStateHandler::TechnologyAvailable(
42    const std::string& technology) const {
43  return available_technologies_.find(technology) !=
44      available_technologies_.end();
45}
46
47bool NetworkStateHandler::TechnologyEnabled(
48    const std::string& technology) const {
49  return enabled_technologies_.find(technology) != enabled_technologies_.end();
50}
51
52void NetworkStateHandler::SetTechnologyEnabled(const std::string& technology,
53                                               bool enabled) {
54  shill_property_handler_->SetTechnologyEnabled(technology, enabled);
55}
56
57const DeviceState* NetworkStateHandler::GetDeviceState(
58    const std::string& device_path) const {
59  return GetModifiableDeviceState(device_path);
60}
61
62const DeviceState* NetworkStateHandler::GetDeviceStateByType(
63    const std::string& type) const {
64  for (ManagedStateList::const_iterator iter = device_list_.begin();
65       iter != device_list_.end(); ++iter) {
66    ManagedState* device = *iter;
67    if (device->type() == type)
68      return device->AsDeviceState();
69  }
70  return NULL;
71}
72
73const NetworkState* NetworkStateHandler::GetNetworkState(
74    const std::string& service_path) const {
75  return GetModifiableNetworkState(service_path);
76}
77
78const NetworkState* NetworkStateHandler::ActiveNetwork() const {
79  if (network_list_.empty())
80    return NULL;
81  const NetworkState* network = network_list_.front()->AsNetworkState();
82  DCHECK(network);
83  if (!network->IsConnectedState())
84    return NULL;
85  return network;
86}
87
88const NetworkState* NetworkStateHandler::ConnectedNetworkByType(
89    const std::string& type) const {
90  for (ManagedStateList::const_iterator iter = network_list_.begin();
91       iter != network_list_.end(); ++iter) {
92    const NetworkState* network = (*iter)->AsNetworkState();
93    DCHECK(network);
94    if (!network->IsConnectedState())
95      break;  // Connected networks are listed first.
96    if (network->type() == type)
97      return network;
98  }
99  return NULL;
100}
101
102const NetworkState* NetworkStateHandler::ConnectingNetworkByType(
103    const std::string& type) const {
104  for (ManagedStateList::const_iterator iter = network_list_.begin();
105       iter != network_list_.end(); ++iter) {
106    const NetworkState* network = (*iter)->AsNetworkState();
107    DCHECK(network);
108    if (network->IsConnectedState())
109      continue;
110    if (!network->IsConnectingState())
111      break;  // Connected and connecting networks are listed first.
112    if (network->type() == type ||
113        (type.empty() && type != flimflam::kTypeEthernet)) {
114      return network;
115    }
116  }
117  return NULL;
118}
119
120std::string NetworkStateHandler::HardwareAddressForType(
121    const std::string& type) const {
122  std::string result;
123  const NetworkState* network = ConnectedNetworkByType(type);
124  if (network) {
125    const DeviceState* device = GetDeviceState(network->device_path());
126    if (device)
127      result = device->mac_address();
128  }
129  StringToUpperASCII(&result);
130  return result;
131}
132
133std::string NetworkStateHandler::FormattedHardwareAddressForType(
134    const std::string& type) const {
135  std::string address = HardwareAddressForType(type);
136  if (address.size() % 2 != 0)
137    return address;
138  std::string result;
139  for (size_t i = 0; i < address.size(); ++i) {
140    if ((i != 0) && (i % 2 == 0))
141      result.push_back(':');
142    result.push_back(address[i]);
143  }
144  return result;
145}
146
147void NetworkStateHandler::GetNetworkList(NetworkStateList* list) const {
148  DCHECK(list);
149  shill_property_handler_->RequestScan();
150  NetworkStateList result;
151  list->clear();
152  for (ManagedStateList::const_iterator iter = network_list_.begin();
153       iter != network_list_.end(); ++iter) {
154    const NetworkState* network = (*iter)->AsNetworkState();
155    DCHECK(network);
156    list->push_back(network);
157  }
158}
159
160//------------------------------------------------------------------------------
161// ShillPropertyHandler::Delegate overrides
162
163void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type,
164                                            const base::ListValue& entries) {
165  ManagedStateList* managed_list = GetManagedList(type);
166  VLOG(2) << "UpdateManagedList: " << type;
167  // Create a map of existing entries.
168  std::map<std::string, ManagedState*> managed_map;
169  for (ManagedStateList::iterator iter = managed_list->begin();
170       iter != managed_list->end(); ++iter) {
171    ManagedState* managed = *iter;
172    managed_map[managed->path()] = managed;
173  }
174  // Clear the list (pointers are owned by managed_map).
175  managed_list->clear();
176  // Updates managed_list and request updates for new entries.
177  for (base::ListValue::const_iterator iter = entries.begin();
178       iter != entries.end(); ++iter) {
179    std::string path;
180    (*iter)->GetAsString(&path);
181    DCHECK(!path.empty());
182    std::map<std::string, ManagedState*>::iterator found =
183        managed_map.find(path);
184    bool request_properties = false;
185    ManagedState* managed;
186    bool is_observing = shill_property_handler_->IsObservingNetwork(path);
187    if (found == managed_map.end()) {
188      request_properties = true;
189      managed = ManagedState::Create(type, path);
190      managed_list->push_back(managed);
191    } else {
192      managed = found->second;
193      managed_list->push_back(managed);
194      managed_map.erase(found);
195      if (!managed->is_observed() && is_observing)
196        request_properties = true;
197    }
198    if (is_observing)
199      managed->set_is_observed(true);
200    if (request_properties)
201      shill_property_handler_->RequestProperties(type, path);
202  }
203  // Delete any remaning entries in managed_map.
204  STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
205}
206
207void NetworkStateHandler::UpdateAvailableTechnologies(
208    const base::ListValue& technologies) {
209  available_technologies_.clear();
210  for (base::ListValue::const_iterator iter = technologies.begin();
211       iter != technologies.end(); ++iter) {
212    std::string technology;
213    (*iter)->GetAsString(&technology);
214    DCHECK(!technology.empty());
215    available_technologies_.insert(technology);
216  }
217}
218
219void NetworkStateHandler::UpdateEnabledTechnologies(
220    const base::ListValue& technologies) {
221  enabled_technologies_.clear();
222  for (base::ListValue::const_iterator iter = technologies.begin();
223       iter != technologies.end(); ++iter) {
224    std::string technology;
225    (*iter)->GetAsString(&technology);
226    DCHECK(!technology.empty());
227    enabled_technologies_.insert(technology);
228  }
229}
230
231void NetworkStateHandler::UpdateManagedStateProperties(
232    ManagedState::ManagedType type,
233    const std::string& path,
234    const base::DictionaryValue& properties) {
235  ManagedState* managed = GetModifiableManagedState(GetManagedList(type), path);
236  if (!managed) {
237    LOG(ERROR) << "GetPropertiesCallback: " << path << " Not found!";
238    return;
239  }
240  bool network_property_changed = false;
241  for (base::DictionaryValue::Iterator iter(properties);
242       iter.HasNext(); iter.Advance()) {
243    if (type == ManagedState::MANAGED_TYPE_NETWORK) {
244      if (ParseNetworkServiceProperty(managed->AsNetworkState(),
245                                      iter.key(), iter.value()))
246        network_property_changed = true;
247    } else {
248      managed->PropertyChanged(iter.key(), iter.value());
249    }
250  }
251  // Notify observers.
252  if (network_property_changed) {
253    NetworkState* network = managed->AsNetworkState();
254    DCHECK(network);
255    FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
256                      NetworkServiceChanged(network));
257  }
258}
259
260void NetworkStateHandler::UpdateNetworkServiceProperty(
261    const std::string& service_path,
262    const std::string& key,
263    const base::Value& value) {
264  NetworkState* network = GetModifiableNetworkState(service_path);
265  if (!network)
266    return;
267  if (ParseNetworkServiceProperty(network, key, value)) {
268    FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
269                      NetworkServiceChanged(network));
270  }
271}
272
273void NetworkStateHandler::UpdateNetworkServiceIPAddress(
274    const std::string& service_path,
275    const std::string& ip_address) {
276  NetworkState* network = GetModifiableNetworkState(service_path);
277  if (!network)
278    return;
279  network->set_ip_address(ip_address);
280  FOR_EACH_OBSERVER(
281      NetworkStateHandlerObserver, observers_,
282      NetworkServiceChanged(network));
283}
284
285void NetworkStateHandler::ManagerPropertyChanged() {
286  FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
287                    NetworkManagerChanged());
288}
289
290void NetworkStateHandler::ManagedStateListChanged(
291    ManagedState::ManagedType type) {
292  if (type == ManagedState::MANAGED_TYPE_NETWORK) {
293    // Notify observers that the list of networks has changed.
294    NetworkStateList network_list;
295    GetNetworkList(&network_list);
296    FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
297                      NetworkListChanged(network_list));
298    // Update the active network and notify observers if it has changed.
299    NetworkState* new_active_network =
300        network_list_.empty() ? NULL : network_list_.front()->AsNetworkState();
301    std::string new_active_network_path;
302    if (new_active_network)
303      new_active_network_path = new_active_network->path();
304    if (new_active_network_path != active_network_path_) {
305      active_network_path_ = new_active_network_path;
306      FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
307                        ActiveNetworkChanged(new_active_network));
308    }
309  } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
310    FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
311                      DeviceListChanged());
312  } else {
313    NOTREACHED();
314  }
315}
316
317//------------------------------------------------------------------------------
318// Private methods
319
320DeviceState* NetworkStateHandler::GetModifiableDeviceState(
321    const std::string& device_path) const {
322  ManagedState* managed = GetModifiableManagedState(&device_list_, device_path);
323  if (!managed)
324    return NULL;
325  return managed->AsDeviceState();
326}
327
328NetworkState* NetworkStateHandler::GetModifiableNetworkState(
329    const std::string& service_path) const {
330  ManagedState* managed =
331      GetModifiableManagedState(&network_list_, service_path);
332  if (!managed)
333    return NULL;
334  return managed->AsNetworkState();
335}
336
337ManagedState* NetworkStateHandler::GetModifiableManagedState(
338    const ManagedStateList* managed_list,
339    const std::string& path) const {
340  for (ManagedStateList::const_iterator iter = managed_list->begin();
341       iter != managed_list->end(); ++iter) {
342    ManagedState* managed = *iter;
343    if (managed->path() == path)
344      return managed;
345  }
346  return NULL;
347}
348
349NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList(
350    ManagedState::ManagedType type) {
351  switch(type) {
352    case ManagedState::MANAGED_TYPE_NETWORK:
353      return &network_list_;
354    case ManagedState::MANAGED_TYPE_DEVICE:
355      return &device_list_;
356  }
357  NOTREACHED();
358  return NULL;
359}
360
361bool NetworkStateHandler::ParseNetworkServiceProperty(
362    NetworkState* network,
363    const std::string& key,
364    const base::Value& value) {
365  DCHECK(network);
366  bool property_changed = false;
367  if (key == shill::kIPConfigProperty) {
368    // Handle IPConfig here instead of in NetworkState::PropertyChanged since
369    // we need to call into shill_property_handler_ to fetch them. This will
370    // trigger a call to UpdateNetworkServiceIPAddress(), which will notify
371    // any observers.
372    std::string ip_config_path;
373    value.GetAsString(&ip_config_path);
374    DCHECK(!ip_config_path.empty());
375    shill_property_handler_->RequestIPConfig(network->path(), ip_config_path);
376  } else {
377    if (network->PropertyChanged(key, value)) {
378      property_changed = true;
379      if (network->path() == active_network_path_ &&
380          key == flimflam::kStateProperty) {
381        FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
382                          ActiveNetworkStateChanged(network));
383      }
384    }
385  }
386  return property_changed;
387}
388
389}  // namespace chromeos
390