// // Copyright (C) 2014 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "update_engine/update_manager/real_device_policy_provider.h" #include <stdint.h> #include <vector> #include <base/location.h> #include <base/logging.h> #include <base/time/time.h> #include <policy/device_policy.h> #include "update_engine/common/utils.h" #include "update_engine/connection_utils.h" #include "update_engine/update_manager/generic_variables.h" using base::TimeDelta; using brillo::MessageLoop; using chromeos_update_engine::ConnectionType; using policy::DevicePolicy; using std::set; using std::string; using std::vector; namespace { const int kDevicePolicyRefreshRateInMinutes = 60; } // namespace namespace chromeos_update_manager { RealDevicePolicyProvider::~RealDevicePolicyProvider() { MessageLoop::current()->CancelTask(scheduled_refresh_); } bool RealDevicePolicyProvider::Init() { CHECK(policy_provider_ != nullptr); // On Init() we try to get the device policy and keep updating it. RefreshDevicePolicyAndReschedule(); #if USE_DBUS // We also listen for signals from the session manager to force a device // policy refresh. session_manager_proxy_->RegisterPropertyChangeCompleteSignalHandler( base::Bind(&RealDevicePolicyProvider::OnPropertyChangedCompletedSignal, base::Unretained(this)), base::Bind(&RealDevicePolicyProvider::OnSignalConnected, base::Unretained(this))); #endif // USE_DBUS return true; } void RealDevicePolicyProvider::OnPropertyChangedCompletedSignal( const string& success) { if (success != "success") { LOG(WARNING) << "Received device policy updated signal with a failure."; } // We refresh the policy file even if the payload string is kSignalFailure. LOG(INFO) << "Reloading and re-scheduling device policy due to signal " "received."; MessageLoop::current()->CancelTask(scheduled_refresh_); scheduled_refresh_ = MessageLoop::kTaskIdNull; RefreshDevicePolicyAndReschedule(); } void RealDevicePolicyProvider::OnSignalConnected(const string& interface_name, const string& signal_name, bool successful) { if (!successful) { LOG(WARNING) << "We couldn't connect to SessionManager signal for updates " "on the device policy blob. We will reload the policy file " "periodically."; } // We do a one-time refresh of the DevicePolicy just in case we missed a // signal between the first refresh and the time the signal handler was // actually connected. RefreshDevicePolicy(); } void RealDevicePolicyProvider::RefreshDevicePolicyAndReschedule() { RefreshDevicePolicy(); scheduled_refresh_ = MessageLoop::current()->PostDelayedTask( FROM_HERE, base::Bind(&RealDevicePolicyProvider::RefreshDevicePolicyAndReschedule, base::Unretained(this)), TimeDelta::FromMinutes(kDevicePolicyRefreshRateInMinutes)); } template <typename T> void RealDevicePolicyProvider::UpdateVariable( AsyncCopyVariable<T>* var, bool (DevicePolicy::*getter_method)(T*) const) { T new_value; if (policy_provider_->device_policy_is_loaded() && (policy_provider_->GetDevicePolicy().*getter_method)(&new_value)) { var->SetValue(new_value); } else { var->UnsetValue(); } } template <typename T> void RealDevicePolicyProvider::UpdateVariable( AsyncCopyVariable<T>* var, bool (RealDevicePolicyProvider::*getter_method)(T*) const) { T new_value; if (policy_provider_->device_policy_is_loaded() && (this->*getter_method)(&new_value)) { var->SetValue(new_value); } else { var->UnsetValue(); } } bool RealDevicePolicyProvider::ConvertRollbackToTargetVersion( RollbackToTargetVersion* rollback_to_target_version) const { int rollback_to_target_version_int; if (!policy_provider_->GetDevicePolicy().GetRollbackToTargetVersion( &rollback_to_target_version_int)) { return false; } if (rollback_to_target_version_int < 0 || rollback_to_target_version_int >= static_cast<int>(RollbackToTargetVersion::kMaxValue)) { return false; } *rollback_to_target_version = static_cast<RollbackToTargetVersion>(rollback_to_target_version_int); return true; } bool RealDevicePolicyProvider::ConvertAllowedConnectionTypesForUpdate( set<ConnectionType>* allowed_types) const { set<string> allowed_types_str; if (!policy_provider_->GetDevicePolicy().GetAllowedConnectionTypesForUpdate( &allowed_types_str)) { return false; } allowed_types->clear(); for (auto& type_str : allowed_types_str) { ConnectionType type = chromeos_update_engine::connection_utils::ParseConnectionType(type_str); if (type != ConnectionType::kUnknown) { allowed_types->insert(type); } else { LOG(WARNING) << "Policy includes unknown connection type: " << type_str; } } return true; } bool RealDevicePolicyProvider::ConvertScatterFactor( TimeDelta* scatter_factor) const { int64_t scatter_factor_in_seconds; if (!policy_provider_->GetDevicePolicy().GetScatterFactorInSeconds( &scatter_factor_in_seconds)) { return false; } if (scatter_factor_in_seconds < 0) { LOG(WARNING) << "Ignoring negative scatter factor: " << scatter_factor_in_seconds; return false; } *scatter_factor = TimeDelta::FromSeconds(scatter_factor_in_seconds); return true; } bool RealDevicePolicyProvider::ConvertDisallowedTimeIntervals( WeeklyTimeIntervalVector* disallowed_intervals_out) const { vector<DevicePolicy::WeeklyTimeInterval> parsed_intervals; if (!policy_provider_->GetDevicePolicy().GetDisallowedTimeIntervals( &parsed_intervals)) { return false; } disallowed_intervals_out->clear(); for (const auto& interval : parsed_intervals) { disallowed_intervals_out->emplace_back( WeeklyTime(interval.start_day_of_week, interval.start_time), WeeklyTime(interval.end_day_of_week, interval.end_time)); } return true; } void RealDevicePolicyProvider::RefreshDevicePolicy() { if (!policy_provider_->Reload()) { LOG(INFO) << "No device policies/settings present."; } var_device_policy_is_loaded_.SetValue( policy_provider_->device_policy_is_loaded()); UpdateVariable(&var_release_channel_, &DevicePolicy::GetReleaseChannel); UpdateVariable(&var_release_channel_delegated_, &DevicePolicy::GetReleaseChannelDelegated); UpdateVariable(&var_update_disabled_, &DevicePolicy::GetUpdateDisabled); UpdateVariable(&var_target_version_prefix_, &DevicePolicy::GetTargetVersionPrefix); UpdateVariable(&var_rollback_to_target_version_, &RealDevicePolicyProvider::ConvertRollbackToTargetVersion); UpdateVariable(&var_rollback_allowed_milestones_, &DevicePolicy::GetRollbackAllowedMilestones); if (policy_provider_->IsConsumerDevice()) { // For consumer devices (which won't ever have policy), set value to 0. var_rollback_allowed_milestones_.SetValue(0); } UpdateVariable(&var_scatter_factor_, &RealDevicePolicyProvider::ConvertScatterFactor); UpdateVariable( &var_allowed_connection_types_for_update_, &RealDevicePolicyProvider::ConvertAllowedConnectionTypesForUpdate); UpdateVariable(&var_owner_, &DevicePolicy::GetOwner); UpdateVariable(&var_http_downloads_enabled_, &DevicePolicy::GetHttpDownloadsEnabled); UpdateVariable(&var_au_p2p_enabled_, &DevicePolicy::GetAuP2PEnabled); UpdateVariable(&var_allow_kiosk_app_control_chrome_version_, &DevicePolicy::GetAllowKioskAppControlChromeVersion); UpdateVariable(&var_auto_launched_kiosk_app_id_, &DevicePolicy::GetAutoLaunchedKioskAppId); UpdateVariable(&var_disallowed_time_intervals_, &RealDevicePolicyProvider::ConvertDisallowedTimeIntervals); } } // namespace chromeos_update_manager