| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chromeos/network/shill_property_handler.h" | 5 #include "chromeos/network/shill_property_handler.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 } | 204 } |
| 205 | 205 |
| 206 void ShillPropertyHandler::RequestProperties(ManagedState::ManagedType type, | 206 void ShillPropertyHandler::RequestProperties(ManagedState::ManagedType type, |
| 207 const std::string& path) { | 207 const std::string& path) { |
| 208 if (pending_updates_[type].find(path) != pending_updates_[type].end()) | 208 if (pending_updates_[type].find(path) != pending_updates_[type].end()) |
| 209 return; // Update already requested. | 209 return; // Update already requested. |
| 210 | 210 |
| 211 NET_LOG_DEBUG("Request Properties: " + ManagedState::TypeToString(type), | 211 NET_LOG_DEBUG("Request Properties: " + ManagedState::TypeToString(type), |
| 212 path); | 212 path); |
| 213 pending_updates_[type].insert(path); | 213 pending_updates_[type].insert(path); |
| 214 if (type == ManagedState::MANAGED_TYPE_NETWORK || | 214 if (type == ManagedState::MANAGED_TYPE_NETWORK) { |
| 215 type == ManagedState::MANAGED_TYPE_FAVORITE) { | |
| 216 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( | 215 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( |
| 217 dbus::ObjectPath(path), | 216 dbus::ObjectPath(path), |
| 218 base::Bind(&ShillPropertyHandler::GetPropertiesCallback, | 217 base::Bind(&ShillPropertyHandler::GetPropertiesCallback, |
| 219 AsWeakPtr(), type, path)); | 218 AsWeakPtr(), type, path)); |
| 220 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { | 219 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { |
| 221 DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties( | 220 DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties( |
| 222 dbus::ObjectPath(path), | 221 dbus::ObjectPath(path), |
| 223 base::Bind(&ShillPropertyHandler::GetPropertiesCallback, | 222 base::Bind(&ShillPropertyHandler::GetPropertiesCallback, |
| 224 AsWeakPtr(), type, path)); | 223 AsWeakPtr(), type, path)); |
| 225 } else { | 224 } else { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 250 for (base::DictionaryValue::Iterator iter(properties); | 249 for (base::DictionaryValue::Iterator iter(properties); |
| 251 !iter.IsAtEnd(); iter.Advance()) { | 250 !iter.IsAtEnd(); iter.Advance()) { |
| 252 // Defer updating Services until all other properties have been updated. | 251 // Defer updating Services until all other properties have been updated. |
| 253 if (iter.key() == shill::kServicesProperty) | 252 if (iter.key() == shill::kServicesProperty) |
| 254 update_service_value = &iter.value(); | 253 update_service_value = &iter.value(); |
| 255 else if (iter.key() == shill::kServiceCompleteListProperty) | 254 else if (iter.key() == shill::kServiceCompleteListProperty) |
| 256 update_service_complete_value = &iter.value(); | 255 update_service_complete_value = &iter.value(); |
| 257 else | 256 else |
| 258 ManagerPropertyChanged(iter.key(), iter.value()); | 257 ManagerPropertyChanged(iter.key(), iter.value()); |
| 259 } | 258 } |
| 260 // Update Services which can safely assume other properties have been set. | 259 // Update Service lists after other Manager properties. Update |
| 261 if (update_service_value) | 260 // ServiceCompleteList first so that Services (visible) entries already exist. |
| 262 ManagerPropertyChanged(shill::kServicesProperty, *update_service_value); | |
| 263 // Update ServiceCompleteList which skips entries that have already been | |
| 264 // requested for Services. | |
| 265 if (update_service_complete_value) { | 261 if (update_service_complete_value) { |
| 266 ManagerPropertyChanged(shill::kServiceCompleteListProperty, | 262 ManagerPropertyChanged(shill::kServiceCompleteListProperty, |
| 267 *update_service_complete_value); | 263 *update_service_complete_value); |
| 268 } | 264 } |
| 265 if (update_service_value) |
| 266 ManagerPropertyChanged(shill::kServicesProperty, *update_service_value); |
| 269 | 267 |
| 270 CheckPendingStateListUpdates(""); | 268 CheckPendingStateListUpdates(""); |
| 271 } | 269 } |
| 272 | 270 |
| 273 void ShillPropertyHandler::CheckPendingStateListUpdates( | 271 void ShillPropertyHandler::CheckPendingStateListUpdates( |
| 274 const std::string& key) { | 272 const std::string& key) { |
| 275 // Once there are no pending updates, signal the state list changed callbacks. | 273 // Once there are no pending updates, signal the state list changed callbacks. |
| 276 if ((key.empty() || key == shill::kServicesProperty) && | 274 if ((key.empty() || key == shill::kServiceCompleteListProperty) && |
| 277 pending_updates_[ManagedState::MANAGED_TYPE_NETWORK].size() == 0) { | 275 pending_updates_[ManagedState::MANAGED_TYPE_NETWORK].size() == 0) { |
| 278 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_NETWORK); | 276 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_NETWORK); |
| 279 } | 277 } |
| 280 // Both Network update requests and Favorite update requests will affect | |
| 281 // the list of favorites, so wait for both to complete. | |
| 282 if ((key.empty() || key == shill::kServiceCompleteListProperty) && | |
| 283 pending_updates_[ManagedState::MANAGED_TYPE_NETWORK].size() == 0 && | |
| 284 pending_updates_[ManagedState::MANAGED_TYPE_FAVORITE].size() == 0) { | |
| 285 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_FAVORITE); | |
| 286 } | |
| 287 if ((key.empty() || key == shill::kDevicesProperty) && | 278 if ((key.empty() || key == shill::kDevicesProperty) && |
| 288 pending_updates_[ManagedState::MANAGED_TYPE_DEVICE].size() == 0) { | 279 pending_updates_[ManagedState::MANAGED_TYPE_DEVICE].size() == 0) { |
| 289 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_DEVICE); | 280 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_DEVICE); |
| 290 } | 281 } |
| 291 } | 282 } |
| 292 | 283 |
| 293 void ShillPropertyHandler::ManagerPropertyChanged(const std::string& key, | 284 void ShillPropertyHandler::ManagerPropertyChanged(const std::string& key, |
| 294 const base::Value& value) { | 285 const base::Value& value) { |
| 295 NET_LOG_DEBUG("ManagerPropertyChanged", key); | 286 NET_LOG_DEBUG("ManagerPropertyChanged", key); |
| 296 if (key == shill::kDefaultServiceProperty) { | 287 if (key == shill::kDefaultServiceProperty) { |
| 297 std::string service_path; | 288 std::string service_path; |
| 298 value.GetAsString(&service_path); | 289 value.GetAsString(&service_path); |
| 299 listener_->DefaultNetworkServiceChanged(service_path); | 290 listener_->DefaultNetworkServiceChanged(service_path); |
| 300 } else if (key == shill::kServicesProperty) { | 291 } else if (key == shill::kServicesProperty) { |
| 301 const base::ListValue* vlist = GetListValue(key, value); | 292 const base::ListValue* vlist = GetListValue(key, value); |
| 302 if (vlist) { | 293 if (vlist) { |
| 303 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_NETWORK, *vlist); | 294 // Update the visibility of networks in ServiceCompleteList. Note that |
| 304 UpdateProperties(ManagedState::MANAGED_TYPE_NETWORK, *vlist); | 295 // this relies on Shill emitting changes to ServiceCompleteList before |
| 296 // changes to Services. TODO(stevenjb): Eliminate this and rely on |
| 297 // Service.Visible instead. |
| 298 listener_->UpdateVisibleNetworks(*vlist); |
| 299 |
| 305 // UpdateObserved used to use kServiceWatchListProperty for TYPE_NETWORK, | 300 // UpdateObserved used to use kServiceWatchListProperty for TYPE_NETWORK, |
| 306 // however that prevents us from receiving Strength updates from inactive | 301 // however that prevents us from receiving Strength updates from inactive |
| 307 // networks. The overhead for observing all services is not unreasonable | 302 // networks. The overhead for observing all services is not unreasonable |
| 308 // (and we limit the max number of observed services to kMaxObserved). | 303 // (and we limit the max number of observed services to kMaxObserved). |
| 309 UpdateObserved(ManagedState::MANAGED_TYPE_NETWORK, *vlist); | 304 UpdateObserved(ManagedState::MANAGED_TYPE_NETWORK, *vlist); |
| 310 } | 305 } |
| 311 } else if (key == shill::kServiceCompleteListProperty) { | 306 } else if (key == shill::kServiceCompleteListProperty) { |
| 312 const base::ListValue* vlist = GetListValue(key, value); | 307 const base::ListValue* vlist = GetListValue(key, value); |
| 313 if (vlist) { | 308 if (vlist) { |
| 314 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_FAVORITE, *vlist); | 309 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_NETWORK, *vlist); |
| 315 UpdateProperties(ManagedState::MANAGED_TYPE_FAVORITE, *vlist); | 310 UpdateProperties(ManagedState::MANAGED_TYPE_NETWORK, *vlist); |
| 316 } | 311 } |
| 312 } else if (key == shill::kServiceWatchListProperty) { |
| 313 // Currently we ignore the watch list. |
| 317 } else if (key == shill::kDevicesProperty) { | 314 } else if (key == shill::kDevicesProperty) { |
| 318 const base::ListValue* vlist = GetListValue(key, value); | 315 const base::ListValue* vlist = GetListValue(key, value); |
| 319 if (vlist) { | 316 if (vlist) { |
| 320 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_DEVICE, *vlist); | 317 listener_->UpdateManagedList(ManagedState::MANAGED_TYPE_DEVICE, *vlist); |
| 321 UpdateProperties(ManagedState::MANAGED_TYPE_DEVICE, *vlist); | 318 UpdateProperties(ManagedState::MANAGED_TYPE_DEVICE, *vlist); |
| 322 UpdateObserved(ManagedState::MANAGED_TYPE_DEVICE, *vlist); | 319 UpdateObserved(ManagedState::MANAGED_TYPE_DEVICE, *vlist); |
| 323 } | 320 } |
| 324 } else if (key == shill::kAvailableTechnologiesProperty) { | 321 } else if (key == shill::kAvailableTechnologiesProperty) { |
| 325 const base::ListValue* vlist = GetListValue(key, value); | 322 const base::ListValue* vlist = GetListValue(key, value); |
| 326 if (vlist) | 323 if (vlist) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 340 if (value.GetAsString(&check_portal_list)) | 337 if (value.GetAsString(&check_portal_list)) |
| 341 listener_->CheckPortalListChanged(check_portal_list); | 338 listener_->CheckPortalListChanged(check_portal_list); |
| 342 } else { | 339 } else { |
| 343 VLOG(2) << "Ignored Manager Property: " << key; | 340 VLOG(2) << "Ignored Manager Property: " << key; |
| 344 } | 341 } |
| 345 } | 342 } |
| 346 | 343 |
| 347 void ShillPropertyHandler::UpdateProperties(ManagedState::ManagedType type, | 344 void ShillPropertyHandler::UpdateProperties(ManagedState::ManagedType type, |
| 348 const base::ListValue& entries) { | 345 const base::ListValue& entries) { |
| 349 std::set<std::string>& requested_updates = requested_updates_[type]; | 346 std::set<std::string>& requested_updates = requested_updates_[type]; |
| 350 std::set<std::string>& requested_service_updates = | |
| 351 requested_updates_[ManagedState::MANAGED_TYPE_NETWORK]; // For favorites | |
| 352 std::set<std::string> new_requested_updates; | 347 std::set<std::string> new_requested_updates; |
| 353 NET_LOG_DEBUG("UpdateProperties: " + ManagedState::TypeToString(type), | 348 NET_LOG_DEBUG("UpdateProperties: " + ManagedState::TypeToString(type), |
| 354 base::StringPrintf("%" PRIuS, entries.GetSize())); | 349 base::StringPrintf("%" PRIuS, entries.GetSize())); |
| 355 for (base::ListValue::const_iterator iter = entries.begin(); | 350 for (base::ListValue::const_iterator iter = entries.begin(); |
| 356 iter != entries.end(); ++iter) { | 351 iter != entries.end(); ++iter) { |
| 357 std::string path; | 352 std::string path; |
| 358 (*iter)->GetAsString(&path); | 353 (*iter)->GetAsString(&path); |
| 359 if (path.empty()) | 354 if (path.empty()) |
| 360 continue; | 355 continue; |
| 361 // Only request properties once. Favorites that are visible will be updated | |
| 362 // when the Network entry is updated. Since 'Services' is always processed | |
| 363 // before ServiceCompleteList, only Favorites that are not visible will be | |
| 364 // requested here, and GetPropertiesCallback() will only get called with | |
| 365 // type == FAVORITE for non-visible Favorites. | |
| 366 if (type == ManagedState::MANAGED_TYPE_FAVORITE && | |
| 367 requested_service_updates.count(path) > 0) { | |
| 368 continue; | |
| 369 } | |
| 370 | 356 |
| 371 // We add a special case for devices here to work around an issue in shill | 357 // We add a special case for devices here to work around an issue in shill |
| 372 // that prevents it from sending property changed signals for cellular | 358 // that prevents it from sending property changed signals for cellular |
| 373 // devices (see crbug.com/321854). | 359 // devices (see crbug.com/321854). |
| 374 if (type == ManagedState::MANAGED_TYPE_DEVICE || | 360 if (type == ManagedState::MANAGED_TYPE_DEVICE || |
| 375 requested_updates.find(path) == requested_updates.end()) | 361 requested_updates.find(path) == requested_updates.end()) { |
| 376 RequestProperties(type, path); | 362 RequestProperties(type, path); |
| 363 } |
| 377 new_requested_updates.insert(path); | 364 new_requested_updates.insert(path); |
| 378 } | 365 } |
| 379 requested_updates.swap(new_requested_updates); | 366 requested_updates.swap(new_requested_updates); |
| 380 } | 367 } |
| 381 | 368 |
| 382 void ShillPropertyHandler::UpdateObserved(ManagedState::ManagedType type, | 369 void ShillPropertyHandler::UpdateObserved(ManagedState::ManagedType type, |
| 383 const base::ListValue& entries) { | 370 const base::ListValue& entries) { |
| 384 DCHECK(type == ManagedState::MANAGED_TYPE_NETWORK || | |
| 385 type == ManagedState::MANAGED_TYPE_DEVICE); | |
| 386 ShillPropertyObserverMap& observer_map = | 371 ShillPropertyObserverMap& observer_map = |
| 387 (type == ManagedState::MANAGED_TYPE_NETWORK) | 372 (type == ManagedState::MANAGED_TYPE_NETWORK) |
| 388 ? observed_networks_ : observed_devices_; | 373 ? observed_networks_ : observed_devices_; |
| 389 ShillPropertyObserverMap new_observed; | 374 ShillPropertyObserverMap new_observed; |
| 390 for (base::ListValue::const_iterator iter1 = entries.begin(); | 375 for (base::ListValue::const_iterator iter1 = entries.begin(); |
| 391 iter1 != entries.end(); ++iter1) { | 376 iter1 != entries.end(); ++iter1) { |
| 392 std::string path; | 377 std::string path; |
| 393 (*iter1)->GetAsString(&path); | 378 (*iter1)->GetAsString(&path); |
| 394 if (path.empty()) | 379 if (path.empty()) |
| 395 continue; | 380 continue; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 NET_LOG_DEBUG("GetPropertiesCallback: " + ManagedState::TypeToString(type), | 469 NET_LOG_DEBUG("GetPropertiesCallback: " + ManagedState::TypeToString(type), |
| 485 path); | 470 path); |
| 486 pending_updates_[type].erase(path); | 471 pending_updates_[type].erase(path); |
| 487 if (call_status != DBUS_METHOD_CALL_SUCCESS) { | 472 if (call_status != DBUS_METHOD_CALL_SUCCESS) { |
| 488 // The shill service no longer exists. This can happen when a network | 473 // The shill service no longer exists. This can happen when a network |
| 489 // has been removed. | 474 // has been removed. |
| 490 NET_LOG_DEBUG("Failed to get properties", | 475 NET_LOG_DEBUG("Failed to get properties", |
| 491 base::StringPrintf("%s: %d", path.c_str(), call_status)); | 476 base::StringPrintf("%s: %d", path.c_str(), call_status)); |
| 492 return; | 477 return; |
| 493 } | 478 } |
| 494 // Update Favorite properties for networks in the Services list. Call this | |
| 495 // for all networks, regardless of whether or not Profile is set, because | |
| 496 // we track all networks in the Favorites list (even if they aren't saved | |
| 497 // in a Profile). See notes in UpdateProperties() and favorite_state.h. | |
| 498 if (type == ManagedState::MANAGED_TYPE_NETWORK) { | |
| 499 listener_->UpdateManagedStateProperties( | |
| 500 ManagedState::MANAGED_TYPE_FAVORITE, path, properties); | |
| 501 } | |
| 502 listener_->UpdateManagedStateProperties(type, path, properties); | 479 listener_->UpdateManagedStateProperties(type, path, properties); |
| 503 | 480 |
| 504 if (type == ManagedState::MANAGED_TYPE_NETWORK) { | 481 if (type == ManagedState::MANAGED_TYPE_NETWORK) { |
| 505 // Request IPConfig properties. | 482 // Request IPConfig properties. |
| 506 const base::Value* value; | 483 const base::Value* value; |
| 507 if (properties.GetWithoutPathExpansion(shill::kIPConfigProperty, &value)) | 484 if (properties.GetWithoutPathExpansion(shill::kIPConfigProperty, &value)) |
| 508 RequestIPConfig(type, path, *value); | 485 RequestIPConfig(type, path, *value); |
| 509 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { | 486 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { |
| 510 // Clear and request IPConfig properties for each entry in IPConfigs. | 487 // Clear and request IPConfig properties for each entry in IPConfigs. |
| 511 const base::Value* value; | 488 const base::Value* value; |
| 512 if (properties.GetWithoutPathExpansion(shill::kIPConfigsProperty, &value)) | 489 if (properties.GetWithoutPathExpansion(shill::kIPConfigsProperty, &value)) |
| 513 RequestIPConfigsList(type, path, *value); | 490 RequestIPConfigsList(type, path, *value); |
| 514 } | 491 } |
| 515 | 492 |
| 516 // Notify the listener only when all updates for that type have completed. | 493 // Notify the listener only when all updates for that type have completed. |
| 517 if (pending_updates_[type].size() == 0) { | 494 if (pending_updates_[type].size() == 0) |
| 518 listener_->ManagedStateListChanged(type); | 495 listener_->ManagedStateListChanged(type); |
| 519 // Notify that Favorites have changed when notifying for Networks if there | |
| 520 // are no additional Favorite updates pending. | |
| 521 if (type == ManagedState::MANAGED_TYPE_NETWORK && | |
| 522 pending_updates_[ManagedState::MANAGED_TYPE_FAVORITE].size() == 0) { | |
| 523 listener_->ManagedStateListChanged(ManagedState::MANAGED_TYPE_FAVORITE); | |
| 524 } | |
| 525 } | |
| 526 } | 496 } |
| 527 | 497 |
| 528 void ShillPropertyHandler::PropertyChangedCallback( | 498 void ShillPropertyHandler::PropertyChangedCallback( |
| 529 ManagedState::ManagedType type, | 499 ManagedState::ManagedType type, |
| 530 const std::string& path, | 500 const std::string& path, |
| 531 const std::string& key, | 501 const std::string& key, |
| 532 const base::Value& value) { | 502 const base::Value& value) { |
| 533 if (type == ManagedState::MANAGED_TYPE_NETWORK && | 503 if (type == ManagedState::MANAGED_TYPE_NETWORK && |
| 534 key == shill::kIPConfigProperty) { | 504 key == shill::kIPConfigProperty) { |
| 535 RequestIPConfig(type, path, value); | 505 RequestIPConfig(type, path, value); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 NET_LOG_ERROR("Failed to get IP Config properties", | 555 NET_LOG_ERROR("Failed to get IP Config properties", |
| 586 base::StringPrintf("%s: %d", path.c_str(), call_status)); | 556 base::StringPrintf("%s: %d", path.c_str(), call_status)); |
| 587 return; | 557 return; |
| 588 } | 558 } |
| 589 NET_LOG_EVENT("IP Config properties received", path); | 559 NET_LOG_EVENT("IP Config properties received", path); |
| 590 listener_->UpdateIPConfigProperties(type, path, ip_config_path, properties); | 560 listener_->UpdateIPConfigProperties(type, path, ip_config_path, properties); |
| 591 } | 561 } |
| 592 | 562 |
| 593 } // namespace internal | 563 } // namespace internal |
| 594 } // namespace chromeos | 564 } // namespace chromeos |
| OLD | NEW |