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.
5 #include "chromeos/network/network_state_handler.h"
7 #include "base/format_macros.h"
8 #include "base/stl_util.h"
9 #include "base/string_util.h"
10 #include "base/stringprintf.h"
11 #include "base/values.h"
12 #include "chromeos/network/device_state.h"
13 #include "chromeos/network/managed_state.h"
14 #include "chromeos/network/network_event_log.h"
15 #include "chromeos/network/network_state.h"
16 #include "chromeos/network/network_state_handler_observer.h"
17 #include "chromeos/network/shill_property_handler.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
21 const char kLogModule
[] = "NetworkPropertyHandler";
26 static NetworkStateHandler
* g_network_state_handler
= NULL
;
28 NetworkStateHandler::NetworkStateHandler() {
31 NetworkStateHandler::~NetworkStateHandler() {
32 STLDeleteContainerPointers(network_list_
.begin(), network_list_
.end());
33 STLDeleteContainerPointers(device_list_
.begin(), device_list_
.end());
36 void NetworkStateHandler::InitShillPropertyHandler() {
37 shill_property_handler_
.reset(new internal::ShillPropertyHandler(this));
38 shill_property_handler_
->Init();
42 void NetworkStateHandler::Initialize() {
43 CHECK(!g_network_state_handler
);
44 g_network_state_handler
= new NetworkStateHandler();
45 g_network_state_handler
->InitShillPropertyHandler();
49 void NetworkStateHandler::Shutdown() {
50 CHECK(g_network_state_handler
);
51 delete g_network_state_handler
;
52 g_network_state_handler
= NULL
;
56 NetworkStateHandler
* NetworkStateHandler::Get() {
57 CHECK(g_network_state_handler
)
58 << "NetworkStateHandler::Get() called before Initialize()";
59 return g_network_state_handler
;
62 void NetworkStateHandler::AddObserver(NetworkStateHandlerObserver
* observer
) {
63 observers_
.AddObserver(observer
);
66 void NetworkStateHandler::RemoveObserver(
67 NetworkStateHandlerObserver
* observer
) {
68 observers_
.RemoveObserver(observer
);
71 bool NetworkStateHandler::TechnologyAvailable(
72 const std::string
& technology
) const {
73 return available_technologies_
.find(technology
) !=
74 available_technologies_
.end();
77 bool NetworkStateHandler::TechnologyEnabled(
78 const std::string
& technology
) const {
79 return enabled_technologies_
.find(technology
) != enabled_technologies_
.end();
82 void NetworkStateHandler::SetTechnologyEnabled(
83 const std::string
& technology
,
85 const network_handler::ErrorCallback
& error_callback
) {
86 shill_property_handler_
->SetTechnologyEnabled(
87 technology
, enabled
, error_callback
);
90 const DeviceState
* NetworkStateHandler::GetDeviceState(
91 const std::string
& device_path
) const {
92 return GetModifiableDeviceState(device_path
);
95 const DeviceState
* NetworkStateHandler::GetDeviceStateByType(
96 const std::string
& type
) const {
97 for (ManagedStateList::const_iterator iter
= device_list_
.begin();
98 iter
!= device_list_
.end(); ++iter
) {
99 ManagedState
* device
= *iter
;
100 if (device
->type() == type
)
101 return device
->AsDeviceState();
106 const NetworkState
* NetworkStateHandler::GetNetworkState(
107 const std::string
& service_path
) const {
108 return GetModifiableNetworkState(service_path
);
111 const NetworkState
* NetworkStateHandler::ActiveNetwork() const {
112 if (network_list_
.empty())
114 const NetworkState
* network
= network_list_
.front()->AsNetworkState();
116 if (!network
->IsConnectedState())
121 const NetworkState
* NetworkStateHandler::ConnectedNetworkByType(
122 const std::string
& type
) const {
123 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
124 iter
!= network_list_
.end(); ++iter
) {
125 const NetworkState
* network
= (*iter
)->AsNetworkState();
127 if (!network
->IsConnectedState())
128 break; // Connected networks are listed first.
129 if (network
->type() == type
)
135 const NetworkState
* NetworkStateHandler::ConnectingNetworkByType(
136 const std::string
& type
) const {
137 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
138 iter
!= network_list_
.end(); ++iter
) {
139 const NetworkState
* network
= (*iter
)->AsNetworkState();
141 if (network
->IsConnectedState())
143 if (!network
->IsConnectingState())
144 break; // Connected and connecting networks are listed first.
145 if (network
->type() == type
||
146 (type
.empty() && type
!= flimflam::kTypeEthernet
)) {
153 std::string
NetworkStateHandler::HardwareAddressForType(
154 const std::string
& type
) const {
156 const NetworkState
* network
= ConnectedNetworkByType(type
);
158 const DeviceState
* device
= GetDeviceState(network
->device_path());
160 result
= device
->mac_address();
162 StringToUpperASCII(&result
);
166 std::string
NetworkStateHandler::FormattedHardwareAddressForType(
167 const std::string
& type
) const {
168 std::string address
= HardwareAddressForType(type
);
169 if (address
.size() % 2 != 0)
172 for (size_t i
= 0; i
< address
.size(); ++i
) {
173 if ((i
!= 0) && (i
% 2 == 0))
174 result
.push_back(':');
175 result
.push_back(address
[i
]);
180 void NetworkStateHandler::GetNetworkList(NetworkStateList
* list
) const {
182 NetworkStateList result
;
184 for (ManagedStateList::const_iterator iter
= network_list_
.begin();
185 iter
!= network_list_
.end(); ++iter
) {
186 const NetworkState
* network
= (*iter
)->AsNetworkState();
188 list
->push_back(network
);
192 bool NetworkStateHandler::RequestWifiScan() const {
193 if (!TechnologyEnabled(flimflam::kTypeWifi
))
195 shill_property_handler_
->RequestScan();
199 //------------------------------------------------------------------------------
200 // ShillPropertyHandler::Delegate overrides
202 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type
,
203 const base::ListValue
& entries
) {
204 ManagedStateList
* managed_list
= GetManagedList(type
);
205 VLOG(2) << "UpdateManagedList: " << type
;
206 // Create a map of existing entries.
207 std::map
<std::string
, ManagedState
*> managed_map
;
208 for (ManagedStateList::iterator iter
= managed_list
->begin();
209 iter
!= managed_list
->end(); ++iter
) {
210 ManagedState
* managed
= *iter
;
211 managed_map
[managed
->path()] = managed
;
213 // Clear the list (pointers are owned by managed_map).
214 managed_list
->clear();
215 // Updates managed_list and request updates for new entries.
216 for (base::ListValue::const_iterator iter
= entries
.begin();
217 iter
!= entries
.end(); ++iter
) {
219 (*iter
)->GetAsString(&path
);
220 DCHECK(!path
.empty());
221 std::map
<std::string
, ManagedState
*>::iterator found
=
222 managed_map
.find(path
);
223 bool request_properties
= false;
224 ManagedState
* managed
;
225 bool is_observing
= shill_property_handler_
->IsObservingNetwork(path
);
226 if (found
== managed_map
.end()) {
227 request_properties
= true;
228 managed
= ManagedState::Create(type
, path
);
229 managed_list
->push_back(managed
);
231 managed
= found
->second
;
232 managed_list
->push_back(managed
);
233 managed_map
.erase(found
);
234 if (!managed
->is_observed() && is_observing
)
235 request_properties
= true;
238 managed
->set_is_observed(true);
239 if (request_properties
)
240 shill_property_handler_
->RequestProperties(type
, path
);
242 // Delete any remaning entries in managed_map.
243 STLDeleteContainerPairSecondPointers(managed_map
.begin(), managed_map
.end());
246 void NetworkStateHandler::UpdateAvailableTechnologies(
247 const base::ListValue
& technologies
) {
248 available_technologies_
.clear();
249 network_event_log::AddEntry(
250 kLogModule
, "AvailableTechnologiesChanged",
251 StringPrintf("Size: %"PRIuS
, technologies
.GetSize()));
252 for (base::ListValue::const_iterator iter
= technologies
.begin();
253 iter
!= technologies
.end(); ++iter
) {
254 std::string technology
;
255 (*iter
)->GetAsString(&technology
);
256 DCHECK(!technology
.empty());
257 available_technologies_
.insert(technology
);
261 void NetworkStateHandler::UpdateEnabledTechnologies(
262 const base::ListValue
& technologies
) {
263 bool wifi_was_enabled
= TechnologyEnabled(flimflam::kTypeWifi
);
264 enabled_technologies_
.clear();
265 network_event_log::AddEntry(
266 kLogModule
, "EnabledTechnologiesChanged",
267 StringPrintf("Size: %"PRIuS
, technologies
.GetSize()));
268 for (base::ListValue::const_iterator iter
= technologies
.begin();
269 iter
!= technologies
.end(); ++iter
) {
270 std::string technology
;
271 (*iter
)->GetAsString(&technology
);
272 DCHECK(!technology
.empty());
273 enabled_technologies_
.insert(technology
);
275 if (!wifi_was_enabled
&& TechnologyEnabled(flimflam::kTypeWifi
))
279 void NetworkStateHandler::UpdateManagedStateProperties(
280 ManagedState::ManagedType type
,
281 const std::string
& path
,
282 const base::DictionaryValue
& properties
) {
283 ManagedState
* managed
= GetModifiableManagedState(GetManagedList(type
), path
);
285 LOG(ERROR
) << "GetPropertiesCallback: " << path
<< " Not found!";
288 bool network_property_changed
= false;
289 for (base::DictionaryValue::Iterator
iter(properties
);
290 iter
.HasNext(); iter
.Advance()) {
291 if (type
== ManagedState::MANAGED_TYPE_NETWORK
) {
292 if (ParseNetworkServiceProperty(
293 managed
->AsNetworkState(), iter
.key(), iter
.value())) {
294 network_property_changed
= true;
297 managed
->PropertyChanged(iter
.key(), iter
.value());
301 if (network_property_changed
) {
302 NetworkState
* network
= managed
->AsNetworkState();
304 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
305 NetworkServiceChanged(network
));
307 network_event_log::AddEntry(
308 kLogModule
, "PropertiesReceived",
309 StringPrintf("%s (%s)", path
.c_str(), managed
->name().c_str()));
312 void NetworkStateHandler::UpdateNetworkServiceProperty(
313 const std::string
& service_path
,
314 const std::string
& key
,
315 const base::Value
& value
) {
316 NetworkState
* network
= GetModifiableNetworkState(service_path
);
319 if (ParseNetworkServiceProperty(network
, key
, value
)) {
320 std::string detail
= network
->name() + "." + key
;
322 if (value
.GetAsString(&vstr
))
323 detail
+= " = " + vstr
;
324 network_event_log::AddEntry(kLogModule
, "NetworkPropertyChanged", detail
);
325 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
326 NetworkServiceChanged(network
));
330 void NetworkStateHandler::UpdateNetworkServiceIPAddress(
331 const std::string
& service_path
,
332 const std::string
& ip_address
) {
333 NetworkState
* network
= GetModifiableNetworkState(service_path
);
336 std::string detail
= network
->name() + ".IPAddress = " + ip_address
;
337 network_event_log::AddEntry(kLogModule
, "NetworkIPChanged", detail
);
338 network
->set_ip_address(ip_address
);
340 NetworkStateHandlerObserver
, observers_
,
341 NetworkServiceChanged(network
));
344 void NetworkStateHandler::ManagerPropertyChanged() {
345 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
346 NetworkManagerChanged());
349 void NetworkStateHandler::ManagedStateListChanged(
350 ManagedState::ManagedType type
) {
351 if (type
== ManagedState::MANAGED_TYPE_NETWORK
) {
352 // Notify observers that the list of networks has changed.
353 NetworkStateList network_list
;
354 GetNetworkList(&network_list
);
355 network_event_log::AddEntry(
356 kLogModule
, "NetworkListChanged",
357 StringPrintf("Size: %"PRIuS
, network_list_
.size()));
358 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
359 NetworkListChanged(network_list
));
360 // Update the active network and notify observers if it has changed.
361 NetworkState
* new_active_network
=
362 network_list_
.empty() ? NULL
: network_list_
.front()->AsNetworkState();
363 std::string new_active_network_path
;
364 if (new_active_network
)
365 new_active_network_path
= new_active_network
->path();
366 if (new_active_network_path
!= active_network_path_
) {
367 network_event_log::AddEntry(
368 kLogModule
, "ActiveNetworkChanged", new_active_network_path
);
369 active_network_path_
= new_active_network_path
;
370 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
371 ActiveNetworkChanged(new_active_network
));
373 } else if (type
== ManagedState::MANAGED_TYPE_DEVICE
) {
374 network_event_log::AddEntry(
375 kLogModule
, "DeviceListChanged",
376 StringPrintf("Size: %"PRIuS
, device_list_
.size()));
377 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
378 DeviceListChanged());
384 //------------------------------------------------------------------------------
387 DeviceState
* NetworkStateHandler::GetModifiableDeviceState(
388 const std::string
& device_path
) const {
389 ManagedState
* managed
= GetModifiableManagedState(&device_list_
, device_path
);
392 return managed
->AsDeviceState();
395 NetworkState
* NetworkStateHandler::GetModifiableNetworkState(
396 const std::string
& service_path
) const {
397 ManagedState
* managed
=
398 GetModifiableManagedState(&network_list_
, service_path
);
401 return managed
->AsNetworkState();
404 ManagedState
* NetworkStateHandler::GetModifiableManagedState(
405 const ManagedStateList
* managed_list
,
406 const std::string
& path
) const {
407 for (ManagedStateList::const_iterator iter
= managed_list
->begin();
408 iter
!= managed_list
->end(); ++iter
) {
409 ManagedState
* managed
= *iter
;
410 if (managed
->path() == path
)
416 NetworkStateHandler::ManagedStateList
* NetworkStateHandler::GetManagedList(
417 ManagedState::ManagedType type
) {
419 case ManagedState::MANAGED_TYPE_NETWORK
:
420 return &network_list_
;
421 case ManagedState::MANAGED_TYPE_DEVICE
:
422 return &device_list_
;
428 bool NetworkStateHandler::ParseNetworkServiceProperty(
429 NetworkState
* network
,
430 const std::string
& key
,
431 const base::Value
& value
) {
433 if (!network
->PropertyChanged(key
, value
))
435 if (network
->path() == active_network_path_
&&
436 key
== flimflam::kStateProperty
) {
437 FOR_EACH_OBSERVER(NetworkStateHandlerObserver
, observers_
,
438 ActiveNetworkStateChanged(network
));
443 } // namespace chromeos