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/shill_property_handler.h"
6
7 #include "base/bind.h"
8 #include "base/format_macros.h"
9 #include "base/stl_util.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/values.h"
13 #include "chromeos/dbus/dbus_thread_manager.h"
14 #include "chromeos/dbus/shill_device_client.h"
15 #include "chromeos/dbus/shill_ipconfig_client.h"
16 #include "chromeos/dbus/shill_manager_client.h"
17 #include "chromeos/dbus/shill_profile_client.h"
18 #include "chromeos/dbus/shill_service_client.h"
19 #include "chromeos/network/network_event_log.h"
20 #include "chromeos/network/network_state.h"
21 #include "dbus/object_path.h"
22 #include "third_party/cros_system_api/dbus/service_constants.h"
23
24 namespace {
25
26 // Limit the number of services or devices we observe. Since they are listed in
27 // priority order, it should be reasonable to ignore services past this.
28 const size_t kMaxObserved = 100;
29
GetListValue(const std::string & key,const base::Value & value)30 const base::ListValue* GetListValue(const std::string& key,
31 const base::Value& value) {
32 const base::ListValue* vlist = NULL;
33 if (!value.GetAsList(&vlist)) {
34 LOG(ERROR) << "Error parsing key as list: " << key;
35 return NULL;
36 }
37 return vlist;
38 }
39
40 } // namespace
41
42 namespace chromeos {
43 namespace internal {
44
45 // Class to manage Shill service property changed observers. Observers are
46 // added on construction and removed on destruction. Runs the handler when
47 // OnPropertyChanged is called.
48 class ShillPropertyObserver : public ShillPropertyChangedObserver {
49 public:
50 typedef base::Callback<void(ManagedState::ManagedType type,
51 const std::string& service,
52 const std::string& name,
53 const base::Value& value)> Handler;
54
ShillPropertyObserver(ManagedState::ManagedType type,const std::string & path,const Handler & handler)55 ShillPropertyObserver(ManagedState::ManagedType type,
56 const std::string& path,
57 const Handler& handler)
58 : type_(type),
59 path_(path),
60 handler_(handler) {
61 if (type_ == ManagedState::MANAGED_TYPE_NETWORK) {
62 DBusThreadManager::Get()->GetShillServiceClient()->
63 AddPropertyChangedObserver(dbus::ObjectPath(path_), this);
64 } else if (type_ == ManagedState::MANAGED_TYPE_DEVICE) {
65 DBusThreadManager::Get()->GetShillDeviceClient()->
66 AddPropertyChangedObserver(dbus::ObjectPath(path_), this);
67 } else {
68 NOTREACHED();
69 }
70 }
71
~ShillPropertyObserver()72 virtual ~ShillPropertyObserver() {
73 if (type_ == ManagedState::MANAGED_TYPE_NETWORK) {
74 DBusThreadManager::Get()->GetShillServiceClient()->
75 RemovePropertyChangedObserver(dbus::ObjectPath(path_), this);
76 } else if (type_ == ManagedState::MANAGED_TYPE_DEVICE) {
77 DBusThreadManager::Get()->GetShillDeviceClient()->
78 RemovePropertyChangedObserver(dbus::ObjectPath(path_), this);
79 } else {
80 NOTREACHED();
81 }
82 }
83
84 // ShillPropertyChangedObserver overrides.
OnPropertyChanged(const std::string & key,const base::Value & value)85 virtual void OnPropertyChanged(const std::string& key,
86 const base::Value& value) OVERRIDE {
87 handler_.Run(type_, path_, key, value);
88 }
89
90 private:
91 ManagedState::ManagedType type_;
92 std::string path_;
93 Handler handler_;
94
95 DISALLOW_COPY_AND_ASSIGN(ShillPropertyObserver);
96 };
97
98 //------------------------------------------------------------------------------
99 // ShillPropertyHandler
100
ShillPropertyHandler(Listener * listener)101 ShillPropertyHandler::ShillPropertyHandler(Listener* listener)
102 : listener_(listener),
103 shill_manager_(DBusThreadManager::Get()->GetShillManagerClient()) {
104 }
105
~ShillPropertyHandler()106 ShillPropertyHandler::~ShillPropertyHandler() {
107 // Delete network service observers.
108 STLDeleteContainerPairSecondPointers(
109 observed_networks_.begin(), observed_networks_.end());
110 STLDeleteContainerPairSecondPointers(
111 observed_devices_.begin(), observed_devices_.end());
112 CHECK(shill_manager_ == DBusThreadManager::Get()->GetShillManagerClient());
113 shill_manager_->RemovePropertyChangedObserver(this);
114 }
115
Init()116 void ShillPropertyHandler::Init() {
117 UpdateManagerProperties();
118 shill_manager_->AddPropertyChangedObserver(this);
119 }
120
UpdateManagerProperties()121 void ShillPropertyHandler::UpdateManagerProperties() {
122 NET_LOG_EVENT("UpdateManagerProperties", "");
123 shill_manager_->GetProperties(
124 base::Bind(&ShillPropertyHandler::ManagerPropertiesCallback,
125 AsWeakPtr()));
126 }
127
IsTechnologyAvailable(const std::string & technology) const128 bool ShillPropertyHandler::IsTechnologyAvailable(
129 const std::string& technology) const {
130 return available_technologies_.count(technology) != 0;
131 }
132
IsTechnologyEnabled(const std::string & technology) const133 bool ShillPropertyHandler::IsTechnologyEnabled(
134 const std::string& technology) const {
135 return enabled_technologies_.count(technology) != 0;
136 }
137
IsTechnologyEnabling(const std::string & technology) const138 bool ShillPropertyHandler::IsTechnologyEnabling(
139 const std::string& technology) const {
140 return enabling_technologies_.count(technology) != 0;
141 }
142
IsTechnologyUninitialized(const std::string & technology) const143 bool ShillPropertyHandler::IsTechnologyUninitialized(
144 const std::string& technology) const {
145 return uninitialized_technologies_.count(technology) != 0;
146 }
147
SetTechnologyEnabled(const std::string & technology,bool enabled,const network_handler::ErrorCallback & error_callback)148 void ShillPropertyHandler::SetTechnologyEnabled(
149 const std::string& technology,
150 bool enabled,
151 const network_handler::ErrorCallback& error_callback) {
152 if (enabled) {
153 enabling_technologies_.insert(technology);
154 shill_manager_->EnableTechnology(
155 technology,
156 base::Bind(&base::DoNothing),
157 base::Bind(&ShillPropertyHandler::EnableTechnologyFailed,
158 AsWeakPtr(), technology, error_callback));
159 } else {
160 // Immediately clear locally from enabled and enabling lists.
161 enabled_technologies_.erase(technology);
162 enabling_technologies_.erase(technology);
163 shill_manager_->DisableTechnology(
164 technology,
165 base::Bind(&base::DoNothing),
166 base::Bind(&network_handler::ShillErrorCallbackFunction,
167 "SetTechnologyEnabled Failed",
168 technology, error_callback));
169 }
170 }
171
SetCheckPortalList(const std::string & check_portal_list)172 void ShillPropertyHandler::SetCheckPortalList(
173 const std::string& check_portal_list) {
174 base::StringValue value(check_portal_list);
175 shill_manager_->SetProperty(
176 shill::kCheckPortalListProperty,
177 value,
178 base::Bind(&base::DoNothing),
179 base::Bind(&network_handler::ShillErrorCallbackFunction,
180 "SetCheckPortalList Failed",
181 "", network_handler::ErrorCallback()));
182 }
183
RequestScan() const184 void ShillPropertyHandler::RequestScan() const {
185 shill_manager_->RequestScan(
186 "",
187 base::Bind(&base::DoNothing),
188 base::Bind(&network_handler::ShillErrorCallbackFunction,
189 "RequestScan Failed",
190 "", network_handler::ErrorCallback()));
191 }
192
ConnectToBestServices() const193 void ShillPropertyHandler::ConnectToBestServices() const {
194 NET_LOG_EVENT("ConnectToBestServices", "");
195 shill_manager_->ConnectToBestServices(
196 base::Bind(&base::DoNothing),
197 base::Bind(&network_handler::ShillErrorCallbackFunction,
198 "ConnectToBestServices Failed",
199 "", network_handler::ErrorCallback()));
200 }
201
RequestProperties(ManagedState::ManagedType type,const std::string & path)202 void ShillPropertyHandler::RequestProperties(ManagedState::ManagedType type,
203 const std::string& path) {
204 VLOG(2) << "Request Properties: " << type << " : " << path;
205 if (pending_updates_[type].find(path) != pending_updates_[type].end())
206 return; // Update already requested.
207
208 pending_updates_[type].insert(path);
209 if (type == ManagedState::MANAGED_TYPE_NETWORK ||
210 type == ManagedState::MANAGED_TYPE_FAVORITE) {
211 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
212 dbus::ObjectPath(path),
213 base::Bind(&ShillPropertyHandler::GetPropertiesCallback,
214 AsWeakPtr(), type, path));
215 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
216 DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
217 dbus::ObjectPath(path),
218 base::Bind(&ShillPropertyHandler::GetPropertiesCallback,
219 AsWeakPtr(), type, path));
220 } else {
221 NOTREACHED();
222 }
223 }
224
OnPropertyChanged(const std::string & key,const base::Value & value)225 void ShillPropertyHandler::OnPropertyChanged(const std::string& key,
226 const base::Value& value) {
227 ManagerPropertyChanged(key, value);
228 CheckPendingStateListUpdates(key);
229 }
230
231 //------------------------------------------------------------------------------
232 // Private methods
233
ManagerPropertiesCallback(DBusMethodCallStatus call_status,const base::DictionaryValue & properties)234 void ShillPropertyHandler::ManagerPropertiesCallback(
235 DBusMethodCallStatus call_status,
236 const base::DictionaryValue& properties) {
237 if (call_status != DBUS_METHOD_CALL_SUCCESS) {
238 NET_LOG_ERROR("ManagerPropertiesCallback",
239 base::StringPrintf("Failed: %d", call_status));
240 return;
241 }
242 NET_LOG_EVENT("ManagerPropertiesCallback", "Success");
243 const base::Value* update_service_value = NULL;
244 const base::Value* update_service_complete_value = NULL;
245 for (base::DictionaryValue::Iterator iter(properties);
246 !iter.IsAtEnd(); iter.Advance()) {
247 // Defer updating Services until all other properties have been updated.
248 if (iter.key() == shill::kServicesProperty)
249 update_service_value = &iter.value();
250 else if (iter.key() == shill::kServiceCompleteListProperty)
251 update_service_complete_value = &iter.value();
252 else
253 ManagerPropertyChanged(iter.key(), iter.value());
254 }
255 // Update Services which can safely assume other properties have been set.
256 if (update_service_value)
257 ManagerPropertyChanged(shill::kServicesProperty, *update_service_value);
258 // Update ServiceCompleteList which skips entries that have already been
259 // requested for Services.
260 if (update_service_complete_value) {
261 ManagerPropertyChanged(shill::kServiceCompleteListProperty,
262 *update_service_complete_value);
263 }
264
265 CheckPendingStateListUpdates("");
266 }
267
CheckPendingStateListUpdates(const std::string & key)268 void ShillPropertyHandler::CheckPendingStateListUpdates(
269 const std::string& key) {
270 // Once there are no pending updates, signal the state list changed callbacks.
271 if ((key.empty() || key == shill::kServicesProperty) &&
272 pending_updates_[ManagedState::MANAGED_TYPE_NETWORK].size() == 0) {
273 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_NETWORK);
274 }
275 // Both Network update requests and Favorite update requests will affect
276 // the list of favorites, so wait for both to complete.
277 if ((key.empty() || key == shill::kServiceCompleteListProperty) &&
278 pending_updates_[ManagedState::MANAGED_TYPE_NETWORK].size() == 0 &&
279 pending_updates_[ManagedState::MANAGED_TYPE_FAVORITE].size() == 0) {
280 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_FAVORITE);
281 }
282 if ((key.empty() || key == shill::kDevicesProperty) &&
283 pending_updates_[ManagedState::MANAGED_TYPE_DEVICE].size() == 0) {
284 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_DEVICE);
285 }
286 }
287
ManagerPropertyChanged(const std::string & key,const base::Value & value)288 void ShillPropertyHandler::ManagerPropertyChanged(const std::string& key,
289 const base::Value& value) {
290 if (key == shill::kServicesProperty) {
291 const base::ListValue* vlist = GetListValue(key, value);
292 if (vlist) {
293 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_NETWORK, *vlist);
294 UpdateProperties(ManagedState::MANAGED_TYPE_NETWORK, *vlist);
295 // UpdateObserved used to use kServiceWatchListProperty for TYPE_NETWORK,
296 // however that prevents us from receiving Strength updates from inactive
297 // networks. The overhead for observing all services is not unreasonable
298 // (and we limit the max number of observed services to kMaxObserved).
299 UpdateObserved(ManagedState::MANAGED_TYPE_NETWORK, *vlist);
300 }
301 } else if (key == shill::kServiceCompleteListProperty) {
302 const ListValue* vlist = GetListValue(key, value);
303 if (vlist) {
304 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_FAVORITE, *vlist);
305 UpdateProperties(ManagedState::MANAGED_TYPE_FAVORITE, *vlist);
306 }
307 } else if (key == shill::kDevicesProperty) {
308 const base::ListValue* vlist = GetListValue(key, value);
309 if (vlist) {
310 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_DEVICE, *vlist);
311 UpdateProperties(ManagedState::MANAGED_TYPE_DEVICE, *vlist);
312 UpdateObserved(ManagedState::MANAGED_TYPE_DEVICE, *vlist);
313 }
314 } else if (key == shill::kAvailableTechnologiesProperty) {
315 const base::ListValue* vlist = GetListValue(key, value);
316 if (vlist)
317 UpdateAvailableTechnologies(*vlist);
318 } else if (key == shill::kEnabledTechnologiesProperty) {
319 const base::ListValue* vlist = GetListValue(key, value);
320 if (vlist)
321 UpdateEnabledTechnologies(*vlist);
322 } else if (key == shill::kUninitializedTechnologiesProperty) {
323 const base::ListValue* vlist = GetListValue(key, value);
324 if (vlist)
325 UpdateUninitializedTechnologies(*vlist);
326 } else if (key == shill::kProfilesProperty) {
327 listener_->ProfileListChanged();
328 } else if (key == shill::kCheckPortalListProperty) {
329 std::string check_portal_list;
330 if (value.GetAsString(&check_portal_list))
331 listener_->CheckPortalListChanged(check_portal_list);
332 } else {
333 VLOG(2) << "Ignored Manager Property: " << key;
334 }
335 }
336
UpdateProperties(ManagedState::ManagedType type,const base::ListValue & entries)337 void ShillPropertyHandler::UpdateProperties(ManagedState::ManagedType type,
338 const base::ListValue& entries) {
339 std::set<std::string>& requested_updates = requested_updates_[type];
340 std::set<std::string>& requested_service_updates =
341 requested_updates_[ManagedState::MANAGED_TYPE_NETWORK]; // For favorites
342 std::set<std::string> new_requested_updates;
343 VLOG(2) << "Update Properties: " << type << " Entries: " << entries.GetSize();
344 for (base::ListValue::const_iterator iter = entries.begin();
345 iter != entries.end(); ++iter) {
346 std::string path;
347 (*iter)->GetAsString(&path);
348 if (path.empty())
349 continue;
350 if (type == ManagedState::MANAGED_TYPE_FAVORITE &&
351 requested_service_updates.count(path) > 0)
352 continue; // Update already requested
353
354 // We add a special case for devices here to work around an issue in shill
355 // that prevents it from sending property changed signals for cellular
356 // devices (see crbug.com/321854).
357 if (type == ManagedState::MANAGED_TYPE_DEVICE ||
358 requested_updates.find(path) == requested_updates.end())
359 RequestProperties(type, path);
360 new_requested_updates.insert(path);
361 }
362 requested_updates.swap(new_requested_updates);
363 }
364
UpdateObserved(ManagedState::ManagedType type,const base::ListValue & entries)365 void ShillPropertyHandler::UpdateObserved(ManagedState::ManagedType type,
366 const base::ListValue& entries) {
367 DCHECK(type == ManagedState::MANAGED_TYPE_NETWORK ||
368 type == ManagedState::MANAGED_TYPE_DEVICE);
369 ShillPropertyObserverMap& observer_map =
370 (type == ManagedState::MANAGED_TYPE_NETWORK)
371 ? observed_networks_ : observed_devices_;
372 ShillPropertyObserverMap new_observed;
373 for (base::ListValue::const_iterator iter1 = entries.begin();
374 iter1 != entries.end(); ++iter1) {
375 std::string path;
376 (*iter1)->GetAsString(&path);
377 if (path.empty())
378 continue;
379 ShillPropertyObserverMap::iterator iter2 = observer_map.find(path);
380 if (iter2 != observer_map.end()) {
381 new_observed[path] = iter2->second;
382 } else {
383 // Create an observer for future updates.
384 new_observed[path] = new ShillPropertyObserver(
385 type, path, base::Bind(
386 &ShillPropertyHandler::PropertyChangedCallback, AsWeakPtr()));
387 }
388 observer_map.erase(path);
389 // Limit the number of observed services.
390 if (new_observed.size() >= kMaxObserved)
391 break;
392 }
393 // Delete network service observers still in observer_map.
394 for (ShillPropertyObserverMap::iterator iter = observer_map.begin();
395 iter != observer_map.end(); ++iter) {
396 delete iter->second;
397 }
398 observer_map.swap(new_observed);
399 }
400
UpdateAvailableTechnologies(const base::ListValue & technologies)401 void ShillPropertyHandler::UpdateAvailableTechnologies(
402 const base::ListValue& technologies) {
403 available_technologies_.clear();
404 NET_LOG_EVENT("AvailableTechnologiesChanged",
405 base::StringPrintf("Size: %" PRIuS, technologies.GetSize()));
406 for (base::ListValue::const_iterator iter = technologies.begin();
407 iter != technologies.end(); ++iter) {
408 std::string technology;
409 (*iter)->GetAsString(&technology);
410 DCHECK(!technology.empty());
411 available_technologies_.insert(technology);
412 }
413 listener_->TechnologyListChanged();
414 }
415
UpdateEnabledTechnologies(const base::ListValue & technologies)416 void ShillPropertyHandler::UpdateEnabledTechnologies(
417 const base::ListValue& technologies) {
418 enabled_technologies_.clear();
419 NET_LOG_EVENT("EnabledTechnologiesChanged",
420 base::StringPrintf("Size: %" PRIuS, technologies.GetSize()));
421 for (base::ListValue::const_iterator iter = technologies.begin();
422 iter != technologies.end(); ++iter) {
423 std::string technology;
424 (*iter)->GetAsString(&technology);
425 DCHECK(!technology.empty());
426 enabled_technologies_.insert(technology);
427 enabling_technologies_.erase(technology);
428 }
429 listener_->TechnologyListChanged();
430 }
431
UpdateUninitializedTechnologies(const base::ListValue & technologies)432 void ShillPropertyHandler::UpdateUninitializedTechnologies(
433 const base::ListValue& technologies) {
434 uninitialized_technologies_.clear();
435 NET_LOG_EVENT("UninitializedTechnologiesChanged",
436 base::StringPrintf("Size: %" PRIuS, technologies.GetSize()));
437 for (base::ListValue::const_iterator iter = technologies.begin();
438 iter != technologies.end(); ++iter) {
439 std::string technology;
440 (*iter)->GetAsString(&technology);
441 DCHECK(!technology.empty());
442 uninitialized_technologies_.insert(technology);
443 }
444 listener_->TechnologyListChanged();
445 }
446
EnableTechnologyFailed(const std::string & technology,const network_handler::ErrorCallback & error_callback,const std::string & dbus_error_name,const std::string & dbus_error_message)447 void ShillPropertyHandler::EnableTechnologyFailed(
448 const std::string& technology,
449 const network_handler::ErrorCallback& error_callback,
450 const std::string& dbus_error_name,
451 const std::string& dbus_error_message) {
452 enabling_technologies_.erase(technology);
453 network_handler::ShillErrorCallbackFunction(
454 "EnableTechnology Failed",
455 technology, error_callback,
456 dbus_error_name, dbus_error_message);
457 }
458
GetPropertiesCallback(ManagedState::ManagedType type,const std::string & path,DBusMethodCallStatus call_status,const base::DictionaryValue & properties)459 void ShillPropertyHandler::GetPropertiesCallback(
460 ManagedState::ManagedType type,
461 const std::string& path,
462 DBusMethodCallStatus call_status,
463 const base::DictionaryValue& properties) {
464 VLOG(2) << "GetPropertiesCallback: " << type << " : " << path;
465 pending_updates_[type].erase(path);
466 if (call_status != DBUS_METHOD_CALL_SUCCESS) {
467 // The shill service no longer exists. This can happen when a network
468 // has been removed.
469 NET_LOG_DEBUG("Failed to get properties",
470 base::StringPrintf("%s: %d", path.c_str(), call_status));
471 return;
472 }
473 // Update Favorite properties for networks in the Services list.
474 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
475 // Only networks with a ProfilePath set are Favorites.
476 std::string profile_path;
477 properties.GetStringWithoutPathExpansion(
478 shill::kProfileProperty, &profile_path);
479 if (!profile_path.empty()) {
480 listener_->UpdateManagedStateProperties(
481 ManagedState::MANAGED_TYPE_FAVORITE, path, properties);
482 }
483 }
484 listener_->UpdateManagedStateProperties(type, path, properties);
485 // Request IPConfig parameters for networks.
486 if (type == ManagedState::MANAGED_TYPE_NETWORK &&
487 properties.HasKey(shill::kIPConfigProperty)) {
488 std::string ip_config_path;
489 if (properties.GetString(shill::kIPConfigProperty, &ip_config_path)) {
490 DBusThreadManager::Get()->GetShillIPConfigClient()->GetProperties(
491 dbus::ObjectPath(ip_config_path),
492 base::Bind(&ShillPropertyHandler::GetIPConfigCallback,
493 AsWeakPtr(), path));
494 }
495 }
496
497 // Notify the listener only when all updates for that type have completed.
498 if (pending_updates_[type].size() == 0) {
499 listener_->ManagedStateListChanged(type);
500 // Notify that Favorites have changed when notifying for Networks if there
501 // are no additional Favorite updates pending.
502 if (type == ManagedState::MANAGED_TYPE_NETWORK &&
503 pending_updates_[ManagedState::MANAGED_TYPE_FAVORITE].size() == 0) {
504 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_FAVORITE);
505 }
506 }
507 }
508
PropertyChangedCallback(ManagedState::ManagedType type,const std::string & path,const std::string & key,const base::Value & value)509 void ShillPropertyHandler::PropertyChangedCallback(
510 ManagedState::ManagedType type,
511 const std::string& path,
512 const std::string& key,
513 const base::Value& value) {
514 if (type == ManagedState::MANAGED_TYPE_NETWORK)
515 NetworkServicePropertyChangedCallback(path, key, value);
516 else if (type == ManagedState::MANAGED_TYPE_DEVICE)
517 NetworkDevicePropertyChangedCallback(path, key, value);
518 else
519 NOTREACHED();
520 }
521
NetworkServicePropertyChangedCallback(const std::string & path,const std::string & key,const base::Value & value)522 void ShillPropertyHandler::NetworkServicePropertyChangedCallback(
523 const std::string& path,
524 const std::string& key,
525 const base::Value& value) {
526 if (key == shill::kIPConfigProperty) {
527 // Request the IPConfig for the network and update network properties
528 // when the request completes.
529 std::string ip_config_path;
530 value.GetAsString(&ip_config_path);
531 DCHECK(!ip_config_path.empty());
532 DBusThreadManager::Get()->GetShillIPConfigClient()->GetProperties(
533 dbus::ObjectPath(ip_config_path),
534 base::Bind(&ShillPropertyHandler::GetIPConfigCallback,
535 AsWeakPtr(), path));
536 } else {
537 listener_->UpdateNetworkServiceProperty(path, key, value);
538 }
539 }
540
GetIPConfigCallback(const std::string & service_path,DBusMethodCallStatus call_status,const base::DictionaryValue & properties)541 void ShillPropertyHandler::GetIPConfigCallback(
542 const std::string& service_path,
543 DBusMethodCallStatus call_status,
544 const base::DictionaryValue& properties) {
545 if (call_status != DBUS_METHOD_CALL_SUCCESS) {
546 NET_LOG_ERROR("Failed to get IP Config properties",
547 base::StringPrintf("%s: %d",
548 service_path.c_str(), call_status));
549 return;
550 }
551 UpdateIPConfigProperty(service_path, properties, shill::kAddressProperty);
552 UpdateIPConfigProperty(service_path, properties, shill::kNameServersProperty);
553 UpdateIPConfigProperty(service_path, properties, shill::kPrefixlenProperty);
554 UpdateIPConfigProperty(service_path, properties, shill::kGatewayProperty);
555 UpdateIPConfigProperty(service_path, properties,
556 shill::kWebProxyAutoDiscoveryUrlProperty);
557 }
558
UpdateIPConfigProperty(const std::string & service_path,const base::DictionaryValue & properties,const char * property)559 void ShillPropertyHandler::UpdateIPConfigProperty(
560 const std::string& service_path,
561 const base::DictionaryValue& properties,
562 const char* property) {
563 const base::Value* value;
564 if (!properties.GetWithoutPathExpansion(property, &value)) {
565 LOG(ERROR) << "Failed to get IPConfig property: " << property
566 << ", for: " << service_path;
567 return;
568 }
569 listener_->UpdateNetworkServiceProperty(
570 service_path, NetworkState::IPConfigProperty(property), *value);
571 }
572
NetworkDevicePropertyChangedCallback(const std::string & path,const std::string & key,const base::Value & value)573 void ShillPropertyHandler::NetworkDevicePropertyChangedCallback(
574 const std::string& path,
575 const std::string& key,
576 const base::Value& value) {
577 listener_->UpdateDeviceProperty(path, key, value);
578 }
579
580 } // namespace internal
581 } // namespace chromeos
582