| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chromeos/network/managed_network_configuration_handler_impl.h" |
| |
| #include <set> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/guid.h" |
| #include "base/location.h" |
| #include "base/logging.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/stl_util.h" |
| #include "base/values.h" |
| #include "chromeos/dbus/shill_manager_client.h" |
| #include "chromeos/dbus/shill_profile_client.h" |
| #include "chromeos/dbus/shill_service_client.h" |
| #include "chromeos/network/device_state.h" |
| #include "chromeos/network/network_configuration_handler.h" |
| #include "chromeos/network/network_device_handler.h" |
| #include "chromeos/network/network_event_log.h" |
| #include "chromeos/network/network_policy_observer.h" |
| #include "chromeos/network/network_profile.h" |
| #include "chromeos/network/network_profile_handler.h" |
| #include "chromeos/network/network_state.h" |
| #include "chromeos/network/network_state_handler.h" |
| #include "chromeos/network/network_ui_data.h" |
| #include "chromeos/network/onc/onc_merger.h" |
| #include "chromeos/network/onc/onc_signature.h" |
| #include "chromeos/network/onc/onc_translator.h" |
| #include "chromeos/network/onc/onc_validator.h" |
| #include "chromeos/network/policy_util.h" |
| #include "chromeos/network/shill_property_util.h" |
| #include "components/onc/onc_constants.h" |
| #include "third_party/cros_system_api/dbus/service_constants.h" |
| |
| namespace chromeos { |
| |
| namespace { |
| |
| typedef std::map<std::string, const base::DictionaryValue*> GuidToPolicyMap; |
| |
| // These are error strings used for error callbacks. None of these error |
| // messages are user-facing: they should only appear in logs. |
| const char kInvalidUserSettings[] = "InvalidUserSettings"; |
| const char kNetworkAlreadyConfigured[] = "NetworkAlreadyConfigured"; |
| const char kPoliciesNotInitialized[] = "PoliciesNotInitialized"; |
| const char kProfileNotInitialized[] = "ProflieNotInitialized"; |
| const char kSetOnUnconfiguredNetwork[] = "SetCalledOnUnconfiguredNetwork"; |
| const char kUnknownProfilePath[] = "UnknownProfilePath"; |
| const char kUnknownNetwork[] = "UnknownNetwork"; |
| |
| std::string ToDebugString(::onc::ONCSource source, |
| const std::string& userhash) { |
| return source == ::onc::ONC_SOURCE_USER_POLICY ? |
| ("user policy of " + userhash) : "device policy"; |
| } |
| |
| void InvokeErrorCallback(const std::string& service_path, |
| const network_handler::ErrorCallback& error_callback, |
| const std::string& error_name) { |
| std::string error_msg = "ManagedConfig Error: " + error_name; |
| NET_LOG_ERROR(error_msg, service_path); |
| network_handler::RunErrorCallback( |
| error_callback, service_path, error_name, error_msg); |
| } |
| |
| void LogErrorWithDict(const tracked_objects::Location& from_where, |
| const std::string& error_name, |
| scoped_ptr<base::DictionaryValue> error_data) { |
| network_event_log::internal::AddEntry( |
| from_where.file_name(), from_where.line_number(), |
| network_event_log::LOG_LEVEL_ERROR, |
| error_name, ""); |
| } |
| |
| const base::DictionaryValue* GetByGUID(const GuidToPolicyMap& policies, |
| const std::string& guid) { |
| GuidToPolicyMap::const_iterator it = policies.find(guid); |
| if (it == policies.end()) |
| return NULL; |
| return it->second; |
| } |
| |
| } // namespace |
| |
| struct ManagedNetworkConfigurationHandlerImpl::Policies { |
| ~Policies(); |
| |
| GuidToPolicyMap per_network_config; |
| base::DictionaryValue global_network_config; |
| }; |
| |
| ManagedNetworkConfigurationHandlerImpl::Policies::~Policies() { |
| STLDeleteValues(&per_network_config); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::AddObserver( |
| NetworkPolicyObserver* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::RemoveObserver( |
| NetworkPolicyObserver* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| // GetManagedProperties |
| |
| void ManagedNetworkConfigurationHandlerImpl::GetManagedProperties( |
| const std::string& userhash, |
| const std::string& service_path, |
| const network_handler::DictionaryResultCallback& callback, |
| const network_handler::ErrorCallback& error_callback) { |
| if (!GetPoliciesForUser(userhash) || !GetPoliciesForUser(std::string())) { |
| InvokeErrorCallback(service_path, error_callback, kPoliciesNotInitialized); |
| return; |
| } |
| network_configuration_handler_->GetProperties( |
| service_path, |
| base::Bind( |
| &ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback, |
| weak_ptr_factory_.GetWeakPtr(), |
| base::Bind( |
| &ManagedNetworkConfigurationHandlerImpl::SendManagedProperties, |
| weak_ptr_factory_.GetWeakPtr(), |
| callback, |
| error_callback)), |
| error_callback); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::SendManagedProperties( |
| const network_handler::DictionaryResultCallback& callback, |
| const network_handler::ErrorCallback& error_callback, |
| const std::string& service_path, |
| scoped_ptr<base::DictionaryValue> shill_properties) { |
| std::string profile_path; |
| shill_properties->GetStringWithoutPathExpansion(shill::kProfileProperty, |
| &profile_path); |
| const NetworkProfile* profile = |
| network_profile_handler_->GetProfileForPath(profile_path); |
| if (!profile) |
| NET_LOG_ERROR("No profile for service: " + profile_path, service_path); |
| |
| scoped_ptr<NetworkUIData> ui_data = |
| shill_property_util::GetUIDataFromProperties(*shill_properties); |
| |
| const base::DictionaryValue* user_settings = NULL; |
| const base::DictionaryValue* shared_settings = NULL; |
| |
| if (ui_data && profile) { |
| if (profile->type() == NetworkProfile::TYPE_SHARED) |
| shared_settings = ui_data->user_settings(); |
| else if (profile->type() == NetworkProfile::TYPE_USER) |
| user_settings = ui_data->user_settings(); |
| else |
| NOTREACHED(); |
| } else if (profile) { |
| NET_LOG_ERROR("Service contains empty or invalid UIData", service_path); |
| // TODO(pneubeck): add a conversion of user configured entries of old |
| // ChromeOS versions. We will have to use a heuristic to determine which |
| // properties _might_ be user configured. |
| } |
| |
| scoped_ptr<base::DictionaryValue> active_settings( |
| onc::TranslateShillServiceToONCPart( |
| *shill_properties, |
| &onc::kNetworkWithStateSignature)); |
| |
| std::string guid; |
| active_settings->GetStringWithoutPathExpansion(::onc::network_config::kGUID, |
| &guid); |
| |
| const base::DictionaryValue* user_policy = NULL; |
| const base::DictionaryValue* device_policy = NULL; |
| if (!guid.empty() && profile) { |
| const Policies* policies = GetPoliciesForProfile(*profile); |
| if (!policies) { |
| InvokeErrorCallback( |
| service_path, error_callback, kPoliciesNotInitialized); |
| return; |
| } |
| const base::DictionaryValue* policy = |
| GetByGUID(policies->per_network_config, guid); |
| if (profile->type() == NetworkProfile::TYPE_SHARED) |
| device_policy = policy; |
| else if (profile->type() == NetworkProfile::TYPE_USER) |
| user_policy = policy; |
| else |
| NOTREACHED(); |
| } |
| |
| // This call also removes credentials from policies. |
| scoped_ptr<base::DictionaryValue> augmented_properties = |
| onc::MergeSettingsAndPoliciesToAugmented( |
| onc::kNetworkConfigurationSignature, |
| user_policy, |
| device_policy, |
| user_settings, |
| shared_settings, |
| active_settings.get()); |
| callback.Run(service_path, *augmented_properties); |
| } |
| |
| // GetProperties |
| |
| void ManagedNetworkConfigurationHandlerImpl::GetProperties( |
| const std::string& service_path, |
| const network_handler::DictionaryResultCallback& callback, |
| const network_handler::ErrorCallback& error_callback) { |
| network_configuration_handler_->GetProperties( |
| service_path, |
| base::Bind( |
| &ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback, |
| weak_ptr_factory_.GetWeakPtr(), |
| base::Bind(&ManagedNetworkConfigurationHandlerImpl::SendProperties, |
| weak_ptr_factory_.GetWeakPtr(), |
| callback, |
| error_callback)), |
| error_callback); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::SendProperties( |
| const network_handler::DictionaryResultCallback& callback, |
| const network_handler::ErrorCallback& error_callback, |
| const std::string& service_path, |
| scoped_ptr<base::DictionaryValue> shill_properties) { |
| scoped_ptr<base::DictionaryValue> onc_network( |
| onc::TranslateShillServiceToONCPart(*shill_properties, |
| &onc::kNetworkWithStateSignature)); |
| callback.Run(service_path, *onc_network); |
| } |
| |
| // SetProperties |
| |
| void ManagedNetworkConfigurationHandlerImpl::SetProperties( |
| const std::string& service_path, |
| const base::DictionaryValue& user_settings, |
| const base::Closure& callback, |
| const network_handler::ErrorCallback& error_callback) const { |
| const NetworkState* state = |
| network_state_handler_->GetNetworkStateFromServicePath( |
| service_path, true /* configured_only */); |
| if (!state) { |
| InvokeErrorCallback(service_path, error_callback, kUnknownNetwork); |
| return; |
| } |
| |
| std::string guid = state->guid(); |
| if (guid.empty()) { |
| // TODO(pneubeck): create an initial configuration in this case. As for |
| // CreateConfiguration, user settings from older ChromeOS versions have to |
| // determined here. |
| InvokeErrorCallback( |
| service_path, error_callback, kSetOnUnconfiguredNetwork); |
| return; |
| } |
| |
| const std::string& profile_path = state->profile_path(); |
| const NetworkProfile *profile = |
| network_profile_handler_->GetProfileForPath(profile_path); |
| if (!profile) { |
| InvokeErrorCallback(service_path, error_callback, kUnknownProfilePath); |
| return; |
| } |
| |
| VLOG(2) << "SetProperties: Found GUID " << guid << " and profile " |
| << profile->ToDebugString(); |
| |
| const Policies* policies = GetPoliciesForProfile(*profile); |
| if (!policies) { |
| InvokeErrorCallback(service_path, error_callback, kPoliciesNotInitialized); |
| return; |
| } |
| |
| // Validate the ONC dictionary. We are liberal and ignore unknown field |
| // names. User settings are only partial ONC, thus we ignore missing fields. |
| onc::Validator validator(false, // Ignore unknown fields. |
| false, // Ignore invalid recommended field names. |
| false, // Ignore missing fields. |
| false); // This ONC does not come from policy. |
| |
| onc::Validator::Result validation_result; |
| scoped_ptr<base::DictionaryValue> validated_user_settings = |
| validator.ValidateAndRepairObject( |
| &onc::kNetworkConfigurationSignature, |
| user_settings, |
| &validation_result); |
| |
| if (validation_result == onc::Validator::INVALID) { |
| InvokeErrorCallback(service_path, error_callback, kInvalidUserSettings); |
| return; |
| } |
| if (validation_result == onc::Validator::VALID_WITH_WARNINGS) |
| LOG(WARNING) << "Validation of ONC user settings produced warnings."; |
| |
| const base::DictionaryValue* policy = |
| GetByGUID(policies->per_network_config, guid); |
| VLOG(2) << "This configuration is " << (policy ? "" : "not ") << "managed."; |
| |
| scoped_ptr<base::DictionaryValue> shill_dictionary( |
| policy_util::CreateShillConfiguration( |
| *profile, guid, policy, validated_user_settings.get())); |
| |
| network_configuration_handler_->SetProperties( |
| service_path, *shill_dictionary, callback, error_callback); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::CreateConfiguration( |
| const std::string& userhash, |
| const base::DictionaryValue& properties, |
| const network_handler::StringResultCallback& callback, |
| const network_handler::ErrorCallback& error_callback) const { |
| const Policies* policies = GetPoliciesForUser(userhash); |
| if (!policies) { |
| InvokeErrorCallback("", error_callback, kPoliciesNotInitialized); |
| return; |
| } |
| |
| if (policy_util::FindMatchingPolicy(policies->per_network_config, |
| properties)) { |
| InvokeErrorCallback("", error_callback, kNetworkAlreadyConfigured); |
| return; |
| } |
| |
| const NetworkProfile* profile = |
| network_profile_handler_->GetProfileForUserhash(userhash); |
| if (!profile) { |
| InvokeErrorCallback("", error_callback, kProfileNotInitialized); |
| return; |
| } |
| |
| // TODO(pneubeck): In case of WiFi, check that no other configuration for the |
| // same {SSID, mode, security} exists. We don't support such multiple |
| // configurations, yet. |
| |
| // Generate a new GUID for this configuration. Ignore the maybe provided GUID |
| // in |properties| as it is not our own and from an untrusted source. |
| std::string guid = base::GenerateGUID(); |
| scoped_ptr<base::DictionaryValue> shill_dictionary( |
| policy_util::CreateShillConfiguration( |
| *profile, guid, NULL /*no policy*/, &properties)); |
| |
| network_configuration_handler_->CreateConfiguration( |
| *shill_dictionary, callback, error_callback); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::RemoveConfiguration( |
| const std::string& service_path, |
| const base::Closure& callback, |
| const network_handler::ErrorCallback& error_callback) const { |
| network_configuration_handler_->RemoveConfiguration( |
| service_path, callback, error_callback); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::SetPolicy( |
| ::onc::ONCSource onc_source, |
| const std::string& userhash, |
| const base::ListValue& network_configs_onc, |
| const base::DictionaryValue& global_network_config) { |
| VLOG(1) << "Setting policies from " << ToDebugString(onc_source, userhash) |
| << "."; |
| |
| // |userhash| must be empty for device policies. |
| DCHECK(onc_source != ::onc::ONC_SOURCE_DEVICE_POLICY || |
| userhash.empty()); |
| Policies* policies = NULL; |
| if (ContainsKey(policies_by_user_, userhash)) { |
| policies = policies_by_user_[userhash].get(); |
| } else { |
| policies = new Policies; |
| policies_by_user_[userhash] = make_linked_ptr(policies); |
| } |
| |
| policies->global_network_config.MergeDictionary(&global_network_config); |
| |
| GuidToPolicyMap old_per_network_config; |
| policies->per_network_config.swap(old_per_network_config); |
| |
| // This stores all GUIDs of policies that have changed or are new. |
| std::set<std::string> modified_policies; |
| |
| for (base::ListValue::const_iterator it = network_configs_onc.begin(); |
| it != network_configs_onc.end(); ++it) { |
| const base::DictionaryValue* network = NULL; |
| (*it)->GetAsDictionary(&network); |
| DCHECK(network); |
| |
| std::string guid; |
| network->GetStringWithoutPathExpansion(::onc::network_config::kGUID, &guid); |
| DCHECK(!guid.empty()); |
| |
| if (policies->per_network_config.count(guid) > 0) { |
| NET_LOG_ERROR("ONC from " + ToDebugString(onc_source, userhash) + |
| " contains several entries for the same GUID ", guid); |
| delete policies->per_network_config[guid]; |
| } |
| const base::DictionaryValue* new_entry = network->DeepCopy(); |
| policies->per_network_config[guid] = new_entry; |
| |
| const base::DictionaryValue* old_entry = old_per_network_config[guid]; |
| if (!old_entry || !old_entry->Equals(new_entry)) |
| modified_policies.insert(guid); |
| } |
| |
| STLDeleteValues(&old_per_network_config); |
| |
| const NetworkProfile* profile = |
| network_profile_handler_->GetProfileForUserhash(userhash); |
| if (profile) { |
| scoped_refptr<PolicyApplicator> applicator = |
| new PolicyApplicator(weak_ptr_factory_.GetWeakPtr(), |
| *profile, |
| policies->per_network_config, |
| policies->global_network_config, |
| &modified_policies); |
| applicator->Run(); |
| } else { |
| VLOG(1) << "The relevant Shill profile isn't initialized yet, postponing " |
| << "policy application."; |
| // See OnProfileAdded. |
| } |
| |
| FOR_EACH_OBSERVER(NetworkPolicyObserver, observers_, PolicyChanged(userhash)); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::OnProfileAdded( |
| const NetworkProfile& profile) { |
| VLOG(1) << "Adding profile " << profile.ToDebugString() << "'."; |
| |
| const Policies* policies = GetPoliciesForProfile(profile); |
| if (!policies) { |
| VLOG(1) << "The relevant policy is not initialized, " |
| << "postponing policy application."; |
| // See SetPolicy. |
| return; |
| } |
| |
| std::set<std::string> policy_guids; |
| for (GuidToPolicyMap::const_iterator it = |
| policies->per_network_config.begin(); |
| it != policies->per_network_config.end(); ++it) { |
| policy_guids.insert(it->first); |
| } |
| |
| scoped_refptr<PolicyApplicator> applicator = |
| new PolicyApplicator(weak_ptr_factory_.GetWeakPtr(), |
| profile, |
| policies->per_network_config, |
| policies->global_network_config, |
| &policy_guids); |
| applicator->Run(); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::OnProfileRemoved( |
| const NetworkProfile& profile) { |
| // Nothing to do in this case. |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::CreateConfigurationFromPolicy( |
| const base::DictionaryValue& shill_properties) { |
| network_configuration_handler_->CreateConfiguration( |
| shill_properties, |
| base::Bind( |
| &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork, |
| weak_ptr_factory_.GetWeakPtr()), |
| base::Bind(&LogErrorWithDict, FROM_HERE)); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl:: |
| UpdateExistingConfigurationWithPropertiesFromPolicy( |
| const base::DictionaryValue& existing_properties, |
| const base::DictionaryValue& new_properties) { |
| base::DictionaryValue shill_properties; |
| |
| std::string profile; |
| existing_properties.GetStringWithoutPathExpansion(shill::kProfileProperty, |
| &profile); |
| if (profile.empty()) { |
| NET_LOG_ERROR("Missing profile property", |
| shill_property_util::GetNetworkIdFromProperties( |
| existing_properties)); |
| return; |
| } |
| shill_properties.SetStringWithoutPathExpansion(shill::kProfileProperty, |
| profile); |
| |
| if (!shill_property_util::CopyIdentifyingProperties( |
| existing_properties, |
| true /* properties were read from Shill */, |
| &shill_properties)) { |
| NET_LOG_ERROR("Missing identifying properties", |
| shill_property_util::GetNetworkIdFromProperties( |
| existing_properties)); |
| } |
| |
| shill_properties.MergeDictionary(&new_properties); |
| |
| network_configuration_handler_->CreateConfiguration( |
| shill_properties, |
| base::Bind( |
| &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork, |
| weak_ptr_factory_.GetWeakPtr()), |
| base::Bind(&LogErrorWithDict, FROM_HERE)); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::OnPoliciesApplied() { |
| } |
| |
| const base::DictionaryValue* |
| ManagedNetworkConfigurationHandlerImpl::FindPolicyByGUID( |
| const std::string userhash, |
| const std::string& guid, |
| ::onc::ONCSource* onc_source) const { |
| *onc_source = ::onc::ONC_SOURCE_NONE; |
| |
| if (!userhash.empty()) { |
| const Policies* user_policies = GetPoliciesForUser(userhash); |
| if (user_policies) { |
| const base::DictionaryValue* policy = |
| GetByGUID(user_policies->per_network_config, guid); |
| if (policy) { |
| *onc_source = ::onc::ONC_SOURCE_USER_POLICY; |
| return policy; |
| } |
| } |
| } |
| |
| const Policies* device_policies = GetPoliciesForUser(std::string()); |
| if (device_policies) { |
| const base::DictionaryValue* policy = |
| GetByGUID(device_policies->per_network_config, guid); |
| if (policy) { |
| *onc_source = ::onc::ONC_SOURCE_DEVICE_POLICY; |
| return policy; |
| } |
| } |
| |
| return NULL; |
| } |
| |
| const base::DictionaryValue* |
| ManagedNetworkConfigurationHandlerImpl::GetGlobalConfigFromPolicy( |
| const std::string userhash) const { |
| const Policies* policies = GetPoliciesForUser(userhash); |
| if (!policies) |
| return NULL; |
| |
| return &policies->global_network_config; |
| } |
| const base::DictionaryValue* |
| ManagedNetworkConfigurationHandlerImpl::FindPolicyByGuidAndProfile( |
| const std::string& guid, |
| const std::string& profile_path) const { |
| const NetworkProfile* profile = |
| network_profile_handler_->GetProfileForPath(profile_path); |
| if (!profile) { |
| NET_LOG_ERROR("Profile path unknown:" + profile_path, guid); |
| return NULL; |
| } |
| |
| const Policies* policies = GetPoliciesForProfile(*profile); |
| if (!policies) |
| return NULL; |
| |
| return GetByGUID(policies->per_network_config, guid); |
| } |
| |
| const ManagedNetworkConfigurationHandlerImpl::Policies* |
| ManagedNetworkConfigurationHandlerImpl::GetPoliciesForUser( |
| const std::string& userhash) const { |
| UserToPoliciesMap::const_iterator it = policies_by_user_.find(userhash); |
| if (it == policies_by_user_.end()) |
| return NULL; |
| return it->second.get(); |
| } |
| |
| const ManagedNetworkConfigurationHandlerImpl::Policies* |
| ManagedNetworkConfigurationHandlerImpl::GetPoliciesForProfile( |
| const NetworkProfile& profile) const { |
| DCHECK(profile.type() != NetworkProfile::TYPE_SHARED || |
| profile.userhash.empty()); |
| return GetPoliciesForUser(profile.userhash); |
| } |
| |
| ManagedNetworkConfigurationHandlerImpl::ManagedNetworkConfigurationHandlerImpl() |
| : network_state_handler_(NULL), |
| network_profile_handler_(NULL), |
| network_configuration_handler_(NULL), |
| network_device_handler_(NULL), |
| weak_ptr_factory_(this) {} |
| |
| ManagedNetworkConfigurationHandlerImpl:: |
| ~ManagedNetworkConfigurationHandlerImpl() { |
| network_profile_handler_->RemoveObserver(this); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::Init( |
| NetworkStateHandler* network_state_handler, |
| NetworkProfileHandler* network_profile_handler, |
| NetworkConfigurationHandler* network_configuration_handler, |
| NetworkDeviceHandler* network_device_handler) { |
| network_state_handler_ = network_state_handler; |
| network_profile_handler_ = network_profile_handler; |
| network_configuration_handler_ = network_configuration_handler; |
| network_device_handler_ = network_device_handler; |
| network_profile_handler_->AddObserver(this); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork( |
| const std::string& service_path) { |
| if (service_path.empty()) |
| return; |
| FOR_EACH_OBSERVER( |
| NetworkPolicyObserver, observers_, PolicyApplied(service_path)); |
| } |
| |
| // Get{Managed}Properties helpers |
| |
| void ManagedNetworkConfigurationHandlerImpl::GetDeviceStateProperties( |
| const std::string& service_path, |
| base::DictionaryValue* properties) { |
| std::string connection_state; |
| properties->GetStringWithoutPathExpansion( |
| shill::kStateProperty, &connection_state); |
| if (!NetworkState::StateIsConnected(connection_state)) |
| return; |
| |
| // Get the IPConfig properties from the device and store them in "IPConfigs" |
| // (plural) in the properties dictionary. (Note: Shill only provides a single |
| // "IPConfig" property for a network service, but a consumer of this API may |
| // want information about all ipv4 and ipv6 IPConfig properties. |
| std::string device; |
| properties->GetStringWithoutPathExpansion(shill::kDeviceProperty, &device); |
| const DeviceState* device_state = |
| network_state_handler_->GetDeviceState(device); |
| if (!device_state) { |
| NET_LOG_ERROR("GetDeviceProperties: no device: " + device, service_path); |
| return; |
| } |
| |
| // Get the hardware MAC address from the DeviceState. |
| if (!device_state->mac_address().empty()) { |
| properties->SetStringWithoutPathExpansion( |
| shill::kAddressProperty, device_state->mac_address()); |
| } |
| |
| // Convert IPConfig dictionary to a ListValue. |
| base::ListValue* ip_configs = new base::ListValue; |
| for (base::DictionaryValue::Iterator iter(device_state->ip_configs()); |
| !iter.IsAtEnd(); iter.Advance()) { |
| ip_configs->Append(iter.value().DeepCopy()); |
| } |
| properties->SetWithoutPathExpansion(shill::kIPConfigsProperty, ip_configs); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback( |
| GetDevicePropertiesCallback send_callback, |
| const std::string& service_path, |
| const base::DictionaryValue& shill_properties) { |
| scoped_ptr<base::DictionaryValue> shill_properties_copy( |
| shill_properties.DeepCopy()); |
| |
| // Add associated Device properties before the ONC translation. |
| GetDeviceStateProperties(service_path, shill_properties_copy.get()); |
| |
| // Only request Device properties for Cellular networks with a valid device. |
| std::string type, device_path; |
| if (!network_device_handler_ || |
| !shill_properties_copy->GetStringWithoutPathExpansion( |
| shill::kTypeProperty, &type) || |
| type != shill::kTypeCellular || |
| !shill_properties_copy->GetStringWithoutPathExpansion( |
| shill::kDeviceProperty, &device_path) || |
| device_path.empty()) { |
| send_callback.Run(service_path, shill_properties_copy.Pass()); |
| return; |
| } |
| |
| // Request the device properties. On success or failure pass (a possibly |
| // modified) |shill_properties| to |send_callback|. |
| scoped_ptr<base::DictionaryValue> shill_properties_copy_error_copy( |
| shill_properties_copy->DeepCopy()); |
| network_device_handler_->GetDeviceProperties( |
| device_path, |
| base::Bind(&ManagedNetworkConfigurationHandlerImpl:: |
| GetDevicePropertiesSuccess, |
| weak_ptr_factory_.GetWeakPtr(), |
| service_path, |
| base::Passed(&shill_properties_copy), |
| send_callback), |
| base::Bind(&ManagedNetworkConfigurationHandlerImpl:: |
| GetDevicePropertiesFailure, |
| weak_ptr_factory_.GetWeakPtr(), |
| service_path, |
| base::Passed(&shill_properties_copy_error_copy), |
| send_callback)); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::GetDevicePropertiesSuccess( |
| const std::string& service_path, |
| scoped_ptr<base::DictionaryValue> network_properties, |
| GetDevicePropertiesCallback send_callback, |
| const std::string& device_path, |
| const base::DictionaryValue& device_properties) { |
| // Create a "Device" dictionary in |network_properties|. |
| network_properties->SetWithoutPathExpansion( |
| shill::kDeviceProperty, device_properties.DeepCopy()); |
| send_callback.Run(service_path, network_properties.Pass()); |
| } |
| |
| void ManagedNetworkConfigurationHandlerImpl::GetDevicePropertiesFailure( |
| const std::string& service_path, |
| scoped_ptr<base::DictionaryValue> network_properties, |
| GetDevicePropertiesCallback send_callback, |
| const std::string& error_name, |
| scoped_ptr<base::DictionaryValue> error_data) { |
| NET_LOG_ERROR("Error getting device properties", service_path); |
| send_callback.Run(service_path, network_properties.Pass()); |
| } |
| |
| |
| } // namespace chromeos |