summaryrefslogtreecommitdiffstats
path: root/chromium/components/policy/core/browser/configuration_policy_handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/policy/core/browser/configuration_policy_handler.cc')
-rw-r--r--chromium/components/policy/core/browser/configuration_policy_handler.cc730
1 files changed, 730 insertions, 0 deletions
diff --git a/chromium/components/policy/core/browser/configuration_policy_handler.cc b/chromium/components/policy/core/browser/configuration_policy_handler.cc
new file mode 100644
index 00000000000..c58f855a36a
--- /dev/null
+++ b/chromium/components/policy/core/browser/configuration_policy_handler.cc
@@ -0,0 +1,730 @@
+// Copyright (c) 2012 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 "components/policy/core/browser/configuration_policy_handler.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <string>
+#include <utility>
+
+#include "base/callback.h"
+#include "base/check.h"
+#include "base/cxx17_backports.h"
+#include "base/files/file_path.h"
+#include "base/json/json_reader.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/notreached.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "components/policy/core/browser/policy_error_map.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/policy_constants.h"
+#include "components/prefs/pref_value_map.h"
+#include "components/strings/grit/components_strings.h"
+#include "url/gurl.h"
+
+namespace policy {
+
+const size_t kMaxUrlFiltersPerPolicy = 1000;
+
+// ConfigurationPolicyHandler implementation
+// -----------------------------------
+
+ConfigurationPolicyHandler::ConfigurationPolicyHandler() {}
+
+ConfigurationPolicyHandler::~ConfigurationPolicyHandler() {}
+
+void ConfigurationPolicyHandler::PrepareForDisplaying(
+ PolicyMap* policies) const {}
+
+void ConfigurationPolicyHandler::ApplyPolicySettingsWithParameters(
+ const PolicyMap& policies,
+ const PolicyHandlerParameters& parameters,
+ PrefValueMap* prefs) {
+ ApplyPolicySettings(policies, prefs);
+}
+
+// NamedPolicyHandler implementation -------------------------------------------
+NamedPolicyHandler::NamedPolicyHandler(const char* policy_name)
+ : policy_name_(policy_name) {}
+
+NamedPolicyHandler::~NamedPolicyHandler() = default;
+
+const char* NamedPolicyHandler::policy_name() const {
+ return policy_name_;
+}
+
+// TypeCheckingPolicyHandler implementation ------------------------------------
+
+TypeCheckingPolicyHandler::TypeCheckingPolicyHandler(
+ const char* policy_name,
+ base::Value::Type value_type)
+ : NamedPolicyHandler(policy_name), value_type_(value_type) {}
+
+TypeCheckingPolicyHandler::~TypeCheckingPolicyHandler() {}
+
+bool TypeCheckingPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
+ PolicyErrorMap* errors) {
+ const base::Value* value = nullptr;
+ return CheckAndGetValue(policies, errors, &value);
+}
+
+bool TypeCheckingPolicyHandler::CheckAndGetValue(const PolicyMap& policies,
+ PolicyErrorMap* errors,
+ const base::Value** value) {
+ // It is safe to use `GetValueUnsafe()` as multiple policy types are handled.
+ *value = policies.GetValueUnsafe(policy_name());
+ if (*value && (*value)->type() != value_type_) {
+ errors->AddError(policy_name(), IDS_POLICY_TYPE_ERROR,
+ base::Value::GetTypeName(value_type_));
+ return false;
+ }
+ return true;
+}
+
+// StringListPolicyHandler implementation --------------------------------------
+
+ListPolicyHandler::ListPolicyHandler(const char* policy_name,
+ base::Value::Type list_entry_type)
+ : TypeCheckingPolicyHandler(policy_name, base::Value::Type::LIST),
+ list_entry_type_(list_entry_type) {}
+
+ListPolicyHandler::~ListPolicyHandler() {}
+
+bool ListPolicyHandler::CheckPolicySettings(const policy::PolicyMap& policies,
+ policy::PolicyErrorMap* errors) {
+ return CheckAndGetList(policies, errors, nullptr);
+}
+
+void ListPolicyHandler::ApplyPolicySettings(const policy::PolicyMap& policies,
+ PrefValueMap* prefs) {
+ base::Value list(base::Value::Type::NONE);
+ if (CheckAndGetList(policies, nullptr, &list) && list.is_list())
+ ApplyList(std::move(list), prefs);
+}
+
+bool ListPolicyHandler::CheckAndGetList(const policy::PolicyMap& policies,
+ policy::PolicyErrorMap* errors,
+ base::Value* filtered_list) {
+ const base::Value* value = nullptr;
+ if (!CheckAndGetValue(policies, errors, &value))
+ return false;
+
+ if (!value)
+ return true;
+
+ // Filter the list, rejecting any invalid strings.
+ base::Value::ConstListView list = value->GetListDeprecated();
+ if (filtered_list)
+ *filtered_list = base::Value(base::Value::Type::LIST);
+ for (size_t list_index = 0; list_index < list.size(); ++list_index) {
+ const base::Value& entry = list[list_index];
+ if (entry.type() != list_entry_type_) {
+ if (errors) {
+ errors->AddError(policy_name(), list_index, IDS_POLICY_TYPE_ERROR,
+ base::Value::GetTypeName(list_entry_type_));
+ }
+ continue;
+ }
+
+ if (!CheckListEntry(entry)) {
+ if (errors) {
+ errors->AddError(policy_name(), list_index,
+ IDS_POLICY_VALUE_FORMAT_ERROR);
+ }
+ continue;
+ }
+
+ if (filtered_list)
+ filtered_list->Append(entry.Clone());
+ }
+
+ return true;
+}
+
+bool ListPolicyHandler::CheckListEntry(const base::Value& value) {
+ return true;
+}
+
+// IntRangePolicyHandlerBase implementation ------------------------------------
+
+IntRangePolicyHandlerBase::IntRangePolicyHandlerBase(const char* policy_name,
+ int min,
+ int max,
+ bool clamp)
+ : TypeCheckingPolicyHandler(policy_name, base::Value::Type::INTEGER),
+ min_(min),
+ max_(max),
+ clamp_(clamp) {}
+
+bool IntRangePolicyHandlerBase::CheckPolicySettings(const PolicyMap& policies,
+ PolicyErrorMap* errors) {
+ const base::Value* value;
+ return CheckAndGetValue(policies, errors, &value) &&
+ EnsureInRange(value, nullptr, errors);
+}
+
+IntRangePolicyHandlerBase::~IntRangePolicyHandlerBase() {}
+
+bool IntRangePolicyHandlerBase::EnsureInRange(const base::Value* input,
+ int* output,
+ PolicyErrorMap* errors) {
+ if (!input)
+ return true;
+
+ DCHECK(input->is_int());
+ int value = input->GetInt();
+
+ if (value < min_ || value > max_) {
+ if (errors) {
+ errors->AddError(policy_name(), IDS_POLICY_OUT_OF_RANGE_ERROR,
+ base::NumberToString(value));
+ }
+
+ if (!clamp_)
+ return false;
+
+ value = base::clamp(value, min_, max_);
+ }
+
+ if (output)
+ *output = value;
+ return true;
+}
+
+// StringMappingListPolicyHandler implementation -----------------------------
+
+StringMappingListPolicyHandler::MappingEntry::MappingEntry(
+ const char* policy_value,
+ std::unique_ptr<base::Value> map)
+ : enum_value(policy_value), mapped_value(std::move(map)) {}
+
+StringMappingListPolicyHandler::MappingEntry::~MappingEntry() {}
+
+StringMappingListPolicyHandler::StringMappingListPolicyHandler(
+ const char* policy_name,
+ const char* pref_path,
+ const GenerateMapCallback& callback)
+ : TypeCheckingPolicyHandler(policy_name, base::Value::Type::LIST),
+ pref_path_(pref_path),
+ map_getter_(callback) {}
+
+StringMappingListPolicyHandler::~StringMappingListPolicyHandler() {}
+
+bool StringMappingListPolicyHandler::CheckPolicySettings(
+ const PolicyMap& policies,
+ PolicyErrorMap* errors) {
+ const base::Value* value;
+ return CheckAndGetValue(policies, errors, &value) &&
+ Convert(value, nullptr, errors);
+}
+
+void StringMappingListPolicyHandler::ApplyPolicySettings(
+ const PolicyMap& policies,
+ PrefValueMap* prefs) {
+ if (!pref_path_)
+ return;
+ const base::Value* value =
+ policies.GetValue(policy_name(), base::Value::Type::LIST);
+ base::ListValue list;
+ if (value && Convert(value, &list, nullptr))
+ prefs->SetValue(pref_path_, std::move(list));
+}
+
+bool StringMappingListPolicyHandler::Convert(const base::Value* input,
+ base::ListValue* output,
+ PolicyErrorMap* errors) {
+ if (!input)
+ return true;
+
+ DCHECK(input->is_list());
+ int index = -1;
+ for (const auto& entry : input->GetListDeprecated()) {
+ ++index;
+ if (!entry.is_string()) {
+ if (errors) {
+ errors->AddError(policy_name(), index, IDS_POLICY_TYPE_ERROR,
+ base::Value::GetTypeName(base::Value::Type::STRING));
+ }
+ continue;
+ }
+
+ std::unique_ptr<base::Value> mapped_value = Map(entry.GetString());
+ if (mapped_value) {
+ if (output)
+ output->Append(std::move(mapped_value));
+ } else if (errors) {
+ errors->AddError(policy_name(), index, IDS_POLICY_OUT_OF_RANGE_ERROR);
+ }
+ }
+
+ return true;
+}
+
+std::unique_ptr<base::Value> StringMappingListPolicyHandler::Map(
+ const std::string& entry_value) {
+ // Lazily generate the map of policy strings to mapped values.
+ if (map_.empty())
+ map_getter_.Run(&map_);
+
+ for (const auto& mapping_entry : map_) {
+ if (mapping_entry->enum_value == entry_value) {
+ return base::Value::ToUniquePtrValue(
+ mapping_entry->mapped_value->Clone());
+ }
+ }
+ return nullptr;
+}
+
+// IntRangePolicyHandler implementation ----------------------------------------
+
+IntRangePolicyHandler::IntRangePolicyHandler(const char* policy_name,
+ const char* pref_path,
+ int min,
+ int max,
+ bool clamp)
+ : IntRangePolicyHandlerBase(policy_name, min, max, clamp),
+ pref_path_(pref_path) {}
+
+IntRangePolicyHandler::~IntRangePolicyHandler() {}
+
+void IntRangePolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
+ PrefValueMap* prefs) {
+ if (!pref_path_)
+ return;
+ const base::Value* value =
+ policies.GetValue(policy_name(), base::Value::Type::INTEGER);
+ int value_in_range;
+ if (value && EnsureInRange(value, &value_in_range, nullptr))
+ prefs->SetInteger(pref_path_, value_in_range);
+}
+
+// IntPercentageToDoublePolicyHandler implementation ---------------------------
+
+IntPercentageToDoublePolicyHandler::IntPercentageToDoublePolicyHandler(
+ const char* policy_name,
+ const char* pref_path,
+ int min,
+ int max,
+ bool clamp)
+ : IntRangePolicyHandlerBase(policy_name, min, max, clamp),
+ pref_path_(pref_path) {}
+
+IntPercentageToDoublePolicyHandler::~IntPercentageToDoublePolicyHandler() {}
+
+void IntPercentageToDoublePolicyHandler::ApplyPolicySettings(
+ const PolicyMap& policies,
+ PrefValueMap* prefs) {
+ if (!pref_path_)
+ return;
+ const base::Value* value =
+ policies.GetValue(policy_name(), base::Value::Type::INTEGER);
+ int percentage;
+ if (value && EnsureInRange(value, &percentage, nullptr))
+ prefs->SetDouble(pref_path_, static_cast<double>(percentage) / 100.);
+}
+
+// SimplePolicyHandler implementation ------------------------------------------
+
+SimplePolicyHandler::SimplePolicyHandler(const char* policy_name,
+ const char* pref_path,
+ base::Value::Type value_type)
+ : TypeCheckingPolicyHandler(policy_name, value_type),
+ pref_path_(pref_path) {}
+
+SimplePolicyHandler::~SimplePolicyHandler() {}
+
+void SimplePolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
+ PrefValueMap* prefs) {
+ if (!pref_path_)
+ return;
+ // It is safe to use `GetValueUnsafe()` as multiple policy types are handled.
+ const base::Value* value = policies.GetValueUnsafe(policy_name());
+ if (value)
+ prefs->SetValue(pref_path_, value->Clone());
+}
+
+// SchemaValidatingPolicyHandler implementation --------------------------------
+
+SchemaValidatingPolicyHandler::SchemaValidatingPolicyHandler(
+ const char* policy_name,
+ Schema schema,
+ SchemaOnErrorStrategy strategy)
+ : NamedPolicyHandler(policy_name), schema_(schema), strategy_(strategy) {
+ DCHECK(schema_.valid());
+}
+
+SchemaValidatingPolicyHandler::~SchemaValidatingPolicyHandler() {}
+
+bool SchemaValidatingPolicyHandler::CheckPolicySettings(
+ const PolicyMap& policies,
+ PolicyErrorMap* errors) {
+ // It is safe to use `GetValueUnsafe()` as multiple policy types are handled.
+ const base::Value* value = policies.GetValueUnsafe(policy_name());
+ if (!value)
+ return true;
+
+ std::string error_path;
+ std::string error;
+ bool result = schema_.Validate(*value, strategy_, &error_path, &error);
+
+ if (errors && !error.empty()) {
+ if (error_path.empty())
+ error_path = "(ROOT)";
+ errors->AddError(policy_name(), error_path, error);
+ }
+
+ return result;
+}
+
+bool SchemaValidatingPolicyHandler::CheckAndGetValue(
+ const PolicyMap& policies,
+ PolicyErrorMap* errors,
+ std::unique_ptr<base::Value>* output) {
+ // It is safe to use `GetValueUnsafe()` as multiple policy types are handled.
+ const base::Value* value = policies.GetValueUnsafe(policy_name());
+ if (!value)
+ return true;
+
+ *output = base::Value::ToUniquePtrValue(value->Clone());
+ std::string error_path;
+ std::string error;
+ bool result =
+ schema_.Normalize(output->get(), strategy_, &error_path, &error, nullptr);
+
+ if (errors && !error.empty()) {
+ if (error_path.empty())
+ error_path = "(ROOT)";
+ errors->AddError(policy_name(), error_path, error);
+ }
+
+ return result;
+}
+
+// SimpleSchemaValidatingPolicyHandler implementation --------------------------
+
+SimpleSchemaValidatingPolicyHandler::SimpleSchemaValidatingPolicyHandler(
+ const char* policy_name,
+ const char* pref_path,
+ Schema schema,
+ SchemaOnErrorStrategy strategy,
+ RecommendedPermission recommended_permission,
+ MandatoryPermission mandatory_permission)
+ : SchemaValidatingPolicyHandler(policy_name,
+ schema.GetKnownProperty(policy_name),
+ strategy),
+ pref_path_(pref_path),
+ allow_recommended_(recommended_permission == RECOMMENDED_ALLOWED),
+ allow_mandatory_(mandatory_permission == MANDATORY_ALLOWED) {}
+
+SimpleSchemaValidatingPolicyHandler::~SimpleSchemaValidatingPolicyHandler() {}
+
+bool SimpleSchemaValidatingPolicyHandler::CheckPolicySettings(
+ const PolicyMap& policies,
+ PolicyErrorMap* errors) {
+ const PolicyMap::Entry* policy_entry = policies.Get(policy_name());
+ if (!policy_entry)
+ return true;
+ if ((policy_entry->level == policy::POLICY_LEVEL_MANDATORY &&
+ !allow_mandatory_) ||
+ (policy_entry->level == policy::POLICY_LEVEL_RECOMMENDED &&
+ !allow_recommended_)) {
+ if (errors)
+ errors->AddError(policy_name(), IDS_POLICY_LEVEL_ERROR);
+ return false;
+ }
+
+ return SchemaValidatingPolicyHandler::CheckPolicySettings(policies, errors);
+}
+
+void SimpleSchemaValidatingPolicyHandler::ApplyPolicySettings(
+ const PolicyMap& policies,
+ PrefValueMap* prefs) {
+ if (!pref_path_)
+ return;
+ // It is safe to use `GetValueUnsafe()` as multiple policy types are handled.
+ const base::Value* value = policies.GetValueUnsafe(policy_name());
+ if (value)
+ prefs->SetValue(pref_path_, value->Clone());
+}
+
+// SimpleJsonStringSchemaValidatingPolicyHandler implementation ----------------
+
+SimpleJsonStringSchemaValidatingPolicyHandler::
+ SimpleJsonStringSchemaValidatingPolicyHandler(
+ const char* policy_name,
+ const char* pref_path,
+ Schema schema,
+ SimpleSchemaValidatingPolicyHandler::RecommendedPermission
+ recommended_permission,
+ SimpleSchemaValidatingPolicyHandler::MandatoryPermission
+ mandatory_permission)
+ : NamedPolicyHandler(policy_name),
+ schema_(schema.GetKnownProperty(policy_name)),
+ pref_path_(pref_path),
+ allow_recommended_(
+ recommended_permission ==
+ SimpleSchemaValidatingPolicyHandler::RECOMMENDED_ALLOWED),
+ allow_mandatory_(mandatory_permission ==
+ SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED) {
+}
+
+SimpleJsonStringSchemaValidatingPolicyHandler::
+ ~SimpleJsonStringSchemaValidatingPolicyHandler() {}
+
+bool SimpleJsonStringSchemaValidatingPolicyHandler::CheckPolicySettings(
+ const PolicyMap& policies,
+ PolicyErrorMap* errors) {
+ // It is safe to use `GetValueUnsafe()` as multiple policy types are handled.
+ const base::Value* root_value = policies.GetValueUnsafe(policy_name());
+ if (!root_value)
+ return true;
+
+ const PolicyMap::Entry* policy_entry = policies.Get(policy_name());
+ if ((policy_entry->level == policy::POLICY_LEVEL_MANDATORY &&
+ !allow_mandatory_) ||
+ (policy_entry->level == policy::POLICY_LEVEL_RECOMMENDED &&
+ !allow_recommended_)) {
+ if (errors)
+ errors->AddError(policy_name(), IDS_POLICY_LEVEL_ERROR);
+ return false;
+ }
+
+ if (IsListSchema())
+ return CheckListOfJsonStrings(root_value, errors);
+
+ return CheckSingleJsonString(root_value, errors);
+}
+
+bool SimpleJsonStringSchemaValidatingPolicyHandler::CheckSingleJsonString(
+ const base::Value* root_value,
+ PolicyErrorMap* errors) {
+ // First validate the root value is a string.
+ if (!root_value->is_string()) {
+ if (errors) {
+ errors->AddError(policy_name(), "(ROOT)", IDS_POLICY_TYPE_ERROR,
+ base::Value::GetTypeName(base::Value::Type::STRING));
+ }
+ return false;
+ }
+
+ // If that succeeds, validate the JSON inside the string.
+ const std::string& json_string = root_value->GetString();
+ if (!ValidateJsonString(json_string, errors, 0))
+ RecordJsonError();
+
+ // Very lenient - return true as long as the root value is a string.
+ return true;
+}
+
+bool SimpleJsonStringSchemaValidatingPolicyHandler::CheckListOfJsonStrings(
+ const base::Value* root_value,
+ PolicyErrorMap* errors) {
+ // First validate the root value is a list.
+ if (!root_value->is_list()) {
+ if (errors) {
+ errors->AddError(policy_name(), "(ROOT)", IDS_POLICY_TYPE_ERROR,
+ base::Value::GetTypeName(base::Value::Type::LIST));
+ }
+ return false;
+ }
+
+ // If that succeeds, validate all the list items are strings and validate
+ // the JSON inside the strings.
+ base::Value::ConstListView list = root_value->GetListDeprecated();
+ bool json_error_seen = false;
+
+ for (size_t index = 0; index < list.size(); ++index) {
+ const base::Value& entry = list[index];
+ if (!entry.is_string()) {
+ if (errors) {
+ errors->AddError(policy_name(), index, IDS_POLICY_TYPE_ERROR,
+ base::Value::GetTypeName(base::Value::Type::STRING));
+ }
+ continue;
+ }
+
+ const std::string& json_string = entry.GetString();
+ if (!ValidateJsonString(json_string, errors, index))
+ json_error_seen = true;
+ }
+
+ if (json_error_seen)
+ RecordJsonError();
+
+ // Very lenient - return true as long as the root value is a list.
+ return true;
+}
+
+bool SimpleJsonStringSchemaValidatingPolicyHandler::ValidateJsonString(
+ const std::string& json_string,
+ PolicyErrorMap* errors,
+ int index) {
+ base::JSONReader::ValueWithError value_with_error =
+ base::JSONReader::ReadAndReturnValueWithError(
+ json_string, base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS);
+ if (!value_with_error.value) {
+ if (errors) {
+ errors->AddError(policy_name(), ErrorPath(index, ""),
+ IDS_POLICY_INVALID_JSON_ERROR,
+ value_with_error.error_message);
+ }
+ return false;
+ }
+
+ std::string schema_error;
+ std::string error_path;
+ const Schema json_string_schema =
+ IsListSchema() ? schema_.GetItems() : schema_;
+ // Even though we are validating this schema here, we don't actually change
+ // the policy if it fails to validate. This validation is just so we can show
+ // the user errors.
+ bool validated = json_string_schema.Validate(value_with_error.value.value(),
+ SCHEMA_ALLOW_UNKNOWN,
+ &error_path, &schema_error);
+ if (errors && !schema_error.empty())
+ errors->AddError(policy_name(), ErrorPath(index, error_path), schema_error);
+ if (!validated)
+ return false;
+
+ return true;
+}
+
+std::string SimpleJsonStringSchemaValidatingPolicyHandler::ErrorPath(
+ int index,
+ std::string json_error_path) {
+ if (IsListSchema()) {
+ return json_error_path.empty()
+ ? base::StringPrintf("items[%d]", index)
+ : base::StringPrintf("items[%d].%s", index,
+ json_error_path.c_str());
+ }
+ return json_error_path.empty() ? "(ROOT)" : json_error_path;
+}
+
+void SimpleJsonStringSchemaValidatingPolicyHandler::ApplyPolicySettings(
+ const PolicyMap& policies,
+ PrefValueMap* prefs) {
+ if (!pref_path_)
+ return;
+ // It is safe to use `GetValueUnsafe()` as multiple policy types are handled.
+ const base::Value* value = policies.GetValueUnsafe(policy_name());
+ if (value)
+ prefs->SetValue(pref_path_, value->Clone());
+}
+
+void SimpleJsonStringSchemaValidatingPolicyHandler::RecordJsonError() {
+ const PolicyDetails* details = GetChromePolicyDetails(policy_name());
+ if (details) {
+ base::UmaHistogramSparse("EnterpriseCheck.InvalidJsonPolicies",
+ details->id);
+ }
+}
+
+bool SimpleJsonStringSchemaValidatingPolicyHandler::IsListSchema() const {
+ return schema_.type() == base::Value::Type::LIST;
+}
+
+// LegacyPoliciesDeprecatingPolicyHandler implementation -----------------------
+
+LegacyPoliciesDeprecatingPolicyHandler::LegacyPoliciesDeprecatingPolicyHandler(
+ std::vector<std::unique_ptr<ConfigurationPolicyHandler>>
+ legacy_policy_handlers,
+ std::unique_ptr<NamedPolicyHandler> new_policy_handler)
+ : legacy_policy_handlers_(std::move(legacy_policy_handlers)),
+ new_policy_handler_(std::move(new_policy_handler)) {}
+
+LegacyPoliciesDeprecatingPolicyHandler::
+ ~LegacyPoliciesDeprecatingPolicyHandler() {}
+
+bool LegacyPoliciesDeprecatingPolicyHandler::CheckPolicySettings(
+ const PolicyMap& policies,
+ PolicyErrorMap* errors) {
+ if (policies.Get(new_policy_handler_->policy_name()))
+ return new_policy_handler_->CheckPolicySettings(policies, errors);
+
+ // The new policy is not set, fall back to legacy ones.
+ bool valid_policy_found = false;
+ for (const auto& handler : legacy_policy_handlers_) {
+ if (handler->CheckPolicySettings(policies, errors))
+ valid_policy_found = true;
+ }
+ return valid_policy_found;
+}
+
+void LegacyPoliciesDeprecatingPolicyHandler::ApplyPolicySettingsWithParameters(
+ const policy::PolicyMap& policies,
+ const policy::PolicyHandlerParameters& parameters,
+ PrefValueMap* prefs) {
+ if (policies.Get(new_policy_handler_->policy_name())) {
+ new_policy_handler_->ApplyPolicySettingsWithParameters(policies, parameters,
+ prefs);
+ return;
+ }
+
+ // The new policy is not set, fall back to legacy ones.
+ PolicyErrorMap scoped_errors;
+ for (const auto& handler : legacy_policy_handlers_) {
+ if (handler->CheckPolicySettings(policies, &scoped_errors))
+ handler->ApplyPolicySettingsWithParameters(policies, parameters, prefs);
+ }
+}
+
+void LegacyPoliciesDeprecatingPolicyHandler::ApplyPolicySettings(
+ const policy::PolicyMap& /* policies */,
+ PrefValueMap* /* prefs */) {
+ NOTREACHED();
+}
+
+// SimpleDeprecatingPolicyHandler implementation -----------------------
+
+SimpleDeprecatingPolicyHandler::SimpleDeprecatingPolicyHandler(
+ std::unique_ptr<NamedPolicyHandler> legacy_policy_handler,
+ std::unique_ptr<NamedPolicyHandler> new_policy_handler)
+ : legacy_policy_handler_(std::move(legacy_policy_handler)),
+ new_policy_handler_(std::move(new_policy_handler)) {}
+
+SimpleDeprecatingPolicyHandler::~SimpleDeprecatingPolicyHandler() = default;
+
+bool SimpleDeprecatingPolicyHandler::CheckPolicySettings(
+ const PolicyMap& policies,
+ PolicyErrorMap* errors) {
+ if (policies.Get(new_policy_handler_->policy_name())) {
+ if (policies.Get(legacy_policy_handler_->policy_name())) {
+ errors->AddError(legacy_policy_handler_->policy_name(),
+ IDS_POLICY_OVERRIDDEN,
+ new_policy_handler_->policy_name());
+ }
+ return new_policy_handler_->CheckPolicySettings(policies, errors);
+ }
+
+ // The new policy is not set, fall back to legacy ones.
+ return legacy_policy_handler_->CheckPolicySettings(policies, errors);
+}
+
+void SimpleDeprecatingPolicyHandler::ApplyPolicySettingsWithParameters(
+ const policy::PolicyMap& policies,
+ const policy::PolicyHandlerParameters& parameters,
+ PrefValueMap* prefs) {
+ if (policies.Get(new_policy_handler_->policy_name())) {
+ new_policy_handler_->ApplyPolicySettingsWithParameters(policies, parameters,
+ prefs);
+ } else {
+ legacy_policy_handler_->ApplyPolicySettingsWithParameters(
+ policies, parameters, prefs);
+ }
+}
+
+void SimpleDeprecatingPolicyHandler::ApplyPolicySettings(
+ const policy::PolicyMap& /* policies */,
+ PrefValueMap* /* prefs */) {
+ NOTREACHED();
+}
+
+} // namespace policy