shill_property_handler.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file. 4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chromeos/network/shill_property_handler.h" 6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/bind.h" 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/format_macros.h" 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/stl_util.h" 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/strings/string_util.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/strings/stringprintf.h" 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/values.h" 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chromeos/dbus/dbus_thread_manager.h" 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chromeos/dbus/shill_device_client.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromeos/dbus/shill_ipconfig_client.h" 16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chromeos/dbus/shill_manager_client.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chromeos/dbus/shill_profile_client.h" 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#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 24namespace { 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. 28const size_t kMaxObserved = 100; 29 30const 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 42namespace chromeos { 43namespace 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. 48class 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 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 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. 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 101ShillPropertyHandler::ShillPropertyHandler(Listener* listener) 102 : listener_(listener), 103 shill_manager_(DBusThreadManager::Get()->GetShillManagerClient()) { 104} 105 106ShillPropertyHandler::~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 116void ShillPropertyHandler::Init() { 117 UpdateManagerProperties(); 118 shill_manager_->AddPropertyChangedObserver(this); 119} 120 121void ShillPropertyHandler::UpdateManagerProperties() { 122 NET_LOG_EVENT("UpdateManagerProperties", ""); 123 shill_manager_->GetProperties( 124 base::Bind(&ShillPropertyHandler::ManagerPropertiesCallback, 125 AsWeakPtr())); 126} 127 128bool ShillPropertyHandler::IsTechnologyAvailable( 129 const std::string& technology) const { 130 return available_technologies_.count(technology) != 0; 131} 132 133bool ShillPropertyHandler::IsTechnologyEnabled( 134 const std::string& technology) const { 135 return enabled_technologies_.count(technology) != 0; 136} 137 138bool ShillPropertyHandler::IsTechnologyEnabling( 139 const std::string& technology) const { 140 return enabling_technologies_.count(technology) != 0; 141} 142 143bool ShillPropertyHandler::IsTechnologyUninitialized( 144 const std::string& technology) const { 145 return uninitialized_technologies_.count(technology) != 0; 146} 147 148void 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 technology, error_callback)); 168 } 169} 170 171void ShillPropertyHandler::SetCheckPortalList( 172 const std::string& check_portal_list) { 173 base::StringValue value(check_portal_list); 174 shill_manager_->SetProperty( 175 flimflam::kCheckPortalListProperty, 176 value, 177 base::Bind(&base::DoNothing), 178 base::Bind(&network_handler::ShillErrorCallbackFunction, 179 "", network_handler::ErrorCallback())); 180} 181 182void ShillPropertyHandler::RequestScan() const { 183 shill_manager_->RequestScan( 184 "", 185 base::Bind(&base::DoNothing), 186 base::Bind(&network_handler::ShillErrorCallbackFunction, 187 "", network_handler::ErrorCallback())); 188} 189 190void ShillPropertyHandler::ConnectToBestServices() const { 191 NET_LOG_EVENT("ConnectToBestServices", ""); 192 shill_manager_->ConnectToBestServices( 193 base::Bind(&base::DoNothing), 194 base::Bind(&network_handler::ShillErrorCallbackFunction, 195 "", network_handler::ErrorCallback())); 196} 197 198void ShillPropertyHandler::RequestProperties(ManagedState::ManagedType type, 199 const std::string& path) { 200 VLOG(2) << "Request Properties: " << type << " : " << path; 201 if (pending_updates_[type].find(path) != pending_updates_[type].end()) 202 return; // Update already requested. 203 204 pending_updates_[type].insert(path); 205 if (type == ManagedState::MANAGED_TYPE_NETWORK || 206 type == ManagedState::MANAGED_TYPE_FAVORITE) { 207 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( 208 dbus::ObjectPath(path), 209 base::Bind(&ShillPropertyHandler::GetPropertiesCallback, 210 AsWeakPtr(), type, path)); 211 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { 212 DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties( 213 dbus::ObjectPath(path), 214 base::Bind(&ShillPropertyHandler::GetPropertiesCallback, 215 AsWeakPtr(), type, path)); 216 } else { 217 NOTREACHED(); 218 } 219} 220 221void ShillPropertyHandler::OnPropertyChanged(const std::string& key, 222 const base::Value& value) { 223 if (ManagerPropertyChanged(key, value)) { 224 std::string detail = key; 225 detail += " = " + network_event_log::ValueAsString(value); 226 NET_LOG_DEBUG("ManagerPropertyChanged", detail); 227 listener_->NotifyManagerPropertyChanged(); 228 } 229 CheckPendingStateListUpdates(key); 230} 231 232//------------------------------------------------------------------------------ 233// Private methods 234 235void ShillPropertyHandler::ManagerPropertiesCallback( 236 DBusMethodCallStatus call_status, 237 const base::DictionaryValue& properties) { 238 if (call_status != DBUS_METHOD_CALL_SUCCESS) { 239 NET_LOG_ERROR("ManagerPropertiesCallback", 240 base::StringPrintf("Failed: %d", call_status)); 241 return; 242 } 243 NET_LOG_EVENT("ManagerPropertiesCallback", "Success"); 244 bool notify = false; 245 const base::Value* update_service_value = NULL; 246 const base::Value* update_service_complete_value = NULL; 247 for (base::DictionaryValue::Iterator iter(properties); 248 !iter.IsAtEnd(); iter.Advance()) { 249 // Defer updating Services until all other properties have been updated. 250 if (iter.key() == flimflam::kServicesProperty) 251 update_service_value = &iter.value(); 252 else if (iter.key() == shill::kServiceCompleteListProperty) 253 update_service_complete_value = &iter.value(); 254 else 255 notify |= ManagerPropertyChanged(iter.key(), iter.value()); 256 } 257 // Update Services which can safely assume other properties have been set. 258 if (update_service_value) { 259 notify |= ManagerPropertyChanged(flimflam::kServicesProperty, 260 *update_service_value); 261 } 262 // Update ServiceCompleteList which skips entries that have already been 263 // requested for Services. 264 if (update_service_complete_value) { 265 notify |= ManagerPropertyChanged(shill::kServiceCompleteListProperty, 266 *update_service_complete_value); 267 } 268 269 if (notify) 270 listener_->NotifyManagerPropertyChanged(); 271 CheckPendingStateListUpdates(""); 272} 273 274void ShillPropertyHandler::CheckPendingStateListUpdates( 275 const std::string& key) { 276 // Once there are no pending updates, signal the state list changed callbacks. 277 if ((key.empty() || key == flimflam::kServicesProperty) && 278 pending_updates_[ManagedState::MANAGED_TYPE_NETWORK].size() == 0) { 279 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_NETWORK); 280 } 281 // Both Network update requests and Favorite update requests will affect 282 // the list of favorites, so wait for both to complete. 283 if ((key.empty() || key == shill::kServiceCompleteListProperty) && 284 pending_updates_[ManagedState::MANAGED_TYPE_NETWORK].size() == 0 && 285 pending_updates_[ManagedState::MANAGED_TYPE_FAVORITE].size() == 0) { 286 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_FAVORITE); 287 } 288 if ((key.empty() || key == flimflam::kDevicesProperty) && 289 pending_updates_[ManagedState::MANAGED_TYPE_DEVICE].size() == 0) { 290 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_DEVICE); 291 } 292} 293 294bool ShillPropertyHandler::ManagerPropertyChanged(const std::string& key, 295 const base::Value& value) { 296 bool notify_manager_changed = false; 297 if (key == flimflam::kServicesProperty) { 298 const base::ListValue* vlist = GetListValue(key, value); 299 if (vlist) { 300 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_NETWORK, *vlist); 301 UpdateProperties(ManagedState::MANAGED_TYPE_NETWORK, *vlist); 302 // UpdateObserved used to use kServiceWatchListProperty for TYPE_NETWORK, 303 // however that prevents us from receiving Strength updates from inactive 304 // networks. The overhead for observing all services is not unreasonable 305 // (and we limit the max number of observed services to kMaxObserved). 306 UpdateObserved(ManagedState::MANAGED_TYPE_NETWORK, *vlist); 307 } 308 } else if (key == shill::kServiceCompleteListProperty) { 309 const ListValue* vlist = GetListValue(key, value); 310 if (vlist) { 311 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_FAVORITE, *vlist); 312 UpdateProperties(ManagedState::MANAGED_TYPE_FAVORITE, *vlist); 313 } 314 } else if (key == flimflam::kDevicesProperty) { 315 const base::ListValue* vlist = GetListValue(key, value); 316 if (vlist) { 317 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_DEVICE, *vlist); 318 UpdateProperties(ManagedState::MANAGED_TYPE_DEVICE, *vlist); 319 UpdateObserved(ManagedState::MANAGED_TYPE_DEVICE, *vlist); 320 } 321 } else if (key == flimflam::kAvailableTechnologiesProperty) { 322 const base::ListValue* vlist = GetListValue(key, value); 323 if (vlist) { 324 UpdateAvailableTechnologies(*vlist); 325 notify_manager_changed = true; 326 } 327 } else if (key == flimflam::kEnabledTechnologiesProperty) { 328 const base::ListValue* vlist = GetListValue(key, value); 329 if (vlist) { 330 UpdateEnabledTechnologies(*vlist); 331 notify_manager_changed = true; 332 } 333 } else if (key == shill::kUninitializedTechnologiesProperty) { 334 const base::ListValue* vlist = GetListValue(key, value); 335 if (vlist) { 336 UpdateUninitializedTechnologies(*vlist); 337 notify_manager_changed = true; 338 } 339 } else if (key == flimflam::kProfilesProperty) { 340 listener_->ProfileListChanged(); 341 } else if (key == flimflam::kCheckPortalListProperty) { 342 std::string check_portal_list; 343 if (value.GetAsString(&check_portal_list)) { 344 listener_->CheckPortalListChanged(check_portal_list); 345 notify_manager_changed = true; 346 } 347 } else { 348 VLOG(2) << "Ignored Manager Property: " << key; 349 } 350 return notify_manager_changed; 351} 352 353void ShillPropertyHandler::UpdateProperties(ManagedState::ManagedType type, 354 const base::ListValue& entries) { 355 std::set<std::string>& requested_updates = requested_updates_[type]; 356 std::set<std::string>& requested_service_updates = 357 requested_updates_[ManagedState::MANAGED_TYPE_NETWORK]; // For favorites 358 std::set<std::string> new_requested_updates; 359 VLOG(2) << "Update Properties: " << type << " Entries: " << entries.GetSize(); 360 for (base::ListValue::const_iterator iter = entries.begin(); 361 iter != entries.end(); ++iter) { 362 std::string path; 363 (*iter)->GetAsString(&path); 364 if (path.empty()) 365 continue; 366 if (type == ManagedState::MANAGED_TYPE_FAVORITE && 367 requested_service_updates.count(path) > 0) 368 continue; // Update already requested 369 if (requested_updates.find(path) == requested_updates.end()) 370 RequestProperties(type, path); 371 new_requested_updates.insert(path); 372 } 373 requested_updates.swap(new_requested_updates); 374} 375 376void ShillPropertyHandler::UpdateObserved(ManagedState::ManagedType type, 377 const base::ListValue& entries) { 378 DCHECK(type == ManagedState::MANAGED_TYPE_NETWORK || 379 type == ManagedState::MANAGED_TYPE_DEVICE); 380 ShillPropertyObserverMap& observer_map = 381 (type == ManagedState::MANAGED_TYPE_NETWORK) 382 ? observed_networks_ : observed_devices_; 383 ShillPropertyObserverMap new_observed; 384 for (base::ListValue::const_iterator iter1 = entries.begin(); 385 iter1 != entries.end(); ++iter1) { 386 std::string path; 387 (*iter1)->GetAsString(&path); 388 if (path.empty()) 389 continue; 390 ShillPropertyObserverMap::iterator iter2 = observer_map.find(path); 391 if (iter2 != observer_map.end()) { 392 new_observed[path] = iter2->second; 393 } else { 394 // Create an observer for future updates. 395 new_observed[path] = new ShillPropertyObserver( 396 type, path, base::Bind( 397 &ShillPropertyHandler::PropertyChangedCallback, AsWeakPtr())); 398 NET_LOG_DEBUG("StartObserving", path); 399 } 400 observer_map.erase(path); 401 // Limit the number of observed services. 402 if (new_observed.size() >= kMaxObserved) 403 break; 404 } 405 // Delete network service observers still in observer_map. 406 for (ShillPropertyObserverMap::iterator iter = observer_map.begin(); 407 iter != observer_map.end(); ++iter) { 408 NET_LOG_DEBUG("StopObserving", iter->first); 409 delete iter->second; 410 } 411 observer_map.swap(new_observed); 412} 413 414void ShillPropertyHandler::UpdateAvailableTechnologies( 415 const base::ListValue& technologies) { 416 available_technologies_.clear(); 417 NET_LOG_EVENT("AvailableTechnologiesChanged", 418 base::StringPrintf("Size: %"PRIuS, technologies.GetSize())); 419 for (base::ListValue::const_iterator iter = technologies.begin(); 420 iter != technologies.end(); ++iter) { 421 std::string technology; 422 (*iter)->GetAsString(&technology); 423 DCHECK(!technology.empty()); 424 available_technologies_.insert(technology); 425 } 426} 427 428void ShillPropertyHandler::UpdateEnabledTechnologies( 429 const base::ListValue& technologies) { 430 enabled_technologies_.clear(); 431 NET_LOG_EVENT("EnabledTechnologiesChanged", 432 base::StringPrintf("Size: %"PRIuS, technologies.GetSize())); 433 for (base::ListValue::const_iterator iter = technologies.begin(); 434 iter != technologies.end(); ++iter) { 435 std::string technology; 436 (*iter)->GetAsString(&technology); 437 DCHECK(!technology.empty()); 438 enabled_technologies_.insert(technology); 439 enabling_technologies_.erase(technology); 440 } 441} 442 443void ShillPropertyHandler::UpdateUninitializedTechnologies( 444 const base::ListValue& technologies) { 445 uninitialized_technologies_.clear(); 446 NET_LOG_EVENT("UninitializedTechnologiesChanged", 447 base::StringPrintf("Size: %"PRIuS, technologies.GetSize())); 448 for (base::ListValue::const_iterator iter = technologies.begin(); 449 iter != technologies.end(); ++iter) { 450 std::string technology; 451 (*iter)->GetAsString(&technology); 452 DCHECK(!technology.empty()); 453 uninitialized_technologies_.insert(technology); 454 } 455} 456 457void ShillPropertyHandler::EnableTechnologyFailed( 458 const std::string& technology, 459 const network_handler::ErrorCallback& error_callback, 460 const std::string& error_name, 461 const std::string& error_message) { 462 enabling_technologies_.erase(technology); 463 network_handler::ShillErrorCallbackFunction( 464 technology, error_callback, error_name, error_message); 465} 466 467void ShillPropertyHandler::GetPropertiesCallback( 468 ManagedState::ManagedType type, 469 const std::string& path, 470 DBusMethodCallStatus call_status, 471 const base::DictionaryValue& properties) { 472 VLOG(2) << "GetPropertiesCallback: " << type << " : " << path; 473 pending_updates_[type].erase(path); 474 if (call_status != DBUS_METHOD_CALL_SUCCESS) { 475 NET_LOG_ERROR("Failed to get properties", 476 base::StringPrintf("%s: %d", path.c_str(), call_status)); 477 return; 478 } 479 listener_->UpdateManagedStateProperties(type, path, properties); 480 // Update Favorite properties for networks in the Services list. 481 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 482 listener_->UpdateManagedStateProperties( 483 ManagedState::MANAGED_TYPE_FAVORITE, path, properties); 484 } 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 509void 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 522void 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 541void 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 const base::Value* ip_address; 552 if (!properties.GetWithoutPathExpansion(flimflam::kAddressProperty, 553 &ip_address)) { 554 LOG(ERROR) << "Failed to get IP Address property for: " << service_path; 555 return; 556 } 557 listener_->UpdateNetworkServiceProperty( 558 service_path, 559 NetworkState::IPConfigProperty(flimflam::kAddressProperty), 560 *ip_address); 561 562 const base::Value* dns_servers = NULL; 563 if (!properties.GetWithoutPathExpansion( 564 flimflam::kNameServersProperty, &dns_servers)) { 565 LOG(ERROR) << "Failed to get Name servers property for: " << service_path; 566 return; 567 } 568 listener_->UpdateNetworkServiceProperty( 569 service_path, 570 NetworkState::IPConfigProperty(flimflam::kNameServersProperty), 571 *dns_servers); 572} 573 574void ShillPropertyHandler::NetworkDevicePropertyChangedCallback( 575 const std::string& path, 576 const std::string& key, 577 const base::Value& value) { 578 listener_->UpdateDeviceProperty(path, key, value); 579} 580 581} // namespace internal 582} // namespace chromeos 583