blob: 5a190dcf8c26574cfc562f1a9b03a3ac8fc55f90 [file] [log] [blame]
// Copyright 2020 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 "chrome/updater/policy_service.h"
#include <algorithm>
#include "base/bind.h"
#include "base/callback.h"
#include "base/check.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#if defined(OS_WIN)
#include "chrome/updater/win/group_policy_manager.h"
#elif defined(OS_MAC)
#include "chrome/updater/mac/managed_preference_policy_manager.h"
#endif
namespace updater {
// Only policy managers that are enterprise managed are used by the policy
// service.
PolicyService::PolicyService() {
#if defined(OS_WIN)
InsertPolicyManager(std::make_unique<GroupPolicyManager>());
#endif
// TODO(crbug/1122118): Inject the DMPolicyManager here.
#if defined(OS_MAC)
InsertPolicyManager(CreateManagedPreferencePolicyManager());
#endif
InsertPolicyManager(GetPolicyManager());
}
PolicyService::~PolicyService() = default;
void PolicyService::InsertPolicyManager(
std::unique_ptr<PolicyManagerInterface> manager) {
if (manager->IsManaged()) {
for (auto it = policy_managers_.begin(); it != policy_managers_.end();
++it) {
if (!(*it)->IsManaged()) {
policy_managers_.insert(it, std::move(manager));
return;
}
}
}
policy_managers_.push_back(std::move(manager));
}
void PolicyService::SetPolicyManagersForTesting(
std::vector<std::unique_ptr<PolicyManagerInterface>> managers) {
// Testing managers are not inserted via InsertPolicyManager(). Do a
// quick sanity check that all managed providers are ahead of non-managed
// providers: there should be no adjacent pair with the reversed order.
DCHECK(std::adjacent_find(managers.begin(), managers.end(),
[](const auto& fst, const auto& snd) {
return !fst->IsManaged() && snd->IsManaged();
}) == managers.end());
policy_managers_ = std::move(managers);
}
std::string PolicyService::source() const {
// Returns the source combination of all active policy providers, separated
// by ';'. For example: "group_policy;device_management". Note that the
// default provider is not "managed" and its source will be ignored.
std::vector<std::string> sources;
for (const std::unique_ptr<PolicyManagerInterface>& policy_manager :
policy_managers_) {
if (policy_manager->IsManaged())
sources.push_back(policy_manager->source());
}
return base::JoinString(sources, ";");
}
bool PolicyService::GetLastCheckPeriodMinutes(PolicyStatus<int>* policy_status,
int* minutes) const {
return QueryPolicy(
base::BindRepeating(&PolicyManagerInterface::GetLastCheckPeriodMinutes),
policy_status, minutes);
}
bool PolicyService::GetUpdatesSuppressedTimes(
PolicyStatus<UpdatesSuppressedTimes>* policy_status,
UpdatesSuppressedTimes* suppressed_times) const {
return QueryPolicy(
base::BindRepeating(&PolicyManagerInterface::GetUpdatesSuppressedTimes),
policy_status, suppressed_times);
}
bool PolicyService::GetDownloadPreferenceGroupPolicy(
PolicyStatus<std::string>* policy_status,
std::string* download_preference) const {
return QueryPolicy(
base::BindRepeating(
&PolicyManagerInterface::GetDownloadPreferenceGroupPolicy),
policy_status, download_preference);
}
bool PolicyService::GetPackageCacheSizeLimitMBytes(
PolicyStatus<int>* policy_status,
int* cache_size_limit) const {
return QueryPolicy(
base::BindRepeating(
&PolicyManagerInterface::GetPackageCacheSizeLimitMBytes),
policy_status, cache_size_limit);
}
bool PolicyService::GetPackageCacheExpirationTimeDays(
PolicyStatus<int>* policy_status,
int* cache_life_limit) const {
return QueryPolicy(
base::BindRepeating(
&PolicyManagerInterface::GetPackageCacheExpirationTimeDays),
policy_status, cache_life_limit);
}
bool PolicyService::GetEffectivePolicyForAppInstalls(
const std::string& app_id,
PolicyStatus<int>* policy_status,
int* install_policy) const {
return QueryAppPolicy(
base::BindRepeating(
&PolicyManagerInterface::GetEffectivePolicyForAppInstalls),
app_id, policy_status, install_policy);
}
bool PolicyService::GetEffectivePolicyForAppUpdates(
const std::string& app_id,
PolicyStatus<int>* policy_status,
int* update_policy) const {
return QueryAppPolicy(
base::BindRepeating(
&PolicyManagerInterface::GetEffectivePolicyForAppUpdates),
app_id, policy_status, update_policy);
}
bool PolicyService::GetTargetChannel(const std::string& app_id,
PolicyStatus<std::string>* policy_status,
std::string* channel) const {
return QueryAppPolicy(
base::BindRepeating(&PolicyManagerInterface::GetTargetChannel), app_id,
policy_status, channel);
}
bool PolicyService::GetTargetVersionPrefix(
const std::string& app_id,
PolicyStatus<std::string>* policy_status,
std::string* target_version_prefix) const {
return QueryAppPolicy(
base::BindRepeating(&PolicyManagerInterface::GetTargetVersionPrefix),
app_id, policy_status, target_version_prefix);
}
bool PolicyService::IsRollbackToTargetVersionAllowed(
const std::string& app_id,
PolicyStatus<bool>* policy_status,
bool* rollback_allowed) const {
return QueryAppPolicy(
base::BindRepeating(
&PolicyManagerInterface::IsRollbackToTargetVersionAllowed),
app_id, policy_status, rollback_allowed);
}
bool PolicyService::GetProxyMode(PolicyStatus<std::string>* policy_status,
std::string* proxy_mode) const {
return QueryPolicy(base::BindRepeating(&PolicyManagerInterface::GetProxyMode),
policy_status, proxy_mode);
}
bool PolicyService::GetProxyPacUrl(PolicyStatus<std::string>* policy_status,
std::string* proxy_pac_url) const {
return QueryPolicy(
base::BindRepeating(&PolicyManagerInterface::GetProxyPacUrl),
policy_status, proxy_pac_url);
}
bool PolicyService::GetProxyServer(PolicyStatus<std::string>* policy_status,
std::string* proxy_server) const {
return QueryPolicy(
base::BindRepeating(&PolicyManagerInterface::GetProxyServer),
policy_status, proxy_server);
}
template <typename T>
bool PolicyService::QueryPolicy(
const base::RepeatingCallback<bool(const PolicyManagerInterface*, T*)>&
policy_query_callback,
PolicyStatus<T>* policy_status,
T* result) const {
T value{};
PolicyStatus<T> status;
for (const std::unique_ptr<PolicyManagerInterface>& policy_manager :
policy_managers_) {
if (!policy_query_callback.Run(policy_manager.get(), &value))
continue;
status.AddPolicyIfNeeded(policy_manager->IsManaged(),
policy_manager->source(), value);
}
if (!status.effective_policy())
return false;
*result = status.effective_policy().value().policy;
if (policy_status)
*policy_status = status;
return true;
}
template <typename T>
bool PolicyService::QueryAppPolicy(
const base::RepeatingCallback<bool(const PolicyManagerInterface*,
const std::string&,
T*)>& policy_query_callback,
const std::string& app_id,
PolicyStatus<T>* policy_status,
T* result) const {
T value{};
PolicyStatus<T> status;
for (const std::unique_ptr<PolicyManagerInterface>& policy_manager :
policy_managers_) {
if (!policy_query_callback.Run(policy_manager.get(), app_id, &value))
continue;
status.AddPolicyIfNeeded(policy_manager->IsManaged(),
policy_manager->source(), value);
}
if (!status.effective_policy())
return false;
*result = status.effective_policy().value().policy;
if (policy_status)
*policy_status = status;
return true;
}
std::unique_ptr<PolicyService> GetUpdaterPolicyService() {
return std::make_unique<PolicyService>();
}
} // namespace updater