managed_network_configuration_handler_impl.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chromeos/network/managed_network_configuration_handler_impl.h" 6 7#include <set> 8#include <vector> 9 10#include "base/bind.h" 11#include "base/guid.h" 12#include "base/location.h" 13#include "base/logging.h" 14#include "base/memory/ref_counted.h" 15#include "base/memory/scoped_ptr.h" 16#include "base/stl_util.h" 17#include "base/values.h" 18#include "chromeos/dbus/shill_manager_client.h" 19#include "chromeos/dbus/shill_profile_client.h" 20#include "chromeos/dbus/shill_service_client.h" 21#include "chromeos/network/device_state.h" 22#include "chromeos/network/favorite_state.h" 23#include "chromeos/network/network_configuration_handler.h" 24#include "chromeos/network/network_device_handler.h" 25#include "chromeos/network/network_event_log.h" 26#include "chromeos/network/network_policy_observer.h" 27#include "chromeos/network/network_profile.h" 28#include "chromeos/network/network_profile_handler.h" 29#include "chromeos/network/network_state.h" 30#include "chromeos/network/network_state_handler.h" 31#include "chromeos/network/network_ui_data.h" 32#include "chromeos/network/onc/onc_merger.h" 33#include "chromeos/network/onc/onc_signature.h" 34#include "chromeos/network/onc/onc_translator.h" 35#include "chromeos/network/onc/onc_validator.h" 36#include "chromeos/network/policy_util.h" 37#include "chromeos/network/shill_property_util.h" 38#include "components/onc/onc_constants.h" 39#include "third_party/cros_system_api/dbus/service_constants.h" 40 41namespace chromeos { 42 43namespace { 44 45typedef std::map<std::string, const base::DictionaryValue*> GuidToPolicyMap; 46 47// These are error strings used for error callbacks. None of these error 48// messages are user-facing: they should only appear in logs. 49const char kInvalidUserSettings[] = "InvalidUserSettings"; 50const char kNetworkAlreadyConfigured[] = "NetworkAlreadyConfigured"; 51const char kPoliciesNotInitialized[] = "PoliciesNotInitialized"; 52const char kProfileNotInitialized[] = "ProflieNotInitialized"; 53const char kSetOnUnconfiguredNetwork[] = "SetCalledOnUnconfiguredNetwork"; 54const char kUnknownProfilePath[] = "UnknownProfilePath"; 55const char kUnknownNetwork[] = "UnknownNetwork"; 56 57std::string ToDebugString(::onc::ONCSource source, 58 const std::string& userhash) { 59 return source == ::onc::ONC_SOURCE_USER_POLICY ? 60 ("user policy of " + userhash) : "device policy"; 61} 62 63void InvokeErrorCallback(const std::string& service_path, 64 const network_handler::ErrorCallback& error_callback, 65 const std::string& error_name) { 66 std::string error_msg = "ManagedConfig Error: " + error_name; 67 NET_LOG_ERROR(error_msg, service_path); 68 network_handler::RunErrorCallback( 69 error_callback, service_path, error_name, error_msg); 70} 71 72void LogErrorWithDict(const tracked_objects::Location& from_where, 73 const std::string& error_name, 74 scoped_ptr<base::DictionaryValue> error_data) { 75 network_event_log::internal::AddEntry( 76 from_where.file_name(), from_where.line_number(), 77 network_event_log::LOG_LEVEL_ERROR, 78 error_name, ""); 79} 80 81const base::DictionaryValue* GetByGUID(const GuidToPolicyMap& policies, 82 const std::string& guid) { 83 GuidToPolicyMap::const_iterator it = policies.find(guid); 84 if (it == policies.end()) 85 return NULL; 86 return it->second; 87} 88 89} // namespace 90 91struct ManagedNetworkConfigurationHandlerImpl::Policies { 92 ~Policies(); 93 94 GuidToPolicyMap per_network_config; 95 base::DictionaryValue global_network_config; 96}; 97 98ManagedNetworkConfigurationHandlerImpl::Policies::~Policies() { 99 STLDeleteValues(&per_network_config); 100} 101 102void ManagedNetworkConfigurationHandlerImpl::AddObserver( 103 NetworkPolicyObserver* observer) { 104 observers_.AddObserver(observer); 105} 106 107void ManagedNetworkConfigurationHandlerImpl::RemoveObserver( 108 NetworkPolicyObserver* observer) { 109 observers_.RemoveObserver(observer); 110} 111 112// GetManagedProperties 113 114void ManagedNetworkConfigurationHandlerImpl::GetManagedProperties( 115 const std::string& userhash, 116 const std::string& service_path, 117 const network_handler::DictionaryResultCallback& callback, 118 const network_handler::ErrorCallback& error_callback) { 119 if (!GetPoliciesForUser(userhash) || !GetPoliciesForUser(std::string())) { 120 InvokeErrorCallback(service_path, error_callback, kPoliciesNotInitialized); 121 return; 122 } 123 network_configuration_handler_->GetProperties( 124 service_path, 125 base::Bind( 126 &ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback, 127 weak_ptr_factory_.GetWeakPtr(), 128 base::Bind( 129 &ManagedNetworkConfigurationHandlerImpl::SendManagedProperties, 130 weak_ptr_factory_.GetWeakPtr(), 131 callback, 132 error_callback)), 133 error_callback); 134} 135 136void ManagedNetworkConfigurationHandlerImpl::SendManagedProperties( 137 const network_handler::DictionaryResultCallback& callback, 138 const network_handler::ErrorCallback& error_callback, 139 const std::string& service_path, 140 scoped_ptr<base::DictionaryValue> shill_properties) { 141 std::string profile_path; 142 shill_properties->GetStringWithoutPathExpansion(shill::kProfileProperty, 143 &profile_path); 144 const NetworkProfile* profile = 145 network_profile_handler_->GetProfileForPath(profile_path); 146 if (!profile) 147 NET_LOG_ERROR("No profile for service: " + profile_path, service_path); 148 149 scoped_ptr<NetworkUIData> ui_data = 150 shill_property_util::GetUIDataFromProperties(*shill_properties); 151 152 const base::DictionaryValue* user_settings = NULL; 153 const base::DictionaryValue* shared_settings = NULL; 154 155 if (ui_data && profile) { 156 if (profile->type() == NetworkProfile::TYPE_SHARED) 157 shared_settings = ui_data->user_settings(); 158 else if (profile->type() == NetworkProfile::TYPE_USER) 159 user_settings = ui_data->user_settings(); 160 else 161 NOTREACHED(); 162 } else if (profile) { 163 NET_LOG_ERROR("Service contains empty or invalid UIData", service_path); 164 // TODO(pneubeck): add a conversion of user configured entries of old 165 // ChromeOS versions. We will have to use a heuristic to determine which 166 // properties _might_ be user configured. 167 } 168 169 scoped_ptr<base::DictionaryValue> active_settings( 170 onc::TranslateShillServiceToONCPart( 171 *shill_properties, 172 &onc::kNetworkWithStateSignature)); 173 174 std::string guid; 175 active_settings->GetStringWithoutPathExpansion(::onc::network_config::kGUID, 176 &guid); 177 178 const base::DictionaryValue* user_policy = NULL; 179 const base::DictionaryValue* device_policy = NULL; 180 if (!guid.empty() && profile) { 181 const Policies* policies = GetPoliciesForProfile(*profile); 182 if (!policies) { 183 InvokeErrorCallback( 184 service_path, error_callback, kPoliciesNotInitialized); 185 return; 186 } 187 const base::DictionaryValue* policy = 188 GetByGUID(policies->per_network_config, guid); 189 if (profile->type() == NetworkProfile::TYPE_SHARED) 190 device_policy = policy; 191 else if (profile->type() == NetworkProfile::TYPE_USER) 192 user_policy = policy; 193 else 194 NOTREACHED(); 195 } 196 197 // This call also removes credentials from policies. 198 scoped_ptr<base::DictionaryValue> augmented_properties = 199 onc::MergeSettingsAndPoliciesToAugmented( 200 onc::kNetworkConfigurationSignature, 201 user_policy, 202 device_policy, 203 user_settings, 204 shared_settings, 205 active_settings.get()); 206 callback.Run(service_path, *augmented_properties); 207} 208 209// GetProperties 210 211void ManagedNetworkConfigurationHandlerImpl::GetProperties( 212 const std::string& service_path, 213 const network_handler::DictionaryResultCallback& callback, 214 const network_handler::ErrorCallback& error_callback) { 215 network_configuration_handler_->GetProperties( 216 service_path, 217 base::Bind( 218 &ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback, 219 weak_ptr_factory_.GetWeakPtr(), 220 base::Bind(&ManagedNetworkConfigurationHandlerImpl::SendProperties, 221 weak_ptr_factory_.GetWeakPtr(), 222 callback, 223 error_callback)), 224 error_callback); 225} 226 227void ManagedNetworkConfigurationHandlerImpl::SendProperties( 228 const network_handler::DictionaryResultCallback& callback, 229 const network_handler::ErrorCallback& error_callback, 230 const std::string& service_path, 231 scoped_ptr<base::DictionaryValue> shill_properties) { 232 scoped_ptr<base::DictionaryValue> onc_network( 233 onc::TranslateShillServiceToONCPart(*shill_properties, 234 &onc::kNetworkWithStateSignature)); 235 callback.Run(service_path, *onc_network); 236} 237 238// SetProperties 239 240void ManagedNetworkConfigurationHandlerImpl::SetProperties( 241 const std::string& service_path, 242 const base::DictionaryValue& user_settings, 243 const base::Closure& callback, 244 const network_handler::ErrorCallback& error_callback) const { 245 const FavoriteState* state = 246 network_state_handler_->GetFavoriteStateFromServicePath( 247 service_path, true /* configured_only */); 248 if (!state) { 249 InvokeErrorCallback(service_path, error_callback, kUnknownNetwork); 250 return; 251 } 252 253 std::string guid = state->guid(); 254 if (guid.empty()) { 255 // TODO(pneubeck): create an initial configuration in this case. As for 256 // CreateConfiguration, user settings from older ChromeOS versions have to 257 // determined here. 258 InvokeErrorCallback( 259 service_path, error_callback, kSetOnUnconfiguredNetwork); 260 return; 261 } 262 263 const std::string& profile_path = state->profile_path(); 264 const NetworkProfile *profile = 265 network_profile_handler_->GetProfileForPath(profile_path); 266 if (!profile) { 267 InvokeErrorCallback(service_path, error_callback, kUnknownProfilePath); 268 return; 269 } 270 271 VLOG(2) << "SetProperties: Found GUID " << guid << " and profile " 272 << profile->ToDebugString(); 273 274 const Policies* policies = GetPoliciesForProfile(*profile); 275 if (!policies) { 276 InvokeErrorCallback(service_path, error_callback, kPoliciesNotInitialized); 277 return; 278 } 279 280 // Validate the ONC dictionary. We are liberal and ignore unknown field 281 // names. User settings are only partial ONC, thus we ignore missing fields. 282 onc::Validator validator(false, // Ignore unknown fields. 283 false, // Ignore invalid recommended field names. 284 false, // Ignore missing fields. 285 false); // This ONC does not come from policy. 286 287 onc::Validator::Result validation_result; 288 scoped_ptr<base::DictionaryValue> validated_user_settings = 289 validator.ValidateAndRepairObject( 290 &onc::kNetworkConfigurationSignature, 291 user_settings, 292 &validation_result); 293 294 if (validation_result == onc::Validator::INVALID) { 295 InvokeErrorCallback(service_path, error_callback, kInvalidUserSettings); 296 return; 297 } 298 if (validation_result == onc::Validator::VALID_WITH_WARNINGS) 299 LOG(WARNING) << "Validation of ONC user settings produced warnings."; 300 301 const base::DictionaryValue* policy = 302 GetByGUID(policies->per_network_config, guid); 303 VLOG(2) << "This configuration is " << (policy ? "" : "not ") << "managed."; 304 305 scoped_ptr<base::DictionaryValue> shill_dictionary( 306 policy_util::CreateShillConfiguration( 307 *profile, guid, policy, validated_user_settings.get())); 308 309 network_configuration_handler_->SetProperties( 310 service_path, *shill_dictionary, callback, error_callback); 311} 312 313void ManagedNetworkConfigurationHandlerImpl::CreateConfiguration( 314 const std::string& userhash, 315 const base::DictionaryValue& properties, 316 const network_handler::StringResultCallback& callback, 317 const network_handler::ErrorCallback& error_callback) const { 318 const Policies* policies = GetPoliciesForUser(userhash); 319 if (!policies) { 320 InvokeErrorCallback("", error_callback, kPoliciesNotInitialized); 321 return; 322 } 323 324 if (policy_util::FindMatchingPolicy(policies->per_network_config, 325 properties)) { 326 InvokeErrorCallback("", error_callback, kNetworkAlreadyConfigured); 327 return; 328 } 329 330 const NetworkProfile* profile = 331 network_profile_handler_->GetProfileForUserhash(userhash); 332 if (!profile) { 333 InvokeErrorCallback("", error_callback, kProfileNotInitialized); 334 return; 335 } 336 337 // TODO(pneubeck): In case of WiFi, check that no other configuration for the 338 // same {SSID, mode, security} exists. We don't support such multiple 339 // configurations, yet. 340 341 // Generate a new GUID for this configuration. Ignore the maybe provided GUID 342 // in |properties| as it is not our own and from an untrusted source. 343 std::string guid = base::GenerateGUID(); 344 scoped_ptr<base::DictionaryValue> shill_dictionary( 345 policy_util::CreateShillConfiguration( 346 *profile, guid, NULL /*no policy*/, &properties)); 347 348 network_configuration_handler_->CreateConfiguration( 349 *shill_dictionary, callback, error_callback); 350} 351 352void ManagedNetworkConfigurationHandlerImpl::RemoveConfiguration( 353 const std::string& service_path, 354 const base::Closure& callback, 355 const network_handler::ErrorCallback& error_callback) const { 356 network_configuration_handler_->RemoveConfiguration( 357 service_path, callback, error_callback); 358} 359 360void ManagedNetworkConfigurationHandlerImpl::SetPolicy( 361 ::onc::ONCSource onc_source, 362 const std::string& userhash, 363 const base::ListValue& network_configs_onc, 364 const base::DictionaryValue& global_network_config) { 365 VLOG(1) << "Setting policies from " << ToDebugString(onc_source, userhash) 366 << "."; 367 368 // |userhash| must be empty for device policies. 369 DCHECK(onc_source != ::onc::ONC_SOURCE_DEVICE_POLICY || 370 userhash.empty()); 371 Policies* policies = NULL; 372 if (ContainsKey(policies_by_user_, userhash)) { 373 policies = policies_by_user_[userhash].get(); 374 } else { 375 policies = new Policies; 376 policies_by_user_[userhash] = make_linked_ptr(policies); 377 } 378 379 policies->global_network_config.MergeDictionary(&global_network_config); 380 381 GuidToPolicyMap old_per_network_config; 382 policies->per_network_config.swap(old_per_network_config); 383 384 // This stores all GUIDs of policies that have changed or are new. 385 std::set<std::string> modified_policies; 386 387 for (base::ListValue::const_iterator it = network_configs_onc.begin(); 388 it != network_configs_onc.end(); ++it) { 389 const base::DictionaryValue* network = NULL; 390 (*it)->GetAsDictionary(&network); 391 DCHECK(network); 392 393 std::string guid; 394 network->GetStringWithoutPathExpansion(::onc::network_config::kGUID, &guid); 395 DCHECK(!guid.empty()); 396 397 if (policies->per_network_config.count(guid) > 0) { 398 NET_LOG_ERROR("ONC from " + ToDebugString(onc_source, userhash) + 399 " contains several entries for the same GUID ", guid); 400 delete policies->per_network_config[guid]; 401 } 402 const base::DictionaryValue* new_entry = network->DeepCopy(); 403 policies->per_network_config[guid] = new_entry; 404 405 const base::DictionaryValue* old_entry = old_per_network_config[guid]; 406 if (!old_entry || !old_entry->Equals(new_entry)) 407 modified_policies.insert(guid); 408 } 409 410 STLDeleteValues(&old_per_network_config); 411 412 const NetworkProfile* profile = 413 network_profile_handler_->GetProfileForUserhash(userhash); 414 if (profile) { 415 scoped_refptr<PolicyApplicator> applicator = 416 new PolicyApplicator(weak_ptr_factory_.GetWeakPtr(), 417 *profile, 418 policies->per_network_config, 419 policies->global_network_config, 420 &modified_policies); 421 applicator->Run(); 422 } else { 423 VLOG(1) << "The relevant Shill profile isn't initialized yet, postponing " 424 << "policy application."; 425 // See OnProfileAdded. 426 } 427 428 FOR_EACH_OBSERVER(NetworkPolicyObserver, observers_, PolicyChanged(userhash)); 429} 430 431void ManagedNetworkConfigurationHandlerImpl::OnProfileAdded( 432 const NetworkProfile& profile) { 433 VLOG(1) << "Adding profile " << profile.ToDebugString() << "'."; 434 435 const Policies* policies = GetPoliciesForProfile(profile); 436 if (!policies) { 437 VLOG(1) << "The relevant policy is not initialized, " 438 << "postponing policy application."; 439 // See SetPolicy. 440 return; 441 } 442 443 std::set<std::string> policy_guids; 444 for (GuidToPolicyMap::const_iterator it = 445 policies->per_network_config.begin(); 446 it != policies->per_network_config.end(); ++it) { 447 policy_guids.insert(it->first); 448 } 449 450 scoped_refptr<PolicyApplicator> applicator = 451 new PolicyApplicator(weak_ptr_factory_.GetWeakPtr(), 452 profile, 453 policies->per_network_config, 454 policies->global_network_config, 455 &policy_guids); 456 applicator->Run(); 457} 458 459void ManagedNetworkConfigurationHandlerImpl::OnProfileRemoved( 460 const NetworkProfile& profile) { 461 // Nothing to do in this case. 462} 463 464void ManagedNetworkConfigurationHandlerImpl::CreateConfigurationFromPolicy( 465 const base::DictionaryValue& shill_properties) { 466 network_configuration_handler_->CreateConfiguration( 467 shill_properties, 468 base::Bind( 469 &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork, 470 weak_ptr_factory_.GetWeakPtr()), 471 base::Bind(&LogErrorWithDict, FROM_HERE)); 472} 473 474void ManagedNetworkConfigurationHandlerImpl:: 475 UpdateExistingConfigurationWithPropertiesFromPolicy( 476 const base::DictionaryValue& existing_properties, 477 const base::DictionaryValue& new_properties) { 478 base::DictionaryValue shill_properties; 479 480 std::string profile; 481 existing_properties.GetStringWithoutPathExpansion(shill::kProfileProperty, 482 &profile); 483 if (profile.empty()) { 484 NET_LOG_ERROR("Missing profile property", 485 shill_property_util::GetNetworkIdFromProperties( 486 existing_properties)); 487 return; 488 } 489 shill_properties.SetStringWithoutPathExpansion(shill::kProfileProperty, 490 profile); 491 492 if (!shill_property_util::CopyIdentifyingProperties(existing_properties, 493 &shill_properties)) { 494 NET_LOG_ERROR("Missing identifying properties", 495 shill_property_util::GetNetworkIdFromProperties( 496 existing_properties)); 497 } 498 499 shill_properties.MergeDictionary(&new_properties); 500 501 network_configuration_handler_->CreateConfiguration( 502 shill_properties, 503 base::Bind( 504 &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork, 505 weak_ptr_factory_.GetWeakPtr()), 506 base::Bind(&LogErrorWithDict, FROM_HERE)); 507} 508 509void ManagedNetworkConfigurationHandlerImpl::OnPoliciesApplied() { 510 // After all policies were applied, trigger an update of the network lists. 511 if (network_state_handler_) 512 network_state_handler_->UpdateManagerProperties(); 513} 514 515const base::DictionaryValue* 516ManagedNetworkConfigurationHandlerImpl::FindPolicyByGUID( 517 const std::string userhash, 518 const std::string& guid, 519 ::onc::ONCSource* onc_source) const { 520 *onc_source = ::onc::ONC_SOURCE_NONE; 521 522 if (!userhash.empty()) { 523 const Policies* user_policies = GetPoliciesForUser(userhash); 524 if (user_policies) { 525 const base::DictionaryValue* policy = 526 GetByGUID(user_policies->per_network_config, guid); 527 if (policy) { 528 *onc_source = ::onc::ONC_SOURCE_USER_POLICY; 529 return policy; 530 } 531 } 532 } 533 534 const Policies* device_policies = GetPoliciesForUser(std::string()); 535 if (device_policies) { 536 const base::DictionaryValue* policy = 537 GetByGUID(device_policies->per_network_config, guid); 538 if (policy) { 539 *onc_source = ::onc::ONC_SOURCE_DEVICE_POLICY; 540 return policy; 541 } 542 } 543 544 return NULL; 545} 546 547const base::DictionaryValue* 548ManagedNetworkConfigurationHandlerImpl::GetGlobalConfigFromPolicy( 549 const std::string userhash) const { 550 const Policies* policies = GetPoliciesForUser(userhash); 551 if (!policies) 552 return NULL; 553 554 return &policies->global_network_config; 555} 556const base::DictionaryValue* 557ManagedNetworkConfigurationHandlerImpl::FindPolicyByGuidAndProfile( 558 const std::string& guid, 559 const std::string& profile_path) const { 560 const NetworkProfile* profile = 561 network_profile_handler_->GetProfileForPath(profile_path); 562 if (!profile) { 563 NET_LOG_ERROR("Profile path unknown:" + profile_path, guid); 564 return NULL; 565 } 566 567 const Policies* policies = GetPoliciesForProfile(*profile); 568 if (!policies) 569 return NULL; 570 571 return GetByGUID(policies->per_network_config, guid); 572} 573 574const ManagedNetworkConfigurationHandlerImpl::Policies* 575ManagedNetworkConfigurationHandlerImpl::GetPoliciesForUser( 576 const std::string& userhash) const { 577 UserToPoliciesMap::const_iterator it = policies_by_user_.find(userhash); 578 if (it == policies_by_user_.end()) 579 return NULL; 580 return it->second.get(); 581} 582 583const ManagedNetworkConfigurationHandlerImpl::Policies* 584ManagedNetworkConfigurationHandlerImpl::GetPoliciesForProfile( 585 const NetworkProfile& profile) const { 586 DCHECK(profile.type() != NetworkProfile::TYPE_SHARED || 587 profile.userhash.empty()); 588 return GetPoliciesForUser(profile.userhash); 589} 590 591ManagedNetworkConfigurationHandlerImpl::ManagedNetworkConfigurationHandlerImpl() 592 : network_state_handler_(NULL), 593 network_profile_handler_(NULL), 594 network_configuration_handler_(NULL), 595 network_device_handler_(NULL), 596 weak_ptr_factory_(this) {} 597 598ManagedNetworkConfigurationHandlerImpl:: 599 ~ManagedNetworkConfigurationHandlerImpl() { 600 network_profile_handler_->RemoveObserver(this); 601} 602 603void ManagedNetworkConfigurationHandlerImpl::Init( 604 NetworkStateHandler* network_state_handler, 605 NetworkProfileHandler* network_profile_handler, 606 NetworkConfigurationHandler* network_configuration_handler, 607 NetworkDeviceHandler* network_device_handler) { 608 network_state_handler_ = network_state_handler; 609 network_profile_handler_ = network_profile_handler; 610 network_configuration_handler_ = network_configuration_handler; 611 network_device_handler_ = network_device_handler; 612 network_profile_handler_->AddObserver(this); 613} 614 615void ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork( 616 const std::string& service_path) { 617 if (service_path.empty()) 618 return; 619 FOR_EACH_OBSERVER( 620 NetworkPolicyObserver, observers_, PolicyApplied(service_path)); 621} 622 623// Get{Managed}Properties helpers 624 625void ManagedNetworkConfigurationHandlerImpl::GetDeviceStateProperties( 626 const std::string& service_path, 627 base::DictionaryValue* properties) { 628 std::string connection_state; 629 properties->GetStringWithoutPathExpansion( 630 shill::kStateProperty, &connection_state); 631 if (!NetworkState::StateIsConnected(connection_state)) 632 return; 633 634 // Get the IPConfig properties from the device and store them in "IPConfigs" 635 // (plural) in the properties dictionary. (Note: Shill only provides a single 636 // "IPConfig" property for a network service, but a consumer of this API may 637 // want information about all ipv4 and ipv6 IPConfig properties. 638 std::string device; 639 properties->GetStringWithoutPathExpansion(shill::kDeviceProperty, &device); 640 const DeviceState* device_state = 641 network_state_handler_->GetDeviceState(device); 642 if (!device_state) { 643 NET_LOG_ERROR("GetDeviceProperties: no device: " + device, service_path); 644 return; 645 } 646 647 // Get the hardware MAC address from the DeviceState. 648 if (!device_state->mac_address().empty()) { 649 properties->SetStringWithoutPathExpansion( 650 shill::kAddressProperty, device_state->mac_address()); 651 } 652 653 // Convert IPConfig dictionary to a ListValue. 654 base::ListValue* ip_configs = new base::ListValue; 655 for (base::DictionaryValue::Iterator iter(device_state->ip_configs()); 656 !iter.IsAtEnd(); iter.Advance()) { 657 ip_configs->Append(iter.value().DeepCopy()); 658 } 659 properties->SetWithoutPathExpansion(shill::kIPConfigsProperty, ip_configs); 660} 661 662void ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback( 663 GetDevicePropertiesCallback send_callback, 664 const std::string& service_path, 665 const base::DictionaryValue& shill_properties) { 666 scoped_ptr<base::DictionaryValue> shill_properties_copy( 667 shill_properties.DeepCopy()); 668 669 // Add associated Device properties before the ONC translation. 670 GetDeviceStateProperties(service_path, shill_properties_copy.get()); 671 672 // Only request Device properties for Cellular networks with a valid device. 673 std::string type, device_path; 674 if (!network_device_handler_ || 675 !shill_properties_copy->GetStringWithoutPathExpansion( 676 shill::kTypeProperty, &type) || 677 type != shill::kTypeCellular || 678 !shill_properties_copy->GetStringWithoutPathExpansion( 679 shill::kDeviceProperty, &device_path) || 680 device_path.empty()) { 681 send_callback.Run(service_path, shill_properties_copy.Pass()); 682 return; 683 } 684 685 // Request the device properties. On success or failure pass (a possibly 686 // modified) |shill_properties| to |send_callback|. 687 scoped_ptr<base::DictionaryValue> shill_properties_copy_error_copy( 688 shill_properties_copy->DeepCopy()); 689 network_device_handler_->GetDeviceProperties( 690 device_path, 691 base::Bind(&ManagedNetworkConfigurationHandlerImpl:: 692 GetDevicePropertiesSuccess, 693 weak_ptr_factory_.GetWeakPtr(), 694 service_path, 695 base::Passed(&shill_properties_copy), 696 send_callback), 697 base::Bind(&ManagedNetworkConfigurationHandlerImpl:: 698 GetDevicePropertiesFailure, 699 weak_ptr_factory_.GetWeakPtr(), 700 service_path, 701 base::Passed(&shill_properties_copy_error_copy), 702 send_callback)); 703} 704 705void ManagedNetworkConfigurationHandlerImpl::GetDevicePropertiesSuccess( 706 const std::string& service_path, 707 scoped_ptr<base::DictionaryValue> network_properties, 708 GetDevicePropertiesCallback send_callback, 709 const std::string& device_path, 710 const base::DictionaryValue& device_properties) { 711 // Create a "Device" dictionary in |network_properties|. 712 network_properties->SetWithoutPathExpansion( 713 shill::kDeviceProperty, device_properties.DeepCopy()); 714 send_callback.Run(service_path, network_properties.Pass()); 715} 716 717void ManagedNetworkConfigurationHandlerImpl::GetDevicePropertiesFailure( 718 const std::string& service_path, 719 scoped_ptr<base::DictionaryValue> network_properties, 720 GetDevicePropertiesCallback send_callback, 721 const std::string& error_name, 722 scoped_ptr<base::DictionaryValue> error_data) { 723 NET_LOG_ERROR("Error getting device properties", service_path); 724 send_callback.Run(service_path, network_properties.Pass()); 725} 726 727 728} // namespace chromeos 729