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