Roll src/third_party/WebKit 6b63e20:35e1984 (svn 201060:201061)
[chromium-blink-merge.git] / components / policy / core / browser / configuration_policy_handler.cc
bloba2215292cdbb32cb389c5524abb4b6296d83567d
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"
7 #include <algorithm>
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"
19 #include "url/gurl.h"
21 namespace policy {
23 // ConfigurationPolicyHandler implementation -----------------------------------
25 // static
26 std::string ConfigurationPolicyHandler::ValueTypeToString(
27 base::Value::Type type) {
28 static const char* strings[] = {
29 "null",
30 "boolean",
31 "integer",
32 "double",
33 "string",
34 "binary",
35 "dictionary",
36 "list"
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 {
71 return policy_name_;
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_));
88 return false;
90 return true;
94 // IntRangePolicyHandlerBase implementation ------------------------------------
96 IntRangePolicyHandlerBase::IntRangePolicyHandlerBase(
97 const char* policy_name,
98 int min,
99 int max,
100 bool clamp)
101 : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_INTEGER),
102 min_(min),
103 max_(max),
104 clamp_(clamp) {
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,
118 int* output,
119 PolicyErrorMap* errors) {
120 if (!input)
121 return true;
123 int value;
124 if (!input->GetAsInteger(&value)) {
125 NOTREACHED();
126 return false;
129 if (value < min_ || value > max_) {
130 if (errors) {
131 errors->AddError(policy_name(),
132 IDS_POLICY_OUT_OF_RANGE_ERROR,
133 base::IntToString(value));
136 if (!clamp_)
137 return false;
139 value = std::min(std::max(value, min_), max_);
142 if (output)
143 *output = value;
144 return true;
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) {
177 if (!pref_path_)
178 return;
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) {
188 if (!input)
189 return true;
191 const base::ListValue* list_value = NULL;
192 if (!input->GetAsList(&list_value)) {
193 NOTREACHED();
194 return false;
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)) {
201 if (errors) {
202 errors->AddError(policy_name(),
203 entry - list_value->begin(),
204 IDS_POLICY_TYPE_ERROR,
205 ValueTypeToString(base::Value::TYPE_STRING));
207 continue;
210 scoped_ptr<base::Value> mapped_value = Map(entry_value);
211 if (mapped_value) {
212 if (output)
213 output->Append(mapped_value.release());
214 } else {
215 if (errors) {
216 errors->AddError(policy_name(),
217 entry - list_value->begin(),
218 IDS_POLICY_OUT_OF_RANGE_ERROR);
223 return true;
226 scoped_ptr<base::Value> StringMappingListPolicyHandler::Map(
227 const std::string& entry_value) {
228 // Lazily generate the map of policy strings to mapped values.
229 if (map_.empty())
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());
238 break;
241 return return_value.Pass();
244 // IntRangePolicyHandler implementation ----------------------------------------
246 IntRangePolicyHandler::IntRangePolicyHandler(const char* policy_name,
247 const char* pref_path,
248 int min,
249 int max,
250 bool clamp)
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) {
260 if (!pref_path_)
261 return;
262 const base::Value* value = policies.GetValue(policy_name());
263 int value_in_range;
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,
274 int min,
275 int max,
276 bool clamp)
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) {
287 if (!pref_path_)
288 return;
289 const base::Value* value = policies.GetValue(policy_name());
290 int percentage;
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) {
311 if (!pref_path_)
312 return;
313 const base::Value* value = policies.GetValue(policy_name());
314 if (value)
315 prefs->SetValue(pref_path_, value->CreateDeepCopy());
319 // SchemaValidatingPolicyHandler implementation --------------------------------
321 SchemaValidatingPolicyHandler::SchemaValidatingPolicyHandler(
322 const char* policy_name,
323 Schema schema,
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 {
333 return policy_name_;
336 bool SchemaValidatingPolicyHandler::CheckPolicySettings(
337 const PolicyMap& policies,
338 PolicyErrorMap* errors) {
339 const base::Value* value = policies.GetValue(policy_name());
340 if (!value)
341 return true;
343 std::string error_path;
344 std::string error;
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);
353 return result;
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());
361 if (!value)
362 return true;
364 output->reset(value->DeepCopy());
365 std::string error_path;
366 std::string error;
367 bool result =
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);
376 return result;
379 // SimpleSchemaValidatingPolicyHandler implementation --------------------------
381 SimpleSchemaValidatingPolicyHandler::SimpleSchemaValidatingPolicyHandler(
382 const char* policy_name,
383 const char* pref_path,
384 Schema schema,
385 SchemaOnErrorStrategy strategy,
386 RecommendedPermission recommended_permission,
387 MandatoryPermission mandatory_permission)
388 : SchemaValidatingPolicyHandler(policy_name,
389 schema.GetKnownProperty(policy_name),
390 strategy),
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());
403 if (!policy_entry)
404 return true;
405 if ((policy_entry->level == policy::POLICY_LEVEL_MANDATORY &&
406 !allow_mandatory_) ||
407 (policy_entry->level == policy::POLICY_LEVEL_RECOMMENDED &&
408 !allow_recommended_)) {
409 if (errors)
410 errors->AddError(policy_name(), IDS_POLICY_LEVEL_ERROR);
411 return false;
414 return SchemaValidatingPolicyHandler::CheckPolicySettings(policies, errors);
417 void SimpleSchemaValidatingPolicyHandler::ApplyPolicySettings(
418 const PolicyMap& policies,
419 PrefValueMap* prefs) {
420 if (!pref_path_)
421 return;
422 const base::Value* value = policies.GetValue(policy_name());
423 if (value)
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);
449 } else {
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();
455 ++handler) {
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,
469 prefs);
470 } else {
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();
476 ++handler) {
477 if ((*handler)->CheckPolicySettings(policies, &scoped_errors)) {
478 (*handler)
479 ->ApplyPolicySettingsWithParameters(policies, parameters, prefs);
484 void LegacyPoliciesDeprecatingPolicyHandler::ApplyPolicySettings(
485 const policy::PolicyMap& /* policies */,
486 PrefValueMap* /* prefs */) {
487 NOTREACHED();
490 } // namespace policy