1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/policy/core/browser/configuration_policy_handler.h"
9 #include "base/callback.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "base/prefs/pref_value_map.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "components/policy/core/browser/policy_error_map.h"
17 #include "components/policy/core/common/policy_map.h"
18 #include "grit/component_strings.h"
23 // ConfigurationPolicyHandler implementation -----------------------------------
26 std::string
ConfigurationPolicyHandler::ValueTypeToString(
27 base::Value::Type type
) {
28 static const char* strings
[] = {
38 CHECK(static_cast<size_t>(type
) < arraysize(strings
));
39 return std::string(strings
[type
]);
42 ConfigurationPolicyHandler::ConfigurationPolicyHandler() {
45 ConfigurationPolicyHandler::~ConfigurationPolicyHandler() {
48 void ConfigurationPolicyHandler::PrepareForDisplaying(
49 PolicyMap
* policies
) const {}
51 void ConfigurationPolicyHandler::ApplyPolicySettings(
52 const policy::PolicyMap
& policies
,
53 PrefValueMap
* prefs
) {
57 void ConfigurationPolicyHandler::ApplyPolicySettingsWithParameters(
58 const PolicyMap
& policies
,
59 const PolicyHandlerParameters
& parameters
,
60 PrefValueMap
* prefs
) {
61 ApplyPolicySettings(policies
, prefs
);
64 // TypeCheckingPolicyHandler implementation ------------------------------------
66 TypeCheckingPolicyHandler::TypeCheckingPolicyHandler(
67 const char* policy_name
,
68 base::Value::Type value_type
)
69 : policy_name_(policy_name
),
70 value_type_(value_type
) {
73 TypeCheckingPolicyHandler::~TypeCheckingPolicyHandler() {
76 const char* TypeCheckingPolicyHandler::policy_name() const {
80 bool TypeCheckingPolicyHandler::CheckPolicySettings(const PolicyMap
& policies
,
81 PolicyErrorMap
* errors
) {
82 const base::Value
* value
= NULL
;
83 return CheckAndGetValue(policies
, errors
, &value
);
86 bool TypeCheckingPolicyHandler::CheckAndGetValue(const PolicyMap
& policies
,
87 PolicyErrorMap
* errors
,
88 const base::Value
** value
) {
89 *value
= policies
.GetValue(policy_name_
);
90 if (*value
&& !(*value
)->IsType(value_type_
)) {
91 errors
->AddError(policy_name_
,
92 IDS_POLICY_TYPE_ERROR
,
93 ValueTypeToString(value_type_
));
100 // IntRangePolicyHandlerBase implementation ------------------------------------
102 IntRangePolicyHandlerBase::IntRangePolicyHandlerBase(
103 const char* policy_name
,
107 : TypeCheckingPolicyHandler(policy_name
, base::Value::TYPE_INTEGER
),
113 bool IntRangePolicyHandlerBase::CheckPolicySettings(const PolicyMap
& policies
,
114 PolicyErrorMap
* errors
) {
115 const base::Value
* value
;
116 return CheckAndGetValue(policies
, errors
, &value
) &&
117 EnsureInRange(value
, NULL
, errors
);
120 IntRangePolicyHandlerBase::~IntRangePolicyHandlerBase() {
123 bool IntRangePolicyHandlerBase::EnsureInRange(const base::Value
* input
,
125 PolicyErrorMap
* errors
) {
130 if (!input
->GetAsInteger(&value
)) {
135 if (value
< min_
|| value
> max_
) {
137 errors
->AddError(policy_name(),
138 IDS_POLICY_OUT_OF_RANGE_ERROR
,
139 base::IntToString(value
));
145 value
= std::min(std::max(value
, min_
), max_
);
154 // StringToIntEnumListPolicyHandler implementation -----------------------------
156 StringToIntEnumListPolicyHandler::StringToIntEnumListPolicyHandler(
157 const char* policy_name
,
158 const char* pref_path
,
159 const MappingEntry
* mapping_begin
,
160 const MappingEntry
* mapping_end
)
161 : TypeCheckingPolicyHandler(policy_name
, base::Value::TYPE_LIST
),
162 pref_path_(pref_path
),
163 mapping_begin_(mapping_begin
),
164 mapping_end_(mapping_end
) {}
166 bool StringToIntEnumListPolicyHandler::CheckPolicySettings(
167 const PolicyMap
& policies
,
168 PolicyErrorMap
* errors
) {
169 const base::Value
* value
;
170 return CheckAndGetValue(policies
, errors
, &value
) &&
171 Convert(value
, NULL
, errors
);
174 void StringToIntEnumListPolicyHandler::ApplyPolicySettings(
175 const PolicyMap
& policies
,
176 PrefValueMap
* prefs
) {
179 const base::Value
* value
= policies
.GetValue(policy_name());
180 scoped_ptr
<base::ListValue
> list(new base::ListValue());
181 if (value
&& Convert(value
, list
.get(), NULL
))
182 prefs
->SetValue(pref_path_
, list
.release());
185 bool StringToIntEnumListPolicyHandler::Convert(const base::Value
* input
,
186 base::ListValue
* output
,
187 PolicyErrorMap
* errors
) {
191 const base::ListValue
* list_value
= NULL
;
192 if (!input
->GetAsList(&list_value
)) {
197 for (base::ListValue::const_iterator
entry(list_value
->begin());
198 entry
!= list_value
->end(); ++entry
) {
199 std::string entry_value
;
200 if (!(*entry
)->GetAsString(&entry_value
)) {
202 errors
->AddError(policy_name(),
203 entry
- list_value
->begin(),
204 IDS_POLICY_TYPE_ERROR
,
205 ValueTypeToString(base::Value::TYPE_STRING
));
210 for (const MappingEntry
* mapping_entry(mapping_begin_
);
211 mapping_entry
!= mapping_end_
; ++mapping_entry
) {
212 if (mapping_entry
->enum_value
== entry_value
) {
215 output
->AppendInteger(mapping_entry
->int_value
);
221 errors
->AddError(policy_name(),
222 entry
- list_value
->begin(),
223 IDS_POLICY_OUT_OF_RANGE_ERROR
);
232 // IntRangePolicyHandler implementation ----------------------------------------
234 IntRangePolicyHandler::IntRangePolicyHandler(const char* policy_name
,
235 const char* pref_path
,
239 : IntRangePolicyHandlerBase(policy_name
, min
, max
, clamp
),
240 pref_path_(pref_path
) {
243 IntRangePolicyHandler::~IntRangePolicyHandler() {
246 void IntRangePolicyHandler::ApplyPolicySettings(const PolicyMap
& policies
,
247 PrefValueMap
* prefs
) {
250 const base::Value
* value
= policies
.GetValue(policy_name());
252 if (value
&& EnsureInRange(value
, &value_in_range
, NULL
)) {
253 prefs
->SetValue(pref_path_
,
254 base::Value::CreateIntegerValue(value_in_range
));
259 // IntPercentageToDoublePolicyHandler implementation ---------------------------
261 IntPercentageToDoublePolicyHandler::IntPercentageToDoublePolicyHandler(
262 const char* policy_name
,
263 const char* pref_path
,
267 : IntRangePolicyHandlerBase(policy_name
, min
, max
, clamp
),
268 pref_path_(pref_path
) {
271 IntPercentageToDoublePolicyHandler::~IntPercentageToDoublePolicyHandler() {
274 void IntPercentageToDoublePolicyHandler::ApplyPolicySettings(
275 const PolicyMap
& policies
,
276 PrefValueMap
* prefs
) {
279 const base::Value
* value
= policies
.GetValue(policy_name());
281 if (value
&& EnsureInRange(value
, &percentage
, NULL
)) {
282 prefs
->SetValue(pref_path_
, base::Value::CreateDoubleValue(
283 static_cast<double>(percentage
) / 100.));
288 // SimplePolicyHandler implementation ------------------------------------------
290 SimplePolicyHandler::SimplePolicyHandler(
291 const char* policy_name
,
292 const char* pref_path
,
293 base::Value::Type value_type
)
294 : TypeCheckingPolicyHandler(policy_name
, value_type
),
295 pref_path_(pref_path
) {
298 SimplePolicyHandler::~SimplePolicyHandler() {
301 void SimplePolicyHandler::ApplyPolicySettings(const PolicyMap
& policies
,
302 PrefValueMap
* prefs
) {
305 const base::Value
* value
= policies
.GetValue(policy_name());
307 prefs
->SetValue(pref_path_
, value
->DeepCopy());
311 // SchemaValidatingPolicyHandler implementation --------------------------------
313 SchemaValidatingPolicyHandler::SchemaValidatingPolicyHandler(
314 const char* policy_name
,
316 SchemaOnErrorStrategy strategy
)
317 : policy_name_(policy_name
), schema_(schema
), strategy_(strategy
) {
318 DCHECK(schema_
.valid());
321 SchemaValidatingPolicyHandler::~SchemaValidatingPolicyHandler() {
324 const char* SchemaValidatingPolicyHandler::policy_name() const {
328 bool SchemaValidatingPolicyHandler::CheckPolicySettings(
329 const PolicyMap
& policies
,
330 PolicyErrorMap
* errors
) {
331 const base::Value
* value
= policies
.GetValue(policy_name());
335 std::string error_path
;
337 bool result
= schema_
.Validate(*value
, strategy_
, &error_path
, &error
);
339 if (errors
&& !error
.empty()) {
340 if (error_path
.empty())
341 error_path
= "(ROOT)";
342 errors
->AddError(policy_name_
, error_path
, error
);
348 bool SchemaValidatingPolicyHandler::CheckAndGetValue(
349 const PolicyMap
& policies
,
350 PolicyErrorMap
* errors
,
351 scoped_ptr
<base::Value
>* output
) {
352 const base::Value
* value
= policies
.GetValue(policy_name());
356 output
->reset(value
->DeepCopy());
357 std::string error_path
;
360 schema_
.Normalize(output
->get(), strategy_
, &error_path
, &error
, NULL
);
362 if (errors
&& !error
.empty()) {
363 if (error_path
.empty())
364 error_path
= "(ROOT)";
365 errors
->AddError(policy_name_
, error_path
, error
);
371 // LegacyPoliciesDeprecatingPolicyHandler implementation -----------------------
373 // TODO(binjin): Add a new common base class for SchemaValidatingPolicyHandler
374 // and TypeCheckingPolicyHandler representing policy handlers for a single
375 // policy, and use it as the type of |new_policy_handler|.
376 // http://crbug.com/345299
377 LegacyPoliciesDeprecatingPolicyHandler::LegacyPoliciesDeprecatingPolicyHandler(
378 ScopedVector
<ConfigurationPolicyHandler
> legacy_policy_handlers
,
379 scoped_ptr
<SchemaValidatingPolicyHandler
> new_policy_handler
)
380 : legacy_policy_handlers_(legacy_policy_handlers
.Pass()),
381 new_policy_handler_(new_policy_handler
.Pass()) {
384 LegacyPoliciesDeprecatingPolicyHandler::
385 ~LegacyPoliciesDeprecatingPolicyHandler() {
388 bool LegacyPoliciesDeprecatingPolicyHandler::CheckPolicySettings(
389 const PolicyMap
& policies
,
390 PolicyErrorMap
* errors
) {
391 if (policies
.Get(new_policy_handler_
->policy_name())) {
392 return new_policy_handler_
->CheckPolicySettings(policies
, errors
);
394 // The new policy is not set, fall back to legacy ones.
395 ScopedVector
<ConfigurationPolicyHandler
>::iterator handler
;
396 bool valid_policy_found
= false;
397 for (handler
= legacy_policy_handlers_
.begin();
398 handler
!= legacy_policy_handlers_
.end();
400 if ((*handler
)->CheckPolicySettings(policies
, errors
))
401 valid_policy_found
= true;
403 return valid_policy_found
;
407 void LegacyPoliciesDeprecatingPolicyHandler::ApplyPolicySettings(
408 const PolicyMap
& policies
,
409 PrefValueMap
* prefs
) {
410 if (policies
.Get(new_policy_handler_
->policy_name())) {
411 new_policy_handler_
->ApplyPolicySettings(policies
, prefs
);
413 // The new policy is not set, fall back to legacy ones.
414 PolicyErrorMap scoped_errors
;
415 ScopedVector
<ConfigurationPolicyHandler
>::iterator handler
;
416 for (handler
= legacy_policy_handlers_
.begin();
417 handler
!= legacy_policy_handlers_
.end();
419 if ((*handler
)->CheckPolicySettings(policies
, &scoped_errors
))
420 (*handler
)->ApplyPolicySettings(policies
, prefs
);
425 } // namespace policy