1//
2// Copyright (C) 2014 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "update_engine/update_manager/real_device_policy_provider.h"
18
19#include <stdint.h>
20
21#include <base/location.h>
22#include <base/logging.h>
23#include <base/time/time.h>
24#include <policy/device_policy.h>
25
26#include "update_engine/common/utils.h"
27#include "update_engine/update_manager/generic_variables.h"
28#include "update_engine/update_manager/real_shill_provider.h"
29
30using base::TimeDelta;
31using brillo::MessageLoop;
32using policy::DevicePolicy;
33using std::set;
34using std::string;
35
36namespace {
37
38const int kDevicePolicyRefreshRateInMinutes = 60;
39
40}  // namespace
41
42namespace chromeos_update_manager {
43
44RealDevicePolicyProvider::~RealDevicePolicyProvider() {
45  MessageLoop::current()->CancelTask(scheduled_refresh_);
46}
47
48bool RealDevicePolicyProvider::Init() {
49  CHECK(policy_provider_ != nullptr);
50
51  // On Init() we try to get the device policy and keep updating it.
52  RefreshDevicePolicyAndReschedule();
53
54  // We also listen for signals from the session manager to force a device
55  // policy refresh.
56  session_manager_proxy_->RegisterPropertyChangeCompleteSignalHandler(
57      base::Bind(&RealDevicePolicyProvider::OnPropertyChangedCompletedSignal,
58                 base::Unretained(this)),
59      base::Bind(&RealDevicePolicyProvider::OnSignalConnected,
60                 base::Unretained(this)));
61  return true;
62}
63
64void RealDevicePolicyProvider::OnPropertyChangedCompletedSignal(
65    const string& success) {
66  if (success != "success") {
67    LOG(WARNING) << "Received device policy updated signal with a failure.";
68  }
69  // We refresh the policy file even if the payload string is kSignalFailure.
70  LOG(INFO) << "Reloading and re-scheduling device policy due to signal "
71               "received.";
72  MessageLoop::current()->CancelTask(scheduled_refresh_);
73  scheduled_refresh_ = MessageLoop::kTaskIdNull;
74  RefreshDevicePolicyAndReschedule();
75}
76
77void RealDevicePolicyProvider::OnSignalConnected(const string& interface_name,
78                                                 const string& signal_name,
79                                                 bool successful) {
80  if (!successful) {
81    LOG(WARNING) << "We couldn't connect to SessionManager signal for updates "
82                    "on the device policy blob. We will reload the policy file "
83                    "periodically.";
84  }
85  // We do a one-time refresh of the DevicePolicy just in case we missed a
86  // signal between the first refresh and the time the signal handler was
87  // actually connected.
88  RefreshDevicePolicy();
89}
90
91void RealDevicePolicyProvider::RefreshDevicePolicyAndReschedule() {
92  RefreshDevicePolicy();
93  scheduled_refresh_ = MessageLoop::current()->PostDelayedTask(
94      FROM_HERE,
95      base::Bind(&RealDevicePolicyProvider::RefreshDevicePolicyAndReschedule,
96                 base::Unretained(this)),
97      TimeDelta::FromMinutes(kDevicePolicyRefreshRateInMinutes));
98}
99
100template<typename T>
101void RealDevicePolicyProvider::UpdateVariable(
102    AsyncCopyVariable<T>* var,
103    bool (DevicePolicy::*getter_method)(T*) const) {
104  T new_value;
105  if (policy_provider_->device_policy_is_loaded() &&
106      (policy_provider_->GetDevicePolicy().*getter_method)(&new_value)) {
107    var->SetValue(new_value);
108  } else {
109    var->UnsetValue();
110  }
111}
112
113template<typename T>
114void RealDevicePolicyProvider::UpdateVariable(
115    AsyncCopyVariable<T>* var,
116    bool (RealDevicePolicyProvider::*getter_method)(T*) const) {
117  T new_value;
118  if (policy_provider_->device_policy_is_loaded() &&
119      (this->*getter_method)(&new_value)) {
120    var->SetValue(new_value);
121  } else {
122    var->UnsetValue();
123  }
124}
125
126bool RealDevicePolicyProvider::ConvertAllowedConnectionTypesForUpdate(
127      set<ConnectionType>* allowed_types) const {
128  set<string> allowed_types_str;
129  if (!policy_provider_->GetDevicePolicy()
130      .GetAllowedConnectionTypesForUpdate(&allowed_types_str)) {
131    return false;
132  }
133  allowed_types->clear();
134  for (auto& type_str : allowed_types_str) {
135    ConnectionType type =
136        RealShillProvider::ParseConnectionType(type_str.c_str());
137    if (type != ConnectionType::kUnknown) {
138      allowed_types->insert(type);
139    } else {
140      LOG(WARNING) << "Policy includes unknown connection type: " << type_str;
141    }
142  }
143  return true;
144}
145
146bool RealDevicePolicyProvider::ConvertScatterFactor(
147    TimeDelta* scatter_factor) const {
148  int64_t scatter_factor_in_seconds;
149  if (!policy_provider_->GetDevicePolicy().GetScatterFactorInSeconds(
150      &scatter_factor_in_seconds)) {
151    return false;
152  }
153  if (scatter_factor_in_seconds < 0) {
154    LOG(WARNING) << "Ignoring negative scatter factor: "
155                 << scatter_factor_in_seconds;
156    return false;
157  }
158  *scatter_factor = TimeDelta::FromSeconds(scatter_factor_in_seconds);
159  return true;
160}
161
162void RealDevicePolicyProvider::RefreshDevicePolicy() {
163  if (!policy_provider_->Reload()) {
164    LOG(INFO) << "No device policies/settings present.";
165  }
166
167  var_device_policy_is_loaded_.SetValue(
168      policy_provider_->device_policy_is_loaded());
169
170  UpdateVariable(&var_release_channel_, &DevicePolicy::GetReleaseChannel);
171  UpdateVariable(&var_release_channel_delegated_,
172                 &DevicePolicy::GetReleaseChannelDelegated);
173  UpdateVariable(&var_update_disabled_, &DevicePolicy::GetUpdateDisabled);
174  UpdateVariable(&var_target_version_prefix_,
175                 &DevicePolicy::GetTargetVersionPrefix);
176  UpdateVariable(&var_scatter_factor_,
177                 &RealDevicePolicyProvider::ConvertScatterFactor);
178  UpdateVariable(
179      &var_allowed_connection_types_for_update_,
180      &RealDevicePolicyProvider::ConvertAllowedConnectionTypesForUpdate);
181  UpdateVariable(&var_owner_, &DevicePolicy::GetOwner);
182  UpdateVariable(&var_http_downloads_enabled_,
183                 &DevicePolicy::GetHttpDownloadsEnabled);
184  UpdateVariable(&var_au_p2p_enabled_, &DevicePolicy::GetAuP2PEnabled);
185}
186
187}  // namespace chromeos_update_manager
188