| // |
| // 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 |