blob: 3f2c58d1b5b5c9401cdd37bc7cabc045b6ff3c48 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// 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 <concepts>
#include <functional>
#include <optional>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/check.h"
#include "base/containers/contains.h"
#include "base/containers/flat_map.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/to_string.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/updater/app/app_utils.h"
#include "chrome/updater/branded_constants.h"
#include "chrome/updater/constants.h"
#include "chrome/updater/external_constants.h"
#include "chrome/updater/persisted_data.h"
#include "chrome/updater/policy/dm_policy_manager.h"
#include "chrome/updater/policy/platform_policy_manager.h"
#include "chrome/updater/policy/policy_fetcher.h"
#include "chrome/updater/policy/policy_manager.h"
#include "chrome/updater/prefs.h"
#include "chrome/updater/updater_scope.h"
#include "components/crash/core/common/crash_key.h"
#include "components/policy/core/common/policy_types.h"
namespace updater {
PolicyService::PolicyManagers::PolicyManagers(
scoped_refptr<ExternalConstants> external_constants) {
CreateManagers(external_constants);
InitializeManagersVector();
}
PolicyService::PolicyManagers::~PolicyManagers() = default;
void PolicyService::PolicyManagers::CreateManagers(
scoped_refptr<ExternalConstants> external_constants) {
default_policy_manager_ = GetDefaultValuesPolicyManager();
if (!external_constants) {
return;
}
dm_policy_manager_ =
CreateDMPolicyManager(external_constants->IsMachineManaged());
external_constants_policy_manager_ =
CreateDictPolicyManager(external_constants->DictPolicies());
platform_policy_manager_ =
CreatePlatformPolicyManager(external_constants->IsMachineManaged());
}
// The order of the policy managers:
// 1) External constants policy manager (if present).
// 2) Platform policy manager (Group policy on Windows, and Managed
// Preferences on macOS). See NOTE below.
// 3) DM policy manager (if present). See NOTE below.
// 4) The default value policy manager.
// NOTE: If `CloudPolicyOverridesPlatformPolicy`, then the DM policy manager
// has a higher priority than the platform policy manger.
void PolicyService::PolicyManagers::InitializeManagersVector() {
managers_.clear();
if (dm_policy_manager_) {
managers_.push_back(dm_policy_manager_);
}
if (platform_policy_manager_) {
if (CloudPolicyOverridesPlatformPolicy(
{dm_policy_manager_, platform_policy_manager_,
external_constants_policy_manager_})) {
VLOG(1) << __func__ << ": CloudPolicyOverridesPlatformPolicy=1";
managers_.push_back(platform_policy_manager_);
} else {
managers_.insert(managers_.begin(), platform_policy_manager_);
}
}
if (external_constants_policy_manager_) {
managers_.insert(managers_.begin(), external_constants_policy_manager_);
}
managers_.push_back(default_policy_manager_);
SortManagersVector();
}
void PolicyService::PolicyManagers::SortManagersVector() {
std::ranges::stable_sort(
managers_, [](const scoped_refptr<PolicyManagerInterface>& lhs,
const scoped_refptr<PolicyManagerInterface>& rhs) {
return lhs->HasActiveDevicePolicies() &&
!rhs->HasActiveDevicePolicies();
});
}
bool PolicyService::PolicyManagers::CloudPolicyOverridesPlatformPolicy(
const std::vector<scoped_refptr<PolicyManagerInterface>>& providers) {
auto it = std::ranges::find_if(
providers, [](scoped_refptr<PolicyManagerInterface> p) {
return p && (p->CloudPolicyOverridesPlatformPolicy()).has_value();
});
return it == providers.end()
? kCloudPolicyOverridesPlatformPolicyDefaultValue
: ((*it)->CloudPolicyOverridesPlatformPolicy()).value();
}
void PolicyService::PolicyManagers::ResetDeviceManagementManager(
scoped_refptr<PolicyManagerInterface> dm_manager) {
dm_policy_manager_ = dm_manager;
InitializeManagersVector();
}
void PolicyService::PolicyManagers::SetManagersForTesting(
std::vector<scoped_refptr<PolicyManagerInterface>> managers) {
managers_ = std::move(managers);
SortManagersVector();
}
PolicyService::PolicyService(
scoped_refptr<ExternalConstants> external_constants,
scoped_refptr<PersistedData> persisted_data)
: policy_managers_(external_constants),
external_constants_(external_constants),
persisted_data_(persisted_data) {
VLOG(1) << "Current effective policies:" << std::endl
<< GetAllPoliciesAsString();
}
PolicyService::~PolicyService() = default;
void PolicyService::FetchPolicies(policy::PolicyFetchReason reason,
base::OnceCallback<void(int)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::WithBaseSyncPrimitives()},
base::BindOnce(&IsCloudManaged),
base::BindOnce(&PolicyService::DoFetchPolicies,
base::WrapRefCounted(this), reason, std::move(callback)));
}
void PolicyService::DoFetchPolicies(policy::PolicyFetchReason reason,
base::OnceCallback<void(int)> callback,
bool is_cbcm_managed) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
static crash_reporter::CrashKeyString<6> crash_key_cbcm("cbcm");
crash_key_cbcm.Set(base::ToString(is_cbcm_managed));
if (fetch_policies_callback_) {
// Combine with existing call.
fetch_policies_callback_ = base::BindOnce(
[](base::OnceCallback<void(int)> a, base::OnceCallback<void(int)> b,
int v) {
std::move(a).Run(v);
std::move(b).Run(v);
},
std::move(fetch_policies_callback_), std::move(callback));
return;
}
fetch_policies_callback_ = std::move(callback);
if (!is_cbcm_managed) {
VLOG(2) << "Device is not CBCM managed, skipped policy fetch.";
FetchPoliciesDone({}, kErrorOk, {});
return;
}
scoped_refptr<PolicyFetcher> fetcher = CreateOutOfProcessPolicyFetcher(
persisted_data_, external_constants_->IsMachineManaged(),
external_constants_->CecaConnectionTimeout());
fetcher->FetchPolicies(
reason, base::BindOnce(&PolicyService::FetchPoliciesDone, this, fetcher));
}
void PolicyService::FetchPoliciesDone(
scoped_refptr<PolicyFetcher> fetcher,
int result,
scoped_refptr<PolicyManagerInterface> dm_policy_manager) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
VLOG(1) << __func__ << ": " << result;
if (result == kErrorOk) {
policy_managers_.ResetDeviceManagementManager(dm_policy_manager);
VLOG(1) << "Policies after refresh:" << std::endl
<< GetAllPoliciesAsString();
} else {
VLOG(1) << "Failed to refresh policies: " << result;
}
std::move(fetch_policies_callback_).Run(result);
}
std::string PolicyService::source() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Returns the non-empty source combination of all active policy providers,
// separated by ';'. For example: "group_policy;device_management".
std::vector<std::string> sources;
for (const scoped_refptr<PolicyManagerInterface>& policy_manager :
policy_managers_.managers()) {
if (policy_manager->HasActiveDevicePolicies() &&
!policy_manager->source().empty()) {
sources.push_back(policy_manager->source());
}
}
return base::JoinString(sources, ";");
}
PolicyStatus<bool> PolicyService::CloudPolicyOverridesPlatformPolicy() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryPolicy(
&PolicyManagerInterface::CloudPolicyOverridesPlatformPolicy);
}
PolicyStatus<base::TimeDelta> PolicyService::GetLastCheckPeriod() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryPolicy(&PolicyManagerInterface::GetLastCheckPeriod);
}
PolicyStatus<UpdatesSuppressedTimes> PolicyService::GetUpdatesSuppressedTimes()
const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryPolicy(&PolicyManagerInterface::GetUpdatesSuppressedTimes);
}
PolicyStatus<std::string> PolicyService::GetDownloadPreference() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryPolicy(
&PolicyManagerInterface::GetDownloadPreference,
base::BindRepeating([](std::optional<std::string> download_preference) {
return (download_preference.has_value() &&
base::EqualsCaseInsensitiveASCII(download_preference.value(),
kDownloadPreferenceCacheable))
? download_preference
: std::nullopt;
}));
}
PolicyStatus<int> PolicyService::GetPackageCacheSizeLimitMBytes() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryPolicy(&PolicyManagerInterface::GetPackageCacheSizeLimitMBytes);
}
PolicyStatus<int> PolicyService::GetPackageCacheExpirationTimeDays() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryPolicy(
&PolicyManagerInterface::GetPackageCacheExpirationTimeDays);
}
PolicyStatus<int> PolicyService::GetPolicyForAppInstalls(
const std::string& app_id) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryAppPolicy(
&PolicyManagerInterface::GetEffectivePolicyForAppInstalls, app_id);
}
PolicyStatus<int> PolicyService::GetPolicyForAppUpdates(
const std::string& app_id) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryAppPolicy(
&PolicyManagerInterface::GetEffectivePolicyForAppUpdates, app_id);
}
PolicyStatus<std::string> PolicyService::GetTargetChannel(
const std::string& app_id) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryAppPolicy(&PolicyManagerInterface::GetTargetChannel, app_id);
}
PolicyStatus<std::string> PolicyService::GetTargetVersionPrefix(
const std::string& app_id) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryAppPolicy(&PolicyManagerInterface::GetTargetVersionPrefix,
app_id);
}
PolicyStatus<bool> PolicyService::IsRollbackToTargetVersionAllowed(
const std::string& app_id) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryAppPolicy(
&PolicyManagerInterface::IsRollbackToTargetVersionAllowed, app_id);
}
PolicyStatus<int> PolicyService::GetMajorVersionRolloutPolicy(
const std::string& app_id) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryAppPolicy(&PolicyManagerInterface::GetMajorVersionRolloutPolicy,
app_id);
}
PolicyStatus<int> PolicyService::GetMinorVersionRolloutPolicy(
const std::string& app_id) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryAppPolicy(&PolicyManagerInterface::GetMajorVersionRolloutPolicy,
app_id);
}
PolicyStatus<std::string> PolicyService::GetProxyMode() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryPolicy(
&PolicyManagerInterface::GetProxyMode,
base::BindRepeating([](std::optional<std::string> proxy_mode) {
return (proxy_mode.has_value() &&
base::Contains(std::vector<std::string>(
{kProxyModeDirect, kProxyModeSystem,
kProxyModeFixedServers, kProxyModePacScript,
kProxyModeAutoDetect}),
base::ToLowerASCII(proxy_mode.value())))
? proxy_mode
: std::nullopt;
}));
}
PolicyStatus<std::string> PolicyService::GetProxyPacUrl() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryPolicy(&PolicyManagerInterface::GetProxyPacUrl);
}
PolicyStatus<std::string> PolicyService::GetProxyServer() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryPolicy(&PolicyManagerInterface::GetProxyServer);
}
PolicyStatus<std::vector<std::string>> PolicyService::GetForceInstallApps()
const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryPolicy(&PolicyManagerInterface::GetForceInstallApps);
}
PolicyStatus<int> PolicyService::DeprecatedGetLastCheckPeriodMinutes() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return QueryPolicy(
&PolicyManagerInterface::GetLastCheckPeriod,
base::BindRepeating([](std::optional<base::TimeDelta> period) {
return period ? std::make_optional(period->InMinutes()) : std::nullopt;
}));
}
std::set<std::string> PolicyService::GetAppsWithPolicy() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::set<std::string> apps_with_policy;
std::ranges::for_each(
policy_managers_.managers(),
[&apps_with_policy](
const scoped_refptr<PolicyManagerInterface>& manager) {
auto apps = manager->GetAppsWithPolicy();
if (apps) {
apps_with_policy.insert(apps->begin(), apps->end());
}
});
return apps_with_policy;
}
base::Value PolicyService::GetAllPolicies() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::Value::Dict policies;
const PolicyStatus<bool> cloud_policy_override_platform_policy =
CloudPolicyOverridesPlatformPolicy();
if (cloud_policy_override_platform_policy) {
policies.Set(
"CloudPolicyOverridesPlatformPolicy",
base::Value::Dict()
.Set("value", cloud_policy_override_platform_policy.policy())
.Set("source",
cloud_policy_override_platform_policy.effective_policy()
->source));
}
const PolicyStatus<base::TimeDelta> last_check_period = GetLastCheckPeriod();
if (last_check_period) {
policies.Set(
"LastCheckPeriod",
base::Value::Dict()
.Set("value", last_check_period.policy().InMinutes())
.Set("source", last_check_period.effective_policy()->source));
}
const PolicyStatus<UpdatesSuppressedTimes> update_supressed_times =
GetUpdatesSuppressedTimes();
if (update_supressed_times) {
policies.Set(
"UpdatesSuppressed",
base::Value::Dict()
.Set("StartHour", update_supressed_times.policy().start_hour_)
.Set("StartMinute", update_supressed_times.policy().start_minute_)
.Set("Duration", update_supressed_times.policy().duration_minute_)
.Set("source", update_supressed_times.effective_policy()->source));
}
const PolicyStatus<std::string> download_preference = GetDownloadPreference();
if (download_preference) {
policies.Set(
"DownloadPreference",
base::Value::Dict()
.Set("value", download_preference.policy())
.Set("source", download_preference.effective_policy()->source));
}
const PolicyStatus<int> cache_size_limit = GetPackageCacheSizeLimitMBytes();
if (cache_size_limit) {
policies.Set(
"PackageCacheSizeLimit",
base::Value::Dict()
.Set("value", cache_size_limit.policy())
.Set("source", cache_size_limit.effective_policy()->source));
}
const PolicyStatus<int> cache_expiration_time =
GetPackageCacheExpirationTimeDays();
if (cache_expiration_time) {
policies.Set(
"PackageCacheExpires",
base::Value::Dict()
.Set("value", cache_expiration_time.policy())
.Set("source", cache_expiration_time.effective_policy()->source));
}
const PolicyStatus<std::string> proxy_mode = GetProxyMode();
if (proxy_mode) {
policies.Set("ProxyMode",
base::Value::Dict()
.Set("value", proxy_mode.policy())
.Set("source", proxy_mode.effective_policy()->source));
}
const PolicyStatus<std::string> proxy_pac_url = GetProxyPacUrl();
if (proxy_pac_url) {
policies.Set("ProxyPacURL",
base::Value::Dict()
.Set("value", proxy_pac_url.policy())
.Set("source", proxy_pac_url.effective_policy()->source));
}
const PolicyStatus<std::string> proxy_server = GetProxyServer();
if (proxy_server) {
policies.Set("ProxyServer",
base::Value::Dict()
.Set("value", proxy_server.policy())
.Set("source", proxy_server.effective_policy()->source));
}
for (const std::string& app_id : GetAppsWithPolicy()) {
base::Value::Dict app_policies;
const PolicyStatus<int> app_install = GetPolicyForAppInstalls(app_id);
if (app_install) {
app_policies.Set(
"Install",
base::Value::Dict()
.Set("value", app_install.policy())
.Set("source", app_install.effective_policy()->source));
}
const PolicyStatus<int> app_update = GetPolicyForAppUpdates(app_id);
if (app_update) {
app_policies.Set(
"Update", base::Value::Dict()
.Set("value", app_update.policy())
.Set("source", app_update.effective_policy()->source));
}
const PolicyStatus<std::string> target_channel = GetTargetChannel(app_id);
if (target_channel) {
app_policies.Set(
"TargetChannel",
base::Value::Dict()
.Set("value", target_channel.policy())
.Set("source", target_channel.effective_policy()->source));
}
const PolicyStatus<std::string> target_version_prefix =
GetTargetVersionPrefix(app_id);
if (target_version_prefix) {
app_policies.Set(
"TargetVersionPrefix",
base::Value::Dict()
.Set("value", target_version_prefix.policy())
.Set("source", target_version_prefix.effective_policy()->source));
}
const PolicyStatus<bool> rollback_allowed =
IsRollbackToTargetVersionAllowed(app_id);
if (rollback_allowed) {
app_policies.Set(
"RollbackToTargetVersionAllowed",
base::Value::Dict()
.Set("value", rollback_allowed.policy())
.Set("source", rollback_allowed.effective_policy()->source));
}
policies.Set(app_id, std::move(app_policies));
}
return base::Value(std::move(policies));
}
std::string PolicyService::GetAllPoliciesAsString() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::vector<std::string> policies;
const PolicyStatus<bool> cloud_policy_override_platform_policy =
CloudPolicyOverridesPlatformPolicy();
if (cloud_policy_override_platform_policy) {
policies.push_back(base::StringPrintf(
"CloudPolicyOverridesPlatformPolicy = %d (%s)",
cloud_policy_override_platform_policy.policy(),
cloud_policy_override_platform_policy.effective_policy()
->source.c_str()));
}
const PolicyStatus<base::TimeDelta> last_check_period = GetLastCheckPeriod();
if (last_check_period) {
policies.push_back(base::StringPrintf(
"LastCheckPeriod = %d (%s)", last_check_period.policy().InMinutes(),
last_check_period.effective_policy()->source.c_str()));
}
const PolicyStatus<UpdatesSuppressedTimes> update_supressed_times =
GetUpdatesSuppressedTimes();
if (update_supressed_times) {
policies.push_back(base::StringPrintf(
"UpdatesSuppressed = {StartHour: %d, StartMinute: "
"%d, Duration: %d} (%s)",
update_supressed_times.policy().start_hour_,
update_supressed_times.policy().start_minute_,
update_supressed_times.policy().duration_minute_,
update_supressed_times.effective_policy()->source.c_str()));
}
const PolicyStatus<std::string> download_preference = GetDownloadPreference();
if (download_preference) {
policies.push_back(base::StringPrintf(
"DownloadPreference = %s (%s)", download_preference.policy().c_str(),
download_preference.effective_policy()->source.c_str()));
}
const PolicyStatus<int> cache_size_limit = GetPackageCacheSizeLimitMBytes();
if (cache_size_limit) {
policies.push_back(base::StringPrintf(
"PackageCacheSizeLimit = %d MB (%s)", cache_size_limit.policy(),
cache_size_limit.effective_policy()->source.c_str()));
}
const PolicyStatus<int> cache_expiration_time =
GetPackageCacheExpirationTimeDays();
if (cache_expiration_time) {
policies.push_back(base::StringPrintf(
"PackageCacheExpires = %d days (%s)", cache_expiration_time.policy(),
cache_expiration_time.effective_policy()->source.c_str()));
}
const PolicyStatus<std::string> proxy_mode = GetProxyMode();
if (proxy_mode) {
policies.push_back(
base::StringPrintf("ProxyMode = %s (%s)", proxy_mode.policy().c_str(),
proxy_mode.effective_policy()->source.c_str()));
}
const PolicyStatus<std::string> proxy_pac_url = GetProxyPacUrl();
if (proxy_pac_url) {
policies.push_back(base::StringPrintf(
"ProxyPacURL = %s (%s)", proxy_pac_url.policy().c_str(),
proxy_pac_url.effective_policy()->source.c_str()));
}
const PolicyStatus<std::string> proxy_server = GetProxyServer();
if (proxy_server) {
policies.push_back(base::StringPrintf(
"ProxyServer = %s (%s)", proxy_server.policy().c_str(),
proxy_server.effective_policy()->source.c_str()));
}
for (const std::string& app_id : GetAppsWithPolicy()) {
std::vector<std::string> app_policies;
const PolicyStatus<int> app_install = GetPolicyForAppInstalls(app_id);
if (app_install) {
app_policies.push_back(
base::StringPrintf("Install = %d (%s)", app_install.policy(),
app_install.effective_policy()->source.c_str()));
}
const PolicyStatus<int> app_update = GetPolicyForAppUpdates(app_id);
if (app_update) {
app_policies.push_back(
base::StringPrintf("Update = %d (%s)", app_update.policy(),
app_update.effective_policy()->source.c_str()));
}
const PolicyStatus<std::string> target_channel = GetTargetChannel(app_id);
if (target_channel) {
app_policies.push_back(base::StringPrintf(
"TargetChannel = %s (%s)", target_channel.policy().c_str(),
target_channel.effective_policy()->source.c_str()));
}
const PolicyStatus<std::string> target_version_prefix =
GetTargetVersionPrefix(app_id);
if (target_version_prefix) {
app_policies.push_back(base::StringPrintf(
"TargetVersionPrefix = %s (%s)",
target_version_prefix.policy().c_str(),
target_version_prefix.effective_policy()->source.c_str()));
}
const PolicyStatus<bool> rollback_allowed =
IsRollbackToTargetVersionAllowed(app_id);
if (rollback_allowed) {
app_policies.push_back(base::StringPrintf(
"RollbackToTargetVersionAllowed = %d (%s)", rollback_allowed.policy(),
rollback_allowed.effective_policy()->source.c_str()));
}
policies.push_back(
base::StringPrintf("\"%s\": {\n %s\n }", app_id.c_str(),
base::JoinString(app_policies, "\n ").c_str()));
}
return base::StringPrintf("{\n %s\n}\n",
base::JoinString(policies, "\n ").c_str());
}
bool PolicyService::AreUpdatesSuppressedNow(base::Time now) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const PolicyStatus<UpdatesSuppressedTimes> suppression =
GetUpdatesSuppressedTimes();
if (!suppression || !suppression.policy().valid()) {
return false;
}
base::Time::Exploded now_local;
now.LocalExplode(&now_local);
const bool are_updates_suppressed =
suppression.policy().contains(now_local.hour, now_local.minute);
VLOG(0) << __func__ << ": Updates are "
<< (are_updates_suppressed ? "" : "not ") << "suppressed: now=" << now
<< ": UpdatesSuppressedTimes: start_hour_:"
<< suppression.policy().start_hour_
<< ": start_minute_:" << suppression.policy().start_minute_
<< ": duration_minute_:" << suppression.policy().duration_minute_;
return are_updates_suppressed;
}
template <typename T, typename U>
PolicyStatus<U> PolicyService::QueryPolicy(
PolicyQueryFunction<T> policy_query_function,
const base::RepeatingCallback<std::optional<U>(std::optional<T>)>&
transform) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
PolicyStatus<U> status;
for (const scoped_refptr<PolicyManagerInterface>& policy_manager :
policy_managers_.managers()) {
const std::optional<U> transformed_result =
[&transform](std::optional<T> query_result) {
if constexpr (std::same_as<T, U>) {
return transform.is_null() ? std::move(query_result)
: transform.Run(std::move(query_result));
} else {
CHECK(!transform.is_null());
return transform.Run(std::move(query_result));
}
}(std::invoke(policy_query_function, policy_manager));
if (transformed_result.has_value()) {
status.AddPolicyIfNeeded(policy_manager->HasActiveDevicePolicies(),
policy_manager->source(),
transformed_result.value());
}
}
return status;
}
template <typename T>
PolicyStatus<T> PolicyService::QueryAppPolicy(
AppPolicyQueryFunction<T> policy_query_function,
const std::string& app_id) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (IsUpdaterOrCompanionApp(app_id) || app_id == kQualificationAppId) {
// Updater itself, qualification and the companion app are excluded from
// policy settings.
return {};
}
PolicyStatus<T> status;
for (const scoped_refptr<PolicyManagerInterface>& policy_manager :
policy_managers_.managers()) {
std::optional<T> query_result =
std::invoke(policy_query_function, policy_manager, app_id);
if (query_result.has_value()) {
status.AddPolicyIfNeeded(policy_manager->HasActiveDevicePolicies(),
policy_manager->source(), query_result.value());
}
}
return status;
}
PolicyServiceProxyConfiguration::PolicyServiceProxyConfiguration() = default;
PolicyServiceProxyConfiguration::~PolicyServiceProxyConfiguration() = default;
PolicyServiceProxyConfiguration::PolicyServiceProxyConfiguration(
const PolicyServiceProxyConfiguration&) = default;
PolicyServiceProxyConfiguration::PolicyServiceProxyConfiguration(
PolicyServiceProxyConfiguration&&) = default;
PolicyServiceProxyConfiguration& PolicyServiceProxyConfiguration::operator=(
const PolicyServiceProxyConfiguration&) = default;
PolicyServiceProxyConfiguration& PolicyServiceProxyConfiguration::operator=(
PolicyServiceProxyConfiguration&&) = default;
std::optional<PolicyServiceProxyConfiguration>
PolicyServiceProxyConfiguration::Get(
scoped_refptr<PolicyService> policy_service) {
const PolicyStatus<std::string> proxy_mode = policy_service->GetProxyMode();
if (!proxy_mode || proxy_mode.policy().compare(kProxyModeSystem) == 0) {
return std::nullopt;
}
VLOG(2) << "Using policy proxy " << proxy_mode.policy();
PolicyServiceProxyConfiguration policy_service_proxy_configuration;
bool is_policy_config_valid = true;
if (proxy_mode.policy().compare(kProxyModeFixedServers) == 0) {
const PolicyStatus<std::string> proxy_url =
policy_service->GetProxyServer();
if (!proxy_url) {
VLOG(1) << "Fixed server mode proxy has no URL specified.";
is_policy_config_valid = false;
} else {
policy_service_proxy_configuration.proxy_url = proxy_url.policy();
}
} else if (proxy_mode.policy().compare(kProxyModePacScript) == 0) {
const PolicyStatus<std::string> proxy_pac_url =
policy_service->GetProxyPacUrl();
if (!proxy_pac_url) {
VLOG(1) << "PAC proxy policy has no PAC URL specified.";
is_policy_config_valid = false;
} else {
policy_service_proxy_configuration.proxy_pac_url = proxy_pac_url.policy();
}
} else if (proxy_mode.policy().compare(kProxyModeAutoDetect) == 0) {
policy_service_proxy_configuration.proxy_auto_detect = true;
} else {
is_policy_config_valid = false;
}
if (!is_policy_config_valid) {
VLOG(1) << "Configuration set by policy was invalid.";
return std::nullopt;
}
return policy_service_proxy_configuration;
}
bool IsCloudManaged() {
scoped_refptr<device_management_storage::DMStorage> dm_storage =
device_management_storage::GetDefaultDMStorage();
return dm_storage && (dm_storage->IsValidDMToken() ||
(!dm_storage->GetEnrollmentToken().empty() &&
!dm_storage->IsDeviceDeregistered()));
}
} // namespace updater