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