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/components_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 // StringMappingListPolicyHandler implementation -----------------------------
156 StringMappingListPolicyHandler::MappingEntry::MappingEntry(
157 const char* policy_value
, scoped_ptr
<base::Value
> map
)
158 : enum_value(policy_value
), mapped_value(map
.Pass()) {}
160 StringMappingListPolicyHandler::MappingEntry::~MappingEntry() {}
162 StringMappingListPolicyHandler::StringMappingListPolicyHandler(
163 const char* policy_name
,
164 const char* pref_path
,
165 const GenerateMapCallback
& callback
)
166 : TypeCheckingPolicyHandler(policy_name
, base::Value::TYPE_LIST
),
167 pref_path_(pref_path
),
168 map_getter_(callback
) {}
170 StringMappingListPolicyHandler::~StringMappingListPolicyHandler() {}
172 bool StringMappingListPolicyHandler::CheckPolicySettings(
173 const PolicyMap
& policies
,
174 PolicyErrorMap
* errors
) {
175 const base::Value
* value
;
176 return CheckAndGetValue(policies
, errors
, &value
) &&
177 Convert(value
, NULL
, errors
);
180 void StringMappingListPolicyHandler::ApplyPolicySettings(
181 const PolicyMap
& policies
,
182 PrefValueMap
* prefs
) {
185 const base::Value
* value
= policies
.GetValue(policy_name());
186 scoped_ptr
<base::ListValue
> list(new base::ListValue());
187 if (value
&& Convert(value
, list
.get(), NULL
))
188 prefs
->SetValue(pref_path_
, list
.release());
191 bool StringMappingListPolicyHandler::Convert(const base::Value
* input
,
192 base::ListValue
* output
,
193 PolicyErrorMap
* errors
) {
197 const base::ListValue
* list_value
= NULL
;
198 if (!input
->GetAsList(&list_value
)) {
203 for (base::ListValue::const_iterator
entry(list_value
->begin());
204 entry
!= list_value
->end(); ++entry
) {
205 std::string entry_value
;
206 if (!(*entry
)->GetAsString(&entry_value
)) {
208 errors
->AddError(policy_name(),
209 entry
- list_value
->begin(),
210 IDS_POLICY_TYPE_ERROR
,
211 ValueTypeToString(base::Value::TYPE_STRING
));
216 scoped_ptr
<base::Value
> mapped_value
= Map(entry_value
);
219 output
->Append(mapped_value
.release());
222 errors
->AddError(policy_name(),
223 entry
- list_value
->begin(),
224 IDS_POLICY_OUT_OF_RANGE_ERROR
);
232 scoped_ptr
<base::Value
> StringMappingListPolicyHandler::Map(
233 const std::string
& entry_value
) {
234 // Lazily generate the map of policy strings to mapped values.
236 map_getter_
.Run(&map_
);
238 scoped_ptr
<base::Value
> return_value
;
239 for (ScopedVector
<MappingEntry
>::const_iterator it
= map_
.begin();
240 it
!= map_
.end(); ++it
) {
241 const MappingEntry
* mapping_entry
= *it
;
242 if (mapping_entry
->enum_value
== entry_value
) {
243 return_value
= make_scoped_ptr(mapping_entry
->mapped_value
->DeepCopy());
247 return return_value
.Pass();
250 // IntRangePolicyHandler implementation ----------------------------------------
252 IntRangePolicyHandler::IntRangePolicyHandler(const char* policy_name
,
253 const char* pref_path
,
257 : IntRangePolicyHandlerBase(policy_name
, min
, max
, clamp
),
258 pref_path_(pref_path
) {
261 IntRangePolicyHandler::~IntRangePolicyHandler() {
264 void IntRangePolicyHandler::ApplyPolicySettings(const PolicyMap
& policies
,
265 PrefValueMap
* prefs
) {
268 const base::Value
* value
= policies
.GetValue(policy_name());
270 if (value
&& EnsureInRange(value
, &value_in_range
, NULL
))
271 prefs
->SetInteger(pref_path_
, value_in_range
);
275 // IntPercentageToDoublePolicyHandler implementation ---------------------------
277 IntPercentageToDoublePolicyHandler::IntPercentageToDoublePolicyHandler(
278 const char* policy_name
,
279 const char* pref_path
,
283 : IntRangePolicyHandlerBase(policy_name
, min
, max
, clamp
),
284 pref_path_(pref_path
) {
287 IntPercentageToDoublePolicyHandler::~IntPercentageToDoublePolicyHandler() {
290 void IntPercentageToDoublePolicyHandler::ApplyPolicySettings(
291 const PolicyMap
& policies
,
292 PrefValueMap
* prefs
) {
295 const base::Value
* value
= policies
.GetValue(policy_name());
297 if (value
&& EnsureInRange(value
, &percentage
, NULL
))
298 prefs
->SetDouble(pref_path_
, static_cast<double>(percentage
) / 100.);
302 // SimplePolicyHandler implementation ------------------------------------------
304 SimplePolicyHandler::SimplePolicyHandler(
305 const char* policy_name
,
306 const char* pref_path
,
307 base::Value::Type value_type
)
308 : TypeCheckingPolicyHandler(policy_name
, value_type
),
309 pref_path_(pref_path
) {
312 SimplePolicyHandler::~SimplePolicyHandler() {
315 void SimplePolicyHandler::ApplyPolicySettings(const PolicyMap
& policies
,
316 PrefValueMap
* prefs
) {
319 const base::Value
* value
= policies
.GetValue(policy_name());
321 prefs
->SetValue(pref_path_
, value
->DeepCopy());
325 // SchemaValidatingPolicyHandler implementation --------------------------------
327 SchemaValidatingPolicyHandler::SchemaValidatingPolicyHandler(
328 const char* policy_name
,
330 SchemaOnErrorStrategy strategy
)
331 : policy_name_(policy_name
), schema_(schema
), strategy_(strategy
) {
332 DCHECK(schema_
.valid());
335 SchemaValidatingPolicyHandler::~SchemaValidatingPolicyHandler() {
338 const char* SchemaValidatingPolicyHandler::policy_name() const {
342 bool SchemaValidatingPolicyHandler::CheckPolicySettings(
343 const PolicyMap
& policies
,
344 PolicyErrorMap
* errors
) {
345 const base::Value
* value
= policies
.GetValue(policy_name());
349 std::string error_path
;
351 bool result
= schema_
.Validate(*value
, strategy_
, &error_path
, &error
);
353 if (errors
&& !error
.empty()) {
354 if (error_path
.empty())
355 error_path
= "(ROOT)";
356 errors
->AddError(policy_name_
, error_path
, error
);
362 bool SchemaValidatingPolicyHandler::CheckAndGetValue(
363 const PolicyMap
& policies
,
364 PolicyErrorMap
* errors
,
365 scoped_ptr
<base::Value
>* output
) {
366 const base::Value
* value
= policies
.GetValue(policy_name());
370 output
->reset(value
->DeepCopy());
371 std::string error_path
;
374 schema_
.Normalize(output
->get(), strategy_
, &error_path
, &error
, NULL
);
376 if (errors
&& !error
.empty()) {
377 if (error_path
.empty())
378 error_path
= "(ROOT)";
379 errors
->AddError(policy_name_
, error_path
, error
);
385 // SimpleSchemaValidatingPolicyHandler implementation --------------------------
387 SimpleSchemaValidatingPolicyHandler::SimpleSchemaValidatingPolicyHandler(
388 const char* policy_name
,
389 const char* pref_path
,
391 SchemaOnErrorStrategy strategy
,
392 RecommendedPermission recommended_permission
,
393 MandatoryPermission mandatory_permission
)
394 : SchemaValidatingPolicyHandler(policy_name
,
395 schema
.GetKnownProperty(policy_name
),
397 pref_path_(pref_path
),
398 allow_recommended_(recommended_permission
== RECOMMENDED_ALLOWED
),
399 allow_mandatory_(mandatory_permission
== MANDATORY_ALLOWED
) {
402 SimpleSchemaValidatingPolicyHandler::~SimpleSchemaValidatingPolicyHandler() {
405 bool SimpleSchemaValidatingPolicyHandler::CheckPolicySettings(
406 const PolicyMap
& policies
,
407 PolicyErrorMap
* errors
) {
408 const PolicyMap::Entry
* policy_entry
= policies
.Get(policy_name());
411 if ((policy_entry
->level
== policy::POLICY_LEVEL_MANDATORY
&&
412 !allow_mandatory_
) ||
413 (policy_entry
->level
== policy::POLICY_LEVEL_RECOMMENDED
&&
414 !allow_recommended_
)) {
416 errors
->AddError(policy_name(), IDS_POLICY_LEVEL_ERROR
);
420 return SchemaValidatingPolicyHandler::CheckPolicySettings(policies
, errors
);
423 void SimpleSchemaValidatingPolicyHandler::ApplyPolicySettings(
424 const PolicyMap
& policies
,
425 PrefValueMap
* prefs
) {
428 const base::Value
* value
= policies
.GetValue(policy_name());
430 prefs
->SetValue(pref_path_
, value
->DeepCopy());
433 // LegacyPoliciesDeprecatingPolicyHandler implementation -----------------------
435 // TODO(binjin): Add a new common base class for SchemaValidatingPolicyHandler
436 // and TypeCheckingPolicyHandler representing policy handlers for a single
437 // policy, and use it as the type of |new_policy_handler|.
438 // http://crbug.com/345299
439 LegacyPoliciesDeprecatingPolicyHandler::LegacyPoliciesDeprecatingPolicyHandler(
440 ScopedVector
<ConfigurationPolicyHandler
> legacy_policy_handlers
,
441 scoped_ptr
<SchemaValidatingPolicyHandler
> new_policy_handler
)
442 : legacy_policy_handlers_(legacy_policy_handlers
.Pass()),
443 new_policy_handler_(new_policy_handler
.Pass()) {
446 LegacyPoliciesDeprecatingPolicyHandler::
447 ~LegacyPoliciesDeprecatingPolicyHandler() {
450 bool LegacyPoliciesDeprecatingPolicyHandler::CheckPolicySettings(
451 const PolicyMap
& policies
,
452 PolicyErrorMap
* errors
) {
453 if (policies
.Get(new_policy_handler_
->policy_name())) {
454 return new_policy_handler_
->CheckPolicySettings(policies
, errors
);
456 // The new policy is not set, fall back to legacy ones.
457 ScopedVector
<ConfigurationPolicyHandler
>::iterator handler
;
458 bool valid_policy_found
= false;
459 for (handler
= legacy_policy_handlers_
.begin();
460 handler
!= legacy_policy_handlers_
.end();
462 if ((*handler
)->CheckPolicySettings(policies
, errors
))
463 valid_policy_found
= true;
465 return valid_policy_found
;
469 void LegacyPoliciesDeprecatingPolicyHandler::ApplyPolicySettings(
470 const PolicyMap
& policies
,
471 PrefValueMap
* prefs
) {
472 if (policies
.Get(new_policy_handler_
->policy_name())) {
473 new_policy_handler_
->ApplyPolicySettings(policies
, prefs
);
475 // The new policy is not set, fall back to legacy ones.
476 PolicyErrorMap scoped_errors
;
477 ScopedVector
<ConfigurationPolicyHandler
>::iterator handler
;
478 for (handler
= legacy_policy_handlers_
.begin();
479 handler
!= legacy_policy_handlers_
.end();
481 if ((*handler
)->CheckPolicySettings(policies
, &scoped_errors
))
482 (*handler
)->ApplyPolicySettings(policies
, prefs
);
487 } // namespace policy