shill_property_handler.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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" 6a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/string_util.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/strings/stringprintf.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/shill_device_client.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/shill_ipconfig_client.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/shill_manager_client.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/shill_profile_client.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/shill_service_client.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/network_event_log.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/network_state.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Limit the number of services or devices we observe. Since they are listed in 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// priority order, it should be reasonable to ignore services past this. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxObserved = 100; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const base::ListValue* GetListValue(const std::string& key, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Value& value) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::ListValue* vlist = NULL; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.GetAsList(&vlist)) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Error parsing key as list: " << key; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return vlist; 38a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 39a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 40a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} // namespace 41a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Class to manage Shill service property changed observers. Observers are 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// added on construction and removed on destruction. Runs the handler when 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OnPropertyChanged is called. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ShillPropertyObserver : public ShillPropertyChangedObserver { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef base::Callback<void(ManagedState::ManagedType type, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& service, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Value& value)> Handler; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShillPropertyObserver(ManagedState::ManagedType type, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& path, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Handler& handler) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : type_(type), 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path_(path), 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handler_(handler) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type_ == ManagedState::MANAGED_TYPE_NETWORK) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusThreadManager::Get()->GetShillServiceClient()-> 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddPropertyChangedObserver(dbus::ObjectPath(path_), this); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type_ == ManagedState::MANAGED_TYPE_DEVICE) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusThreadManager::Get()->GetShillDeviceClient()-> 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddPropertyChangedObserver(dbus::ObjectPath(path_), this); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ShillPropertyObserver() { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type_ == ManagedState::MANAGED_TYPE_NETWORK) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusThreadManager::Get()->GetShillServiceClient()-> 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemovePropertyChangedObserver(dbus::ObjectPath(path_), this); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type_ == ManagedState::MANAGED_TYPE_DEVICE) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DBusThreadManager::Get()->GetShillDeviceClient()-> 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemovePropertyChangedObserver(dbus::ObjectPath(path_), this); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 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 "SetTechnologyEnabled Failed", 168 technology, error_callback)); 169 } 170} 171 172void 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 184void 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 193void 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 202void ShillPropertyHandler::RequestProperties(ManagedState::ManagedType type, 203 const std::string& path) { 204 if (pending_updates_[type].find(path) != pending_updates_[type].end()) 205 return; // Update already requested. 206 207 NET_LOG_DEBUG("Request Properties", path); 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 225void 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 234void 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 268void 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 288void ShillPropertyHandler::ManagerPropertyChanged(const std::string& key, 289 const base::Value& value) { 290 if (key == shill::kDefaultServiceProperty) { 291 std::string service_path; 292 value.GetAsString(&service_path); 293 listener_->DefaultNetworkServiceChanged(service_path); 294 } else if (key == shill::kServicesProperty) { 295 const base::ListValue* vlist = GetListValue(key, value); 296 if (vlist) { 297 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_NETWORK, *vlist); 298 UpdateProperties(ManagedState::MANAGED_TYPE_NETWORK, *vlist); 299 // UpdateObserved used to use kServiceWatchListProperty for TYPE_NETWORK, 300 // however that prevents us from receiving Strength updates from inactive 301 // networks. The overhead for observing all services is not unreasonable 302 // (and we limit the max number of observed services to kMaxObserved). 303 UpdateObserved(ManagedState::MANAGED_TYPE_NETWORK, *vlist); 304 } 305 } else if (key == shill::kServiceCompleteListProperty) { 306 const base::ListValue* vlist = GetListValue(key, value); 307 if (vlist) { 308 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_FAVORITE, *vlist); 309 UpdateProperties(ManagedState::MANAGED_TYPE_FAVORITE, *vlist); 310 } 311 } else if (key == shill::kDevicesProperty) { 312 const base::ListValue* vlist = GetListValue(key, value); 313 if (vlist) { 314 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_DEVICE, *vlist); 315 UpdateProperties(ManagedState::MANAGED_TYPE_DEVICE, *vlist); 316 UpdateObserved(ManagedState::MANAGED_TYPE_DEVICE, *vlist); 317 } 318 } else if (key == shill::kAvailableTechnologiesProperty) { 319 const base::ListValue* vlist = GetListValue(key, value); 320 if (vlist) 321 UpdateAvailableTechnologies(*vlist); 322 } else if (key == shill::kEnabledTechnologiesProperty) { 323 const base::ListValue* vlist = GetListValue(key, value); 324 if (vlist) 325 UpdateEnabledTechnologies(*vlist); 326 } else if (key == shill::kUninitializedTechnologiesProperty) { 327 const base::ListValue* vlist = GetListValue(key, value); 328 if (vlist) 329 UpdateUninitializedTechnologies(*vlist); 330 } else if (key == shill::kProfilesProperty) { 331 listener_->ProfileListChanged(); 332 } else if (key == shill::kCheckPortalListProperty) { 333 std::string check_portal_list; 334 if (value.GetAsString(&check_portal_list)) 335 listener_->CheckPortalListChanged(check_portal_list); 336 } else { 337 VLOG(2) << "Ignored Manager Property: " << key; 338 } 339} 340 341void ShillPropertyHandler::UpdateProperties(ManagedState::ManagedType type, 342 const base::ListValue& entries) { 343 std::set<std::string>& requested_updates = requested_updates_[type]; 344 std::set<std::string>& requested_service_updates = 345 requested_updates_[ManagedState::MANAGED_TYPE_NETWORK]; // For favorites 346 std::set<std::string> new_requested_updates; 347 NET_LOG_DEBUG( 348 base::StringPrintf("UpdateProperties: %" PRIuS, entries.GetSize()), 349 ManagedState::TypeToString(type)); 350 for (base::ListValue::const_iterator iter = entries.begin(); 351 iter != entries.end(); ++iter) { 352 std::string path; 353 (*iter)->GetAsString(&path); 354 if (path.empty()) 355 continue; 356 if (type == ManagedState::MANAGED_TYPE_FAVORITE && 357 requested_service_updates.count(path) > 0) 358 continue; // Update already requested 359 360 // We add a special case for devices here to work around an issue in shill 361 // that prevents it from sending property changed signals for cellular 362 // devices (see crbug.com/321854). 363 if (type == ManagedState::MANAGED_TYPE_DEVICE || 364 requested_updates.find(path) == requested_updates.end()) 365 RequestProperties(type, path); 366 new_requested_updates.insert(path); 367 } 368 requested_updates.swap(new_requested_updates); 369} 370 371void ShillPropertyHandler::UpdateObserved(ManagedState::ManagedType type, 372 const base::ListValue& entries) { 373 DCHECK(type == ManagedState::MANAGED_TYPE_NETWORK || 374 type == ManagedState::MANAGED_TYPE_DEVICE); 375 ShillPropertyObserverMap& observer_map = 376 (type == ManagedState::MANAGED_TYPE_NETWORK) 377 ? observed_networks_ : observed_devices_; 378 ShillPropertyObserverMap new_observed; 379 for (base::ListValue::const_iterator iter1 = entries.begin(); 380 iter1 != entries.end(); ++iter1) { 381 std::string path; 382 (*iter1)->GetAsString(&path); 383 if (path.empty()) 384 continue; 385 ShillPropertyObserverMap::iterator iter2 = observer_map.find(path); 386 if (iter2 != observer_map.end()) { 387 new_observed[path] = iter2->second; 388 } else { 389 // Create an observer for future updates. 390 new_observed[path] = new ShillPropertyObserver( 391 type, path, base::Bind( 392 &ShillPropertyHandler::PropertyChangedCallback, AsWeakPtr())); 393 } 394 observer_map.erase(path); 395 // Limit the number of observed services. 396 if (new_observed.size() >= kMaxObserved) 397 break; 398 } 399 // Delete network service observers still in observer_map. 400 for (ShillPropertyObserverMap::iterator iter = observer_map.begin(); 401 iter != observer_map.end(); ++iter) { 402 delete iter->second; 403 } 404 observer_map.swap(new_observed); 405} 406 407void ShillPropertyHandler::UpdateAvailableTechnologies( 408 const base::ListValue& technologies) { 409 available_technologies_.clear(); 410 NET_LOG_EVENT("AvailableTechnologiesChanged", 411 base::StringPrintf("Size: %" PRIuS, technologies.GetSize())); 412 for (base::ListValue::const_iterator iter = technologies.begin(); 413 iter != technologies.end(); ++iter) { 414 std::string technology; 415 (*iter)->GetAsString(&technology); 416 DCHECK(!technology.empty()); 417 available_technologies_.insert(technology); 418 } 419 listener_->TechnologyListChanged(); 420} 421 422void ShillPropertyHandler::UpdateEnabledTechnologies( 423 const base::ListValue& technologies) { 424 enabled_technologies_.clear(); 425 NET_LOG_EVENT("EnabledTechnologiesChanged", 426 base::StringPrintf("Size: %" PRIuS, technologies.GetSize())); 427 for (base::ListValue::const_iterator iter = technologies.begin(); 428 iter != technologies.end(); ++iter) { 429 std::string technology; 430 (*iter)->GetAsString(&technology); 431 DCHECK(!technology.empty()); 432 enabled_technologies_.insert(technology); 433 enabling_technologies_.erase(technology); 434 } 435 listener_->TechnologyListChanged(); 436} 437 438void ShillPropertyHandler::UpdateUninitializedTechnologies( 439 const base::ListValue& technologies) { 440 uninitialized_technologies_.clear(); 441 NET_LOG_EVENT("UninitializedTechnologiesChanged", 442 base::StringPrintf("Size: %" PRIuS, technologies.GetSize())); 443 for (base::ListValue::const_iterator iter = technologies.begin(); 444 iter != technologies.end(); ++iter) { 445 std::string technology; 446 (*iter)->GetAsString(&technology); 447 DCHECK(!technology.empty()); 448 uninitialized_technologies_.insert(technology); 449 } 450 listener_->TechnologyListChanged(); 451} 452 453void ShillPropertyHandler::EnableTechnologyFailed( 454 const std::string& technology, 455 const network_handler::ErrorCallback& error_callback, 456 const std::string& dbus_error_name, 457 const std::string& dbus_error_message) { 458 enabling_technologies_.erase(technology); 459 network_handler::ShillErrorCallbackFunction( 460 "EnableTechnology Failed", 461 technology, error_callback, 462 dbus_error_name, dbus_error_message); 463} 464 465void ShillPropertyHandler::GetPropertiesCallback( 466 ManagedState::ManagedType type, 467 const std::string& path, 468 DBusMethodCallStatus call_status, 469 const base::DictionaryValue& properties) { 470 NET_LOG_DEBUG("GetPropertiesCallback: " + ManagedState::TypeToString(type), 471 path); 472 pending_updates_[type].erase(path); 473 if (call_status != DBUS_METHOD_CALL_SUCCESS) { 474 // The shill service no longer exists. This can happen when a network 475 // has been removed. 476 NET_LOG_DEBUG("Failed to get properties", 477 base::StringPrintf("%s: %d", path.c_str(), call_status)); 478 return; 479 } 480 // Update Favorite properties for networks in the Services list. 481 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 482 // Only networks with a ProfilePath set are Favorites. 483 std::string profile_path; 484 properties.GetStringWithoutPathExpansion( 485 shill::kProfileProperty, &profile_path); 486 if (!profile_path.empty()) { 487 listener_->UpdateManagedStateProperties( 488 ManagedState::MANAGED_TYPE_FAVORITE, path, properties); 489 } 490 } 491 listener_->UpdateManagedStateProperties(type, path, properties); 492 // Request IPConfig parameters for networks. 493 if (type == ManagedState::MANAGED_TYPE_NETWORK && 494 properties.HasKey(shill::kIPConfigProperty)) { 495 std::string ip_config_path; 496 if (properties.GetString(shill::kIPConfigProperty, &ip_config_path)) { 497 DBusThreadManager::Get()->GetShillIPConfigClient()->GetProperties( 498 dbus::ObjectPath(ip_config_path), 499 base::Bind(&ShillPropertyHandler::GetIPConfigCallback, 500 AsWeakPtr(), path)); 501 } 502 } 503 504 // Notify the listener only when all updates for that type have completed. 505 if (pending_updates_[type].size() == 0) { 506 listener_->ManagedStateListChanged(type); 507 // Notify that Favorites have changed when notifying for Networks if there 508 // are no additional Favorite updates pending. 509 if (type == ManagedState::MANAGED_TYPE_NETWORK && 510 pending_updates_[ManagedState::MANAGED_TYPE_FAVORITE].size() == 0) { 511 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_FAVORITE); 512 } 513 } 514} 515 516void ShillPropertyHandler::PropertyChangedCallback( 517 ManagedState::ManagedType type, 518 const std::string& path, 519 const std::string& key, 520 const base::Value& value) { 521 if (type == ManagedState::MANAGED_TYPE_NETWORK) 522 NetworkServicePropertyChangedCallback(path, key, value); 523 else if (type == ManagedState::MANAGED_TYPE_DEVICE) 524 NetworkDevicePropertyChangedCallback(path, key, value); 525 else 526 NOTREACHED(); 527} 528 529void ShillPropertyHandler::NetworkServicePropertyChangedCallback( 530 const std::string& path, 531 const std::string& key, 532 const base::Value& value) { 533 if (key == shill::kIPConfigProperty) { 534 // Request the IPConfig for the network and update network properties 535 // when the request completes. 536 std::string ip_config_path; 537 value.GetAsString(&ip_config_path); 538 DCHECK(!ip_config_path.empty()); 539 DBusThreadManager::Get()->GetShillIPConfigClient()->GetProperties( 540 dbus::ObjectPath(ip_config_path), 541 base::Bind(&ShillPropertyHandler::GetIPConfigCallback, 542 AsWeakPtr(), path)); 543 } else { 544 listener_->UpdateNetworkServiceProperty(path, key, value); 545 } 546} 547 548void ShillPropertyHandler::GetIPConfigCallback( 549 const std::string& service_path, 550 DBusMethodCallStatus call_status, 551 const base::DictionaryValue& properties) { 552 if (call_status != DBUS_METHOD_CALL_SUCCESS) { 553 NET_LOG_ERROR("Failed to get IP Config properties", 554 base::StringPrintf("%s: %d", 555 service_path.c_str(), call_status)); 556 return; 557 } 558 UpdateIPConfigProperty(service_path, properties, shill::kAddressProperty); 559 UpdateIPConfigProperty(service_path, properties, shill::kNameServersProperty); 560 UpdateIPConfigProperty(service_path, properties, shill::kPrefixlenProperty); 561 UpdateIPConfigProperty(service_path, properties, shill::kGatewayProperty); 562 UpdateIPConfigProperty(service_path, properties, 563 shill::kWebProxyAutoDiscoveryUrlProperty); 564} 565 566void ShillPropertyHandler::UpdateIPConfigProperty( 567 const std::string& service_path, 568 const base::DictionaryValue& properties, 569 const char* property) { 570 const base::Value* value; 571 if (!properties.GetWithoutPathExpansion(property, &value)) { 572 LOG(ERROR) << "Failed to get IPConfig property: " << property 573 << ", for: " << service_path; 574 return; 575 } 576 listener_->UpdateNetworkServiceProperty( 577 service_path, NetworkState::IPConfigProperty(property), *value); 578} 579 580void ShillPropertyHandler::NetworkDevicePropertyChangedCallback( 581 const std::string& path, 582 const std::string& key, 583 const base::Value& value) { 584 listener_->UpdateDeviceProperty(path, key, value); 585} 586 587} // namespace internal 588} // namespace chromeos 589