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::ApplyPolicySettingsWithParameters(
52 const PolicyMap
& policies
,
53 const PolicyHandlerParameters
& parameters
,
54 PrefValueMap
* prefs
) {
55 ApplyPolicySettings(policies
, prefs
);
58 // TypeCheckingPolicyHandler implementation ------------------------------------
60 TypeCheckingPolicyHandler::TypeCheckingPolicyHandler(
61 const char* policy_name
,
62 base::Value::Type value_type
)
63 : policy_name_(policy_name
),
64 value_type_(value_type
) {
67 TypeCheckingPolicyHandler::~TypeCheckingPolicyHandler() {
70 const char* TypeCheckingPolicyHandler::policy_name() const {
74 bool TypeCheckingPolicyHandler::CheckPolicySettings(const PolicyMap
& policies
,
75 PolicyErrorMap
* errors
) {
76 const base::Value
* value
= NULL
;
77 return CheckAndGetValue(policies
, errors
, &value
);
80 bool TypeCheckingPolicyHandler::CheckAndGetValue(const PolicyMap
& policies
,
81 PolicyErrorMap
* errors
,
82 const base::Value
** value
) {
83 *value
= policies
.GetValue(policy_name_
);
84 if (*value
&& !(*value
)->IsType(value_type_
)) {
85 errors
->AddError(policy_name_
,
86 IDS_POLICY_TYPE_ERROR
,
87 ValueTypeToString(value_type_
));
94 // IntRangePolicyHandlerBase implementation ------------------------------------
96 IntRangePolicyHandlerBase::IntRangePolicyHandlerBase(
97 const char* policy_name
,
101 : TypeCheckingPolicyHandler(policy_name
, base::Value::TYPE_INTEGER
),
107 bool IntRangePolicyHandlerBase::CheckPolicySettings(const PolicyMap
& policies
,
108 PolicyErrorMap
* errors
) {
109 const base::Value
* value
;
110 return CheckAndGetValue(policies
, errors
, &value
) &&
111 EnsureInRange(value
, NULL
, errors
);
114 IntRangePolicyHandlerBase::~IntRangePolicyHandlerBase() {
117 bool IntRangePolicyHandlerBase::EnsureInRange(const base::Value
* input
,
119 PolicyErrorMap
* errors
) {
124 if (!input
->GetAsInteger(&value
)) {
129 if (value
< min_
|| value
> max_
) {
131 errors
->AddError(policy_name(),
132 IDS_POLICY_OUT_OF_RANGE_ERROR
,
133 base::IntToString(value
));
139 value
= std::min(std::max(value
, min_
), max_
);
148 // StringMappingListPolicyHandler implementation -----------------------------
150 StringMappingListPolicyHandler::MappingEntry::MappingEntry(
151 const char* policy_value
, scoped_ptr
<base::Value
> map
)
152 : enum_value(policy_value
), mapped_value(map
.Pass()) {}
154 StringMappingListPolicyHandler::MappingEntry::~MappingEntry() {}
156 StringMappingListPolicyHandler::StringMappingListPolicyHandler(
157 const char* policy_name
,
158 const char* pref_path
,
159 const GenerateMapCallback
& callback
)
160 : TypeCheckingPolicyHandler(policy_name
, base::Value::TYPE_LIST
),
161 pref_path_(pref_path
),
162 map_getter_(callback
) {}
164 StringMappingListPolicyHandler::~StringMappingListPolicyHandler() {}
166 bool StringMappingListPolicyHandler::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 StringMappingListPolicyHandler::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
.Pass());
185 bool StringMappingListPolicyHandler::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 scoped_ptr
<base::Value
> mapped_value
= Map(entry_value
);
213 output
->Append(mapped_value
.release());
216 errors
->AddError(policy_name(),
217 entry
- list_value
->begin(),
218 IDS_POLICY_OUT_OF_RANGE_ERROR
);
226 scoped_ptr
<base::Value
> StringMappingListPolicyHandler::Map(
227 const std::string
& entry_value
) {
228 // Lazily generate the map of policy strings to mapped values.
230 map_getter_
.Run(&map_
);
232 scoped_ptr
<base::Value
> return_value
;
233 for (ScopedVector
<MappingEntry
>::const_iterator it
= map_
.begin();
234 it
!= map_
.end(); ++it
) {
235 const MappingEntry
* mapping_entry
= *it
;
236 if (mapping_entry
->enum_value
== entry_value
) {
237 return_value
= make_scoped_ptr(mapping_entry
->mapped_value
->DeepCopy());
241 return return_value
.Pass();
244 // IntRangePolicyHandler implementation ----------------------------------------
246 IntRangePolicyHandler::IntRangePolicyHandler(const char* policy_name
,
247 const char* pref_path
,
251 : IntRangePolicyHandlerBase(policy_name
, min
, max
, clamp
),
252 pref_path_(pref_path
) {
255 IntRangePolicyHandler::~IntRangePolicyHandler() {
258 void IntRangePolicyHandler::ApplyPolicySettings(const PolicyMap
& policies
,
259 PrefValueMap
* prefs
) {
262 const base::Value
* value
= policies
.GetValue(policy_name());
264 if (value
&& EnsureInRange(value
, &value_in_range
, NULL
))
265 prefs
->SetInteger(pref_path_
, value_in_range
);
269 // IntPercentageToDoublePolicyHandler implementation ---------------------------
271 IntPercentageToDoublePolicyHandler::IntPercentageToDoublePolicyHandler(
272 const char* policy_name
,
273 const char* pref_path
,
277 : IntRangePolicyHandlerBase(policy_name
, min
, max
, clamp
),
278 pref_path_(pref_path
) {
281 IntPercentageToDoublePolicyHandler::~IntPercentageToDoublePolicyHandler() {
284 void IntPercentageToDoublePolicyHandler::ApplyPolicySettings(
285 const PolicyMap
& policies
,
286 PrefValueMap
* prefs
) {
289 const base::Value
* value
= policies
.GetValue(policy_name());
291 if (value
&& EnsureInRange(value
, &percentage
, NULL
))
292 prefs
->SetDouble(pref_path_
, static_cast<double>(percentage
) / 100.);
296 // SimplePolicyHandler implementation ------------------------------------------
298 SimplePolicyHandler::SimplePolicyHandler(
299 const char* policy_name
,
300 const char* pref_path
,
301 base::Value::Type value_type
)
302 : TypeCheckingPolicyHandler(policy_name
, value_type
),
303 pref_path_(pref_path
) {
306 SimplePolicyHandler::~SimplePolicyHandler() {
309 void SimplePolicyHandler::ApplyPolicySettings(const PolicyMap
& policies
,
310 PrefValueMap
* prefs
) {
313 const base::Value
* value
= policies
.GetValue(policy_name());
315 prefs
->SetValue(pref_path_
, value
->CreateDeepCopy());
319 // SchemaValidatingPolicyHandler implementation --------------------------------
321 SchemaValidatingPolicyHandler::SchemaValidatingPolicyHandler(
322 const char* policy_name
,
324 SchemaOnErrorStrategy strategy
)
325 : policy_name_(policy_name
), schema_(schema
), strategy_(strategy
) {
326 DCHECK(schema_
.valid());
329 SchemaValidatingPolicyHandler::~SchemaValidatingPolicyHandler() {
332 const char* SchemaValidatingPolicyHandler::policy_name() const {
336 bool SchemaValidatingPolicyHandler::CheckPolicySettings(
337 const PolicyMap
& policies
,
338 PolicyErrorMap
* errors
) {
339 const base::Value
* value
= policies
.GetValue(policy_name());
343 std::string error_path
;
345 bool result
= schema_
.Validate(*value
, strategy_
, &error_path
, &error
);
347 if (errors
&& !error
.empty()) {
348 if (error_path
.empty())
349 error_path
= "(ROOT)";
350 errors
->AddError(policy_name_
, error_path
, error
);
356 bool SchemaValidatingPolicyHandler::CheckAndGetValue(
357 const PolicyMap
& policies
,
358 PolicyErrorMap
* errors
,
359 scoped_ptr
<base::Value
>* output
) {
360 const base::Value
* value
= policies
.GetValue(policy_name());
364 output
->reset(value
->DeepCopy());
365 std::string error_path
;
368 schema_
.Normalize(output
->get(), strategy_
, &error_path
, &error
, NULL
);
370 if (errors
&& !error
.empty()) {
371 if (error_path
.empty())
372 error_path
= "(ROOT)";
373 errors
->AddError(policy_name_
, error_path
, error
);
379 // SimpleSchemaValidatingPolicyHandler implementation --------------------------
381 SimpleSchemaValidatingPolicyHandler::SimpleSchemaValidatingPolicyHandler(
382 const char* policy_name
,
383 const char* pref_path
,
385 SchemaOnErrorStrategy strategy
,
386 RecommendedPermission recommended_permission
,
387 MandatoryPermission mandatory_permission
)
388 : SchemaValidatingPolicyHandler(policy_name
,
389 schema
.GetKnownProperty(policy_name
),
391 pref_path_(pref_path
),
392 allow_recommended_(recommended_permission
== RECOMMENDED_ALLOWED
),
393 allow_mandatory_(mandatory_permission
== MANDATORY_ALLOWED
) {
396 SimpleSchemaValidatingPolicyHandler::~SimpleSchemaValidatingPolicyHandler() {
399 bool SimpleSchemaValidatingPolicyHandler::CheckPolicySettings(
400 const PolicyMap
& policies
,
401 PolicyErrorMap
* errors
) {
402 const PolicyMap::Entry
* policy_entry
= policies
.Get(policy_name());
405 if ((policy_entry
->level
== policy::POLICY_LEVEL_MANDATORY
&&
406 !allow_mandatory_
) ||
407 (policy_entry
->level
== policy::POLICY_LEVEL_RECOMMENDED
&&
408 !allow_recommended_
)) {
410 errors
->AddError(policy_name(), IDS_POLICY_LEVEL_ERROR
);
414 return SchemaValidatingPolicyHandler::CheckPolicySettings(policies
, errors
);
417 void SimpleSchemaValidatingPolicyHandler::ApplyPolicySettings(
418 const PolicyMap
& policies
,
419 PrefValueMap
* prefs
) {
422 const base::Value
* value
= policies
.GetValue(policy_name());
424 prefs
->SetValue(pref_path_
, value
->CreateDeepCopy());
427 // LegacyPoliciesDeprecatingPolicyHandler implementation -----------------------
429 // TODO(binjin): Add a new common base class for SchemaValidatingPolicyHandler
430 // and TypeCheckingPolicyHandler representing policy handlers for a single
431 // policy, and use it as the type of |new_policy_handler|.
432 // http://crbug.com/345299
433 LegacyPoliciesDeprecatingPolicyHandler::LegacyPoliciesDeprecatingPolicyHandler(
434 ScopedVector
<ConfigurationPolicyHandler
> legacy_policy_handlers
,
435 scoped_ptr
<SchemaValidatingPolicyHandler
> new_policy_handler
)
436 : legacy_policy_handlers_(legacy_policy_handlers
.Pass()),
437 new_policy_handler_(new_policy_handler
.Pass()) {
440 LegacyPoliciesDeprecatingPolicyHandler::
441 ~LegacyPoliciesDeprecatingPolicyHandler() {
444 bool LegacyPoliciesDeprecatingPolicyHandler::CheckPolicySettings(
445 const PolicyMap
& policies
,
446 PolicyErrorMap
* errors
) {
447 if (policies
.Get(new_policy_handler_
->policy_name())) {
448 return new_policy_handler_
->CheckPolicySettings(policies
, errors
);
450 // The new policy is not set, fall back to legacy ones.
451 ScopedVector
<ConfigurationPolicyHandler
>::iterator handler
;
452 bool valid_policy_found
= false;
453 for (handler
= legacy_policy_handlers_
.begin();
454 handler
!= legacy_policy_handlers_
.end();
456 if ((*handler
)->CheckPolicySettings(policies
, errors
))
457 valid_policy_found
= true;
459 return valid_policy_found
;
463 void LegacyPoliciesDeprecatingPolicyHandler::ApplyPolicySettingsWithParameters(
464 const policy::PolicyMap
& policies
,
465 const policy::PolicyHandlerParameters
& parameters
,
466 PrefValueMap
* prefs
) {
467 if (policies
.Get(new_policy_handler_
->policy_name())) {
468 new_policy_handler_
->ApplyPolicySettingsWithParameters(policies
, parameters
,
471 // The new policy is not set, fall back to legacy ones.
472 PolicyErrorMap scoped_errors
;
473 ScopedVector
<ConfigurationPolicyHandler
>::iterator handler
;
474 for (handler
= legacy_policy_handlers_
.begin();
475 handler
!= legacy_policy_handlers_
.end();
477 if ((*handler
)->CheckPolicySettings(policies
, &scoped_errors
)) {
479 ->ApplyPolicySettingsWithParameters(policies
, parameters
, prefs
);
484 void LegacyPoliciesDeprecatingPolicyHandler::ApplyPolicySettings(
485 const policy::PolicyMap
& /* policies */,
486 PrefValueMap
* /* prefs */) {
490 } // namespace policy