Home | History | Annotate | Download | only in browser
      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.
      4 
      5 #include "components/policy/core/browser/configuration_policy_handler.h"
      6 
      7 #include <algorithm>
      8 
      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"
     20 
     21 namespace policy {
     22 
     23 // ConfigurationPolicyHandler implementation -----------------------------------
     24 
     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"
     37   };
     38   CHECK(static_cast<size_t>(type) < arraysize(strings));
     39   return std::string(strings[type]);
     40 }
     41 
     42 ConfigurationPolicyHandler::ConfigurationPolicyHandler() {
     43 }
     44 
     45 ConfigurationPolicyHandler::~ConfigurationPolicyHandler() {
     46 }
     47 
     48 void ConfigurationPolicyHandler::PrepareForDisplaying(
     49     PolicyMap* policies) const {}
     50 
     51 void ConfigurationPolicyHandler::ApplyPolicySettings(
     52     const policy::PolicyMap& policies,
     53     PrefValueMap* prefs) {
     54   NOTREACHED();
     55 }
     56 
     57 void ConfigurationPolicyHandler::ApplyPolicySettingsWithParameters(
     58     const PolicyMap& policies,
     59     const PolicyHandlerParameters& parameters,
     60     PrefValueMap* prefs) {
     61   ApplyPolicySettings(policies, prefs);
     62 }
     63 
     64 // TypeCheckingPolicyHandler implementation ------------------------------------
     65 
     66 TypeCheckingPolicyHandler::TypeCheckingPolicyHandler(
     67     const char* policy_name,
     68     base::Value::Type value_type)
     69     : policy_name_(policy_name),
     70       value_type_(value_type) {
     71 }
     72 
     73 TypeCheckingPolicyHandler::~TypeCheckingPolicyHandler() {
     74 }
     75 
     76 const char* TypeCheckingPolicyHandler::policy_name() const {
     77   return policy_name_;
     78 }
     79 
     80 bool TypeCheckingPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
     81                                                     PolicyErrorMap* errors) {
     82   const base::Value* value = NULL;
     83   return CheckAndGetValue(policies, errors, &value);
     84 }
     85 
     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_));
     94     return false;
     95   }
     96   return true;
     97 }
     98 
     99 
    100 // IntRangePolicyHandlerBase implementation ------------------------------------
    101 
    102 IntRangePolicyHandlerBase::IntRangePolicyHandlerBase(
    103     const char* policy_name,
    104     int min,
    105     int max,
    106     bool clamp)
    107     : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_INTEGER),
    108       min_(min),
    109       max_(max),
    110       clamp_(clamp) {
    111 }
    112 
    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);
    118 }
    119 
    120 IntRangePolicyHandlerBase::~IntRangePolicyHandlerBase() {
    121 }
    122 
    123 bool IntRangePolicyHandlerBase::EnsureInRange(const base::Value* input,
    124                                               int* output,
    125                                               PolicyErrorMap* errors) {
    126   if (!input)
    127     return true;
    128 
    129   int value;
    130   if (!input->GetAsInteger(&value)) {
    131     NOTREACHED();
    132     return false;
    133   }
    134 
    135   if (value < min_ || value > max_) {
    136     if (errors) {
    137       errors->AddError(policy_name(),
    138                        IDS_POLICY_OUT_OF_RANGE_ERROR,
    139                        base::IntToString(value));
    140     }
    141 
    142     if (!clamp_)
    143       return false;
    144 
    145     value = std::min(std::max(value, min_), max_);
    146   }
    147 
    148   if (output)
    149     *output = value;
    150   return true;
    151 }
    152 
    153 
    154 // StringMappingListPolicyHandler implementation -----------------------------
    155 
    156 StringMappingListPolicyHandler::MappingEntry::MappingEntry(
    157     const char* policy_value, scoped_ptr<base::Value> map)
    158     : enum_value(policy_value), mapped_value(map.Pass()) {}
    159 
    160 StringMappingListPolicyHandler::MappingEntry::~MappingEntry() {}
    161 
    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) {}
    169 
    170 StringMappingListPolicyHandler::~StringMappingListPolicyHandler() {}
    171 
    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);
    178 }
    179 
    180 void StringMappingListPolicyHandler::ApplyPolicySettings(
    181     const PolicyMap& policies,
    182     PrefValueMap* prefs) {
    183   if (!pref_path_)
    184     return;
    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());
    189 }
    190 
    191 bool StringMappingListPolicyHandler::Convert(const base::Value* input,
    192                                              base::ListValue* output,
    193                                              PolicyErrorMap* errors) {
    194   if (!input)
    195     return true;
    196 
    197   const base::ListValue* list_value = NULL;
    198   if (!input->GetAsList(&list_value)) {
    199     NOTREACHED();
    200     return false;
    201   }
    202 
    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)) {
    207       if (errors) {
    208         errors->AddError(policy_name(),
    209                          entry - list_value->begin(),
    210                          IDS_POLICY_TYPE_ERROR,
    211                          ValueTypeToString(base::Value::TYPE_STRING));
    212       }
    213       continue;
    214     }
    215 
    216     scoped_ptr<base::Value> mapped_value = Map(entry_value);
    217     if (mapped_value) {
    218       if (output)
    219         output->Append(mapped_value.release());
    220     } else {
    221       if (errors) {
    222         errors->AddError(policy_name(),
    223                          entry - list_value->begin(),
    224                          IDS_POLICY_OUT_OF_RANGE_ERROR);
    225       }
    226     }
    227   }
    228 
    229   return true;
    230 }
    231 
    232 scoped_ptr<base::Value> StringMappingListPolicyHandler::Map(
    233     const std::string& entry_value) {
    234   // Lazily generate the map of policy strings to mapped values.
    235   if (map_.empty())
    236     map_getter_.Run(&map_);
    237 
    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());
    244       break;
    245     }
    246   }
    247   return return_value.Pass();
    248 }
    249 
    250 // IntRangePolicyHandler implementation ----------------------------------------
    251 
    252 IntRangePolicyHandler::IntRangePolicyHandler(const char* policy_name,
    253                                              const char* pref_path,
    254                                              int min,
    255                                              int max,
    256                                              bool clamp)
    257     : IntRangePolicyHandlerBase(policy_name, min, max, clamp),
    258       pref_path_(pref_path) {
    259 }
    260 
    261 IntRangePolicyHandler::~IntRangePolicyHandler() {
    262 }
    263 
    264 void IntRangePolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
    265                                                 PrefValueMap* prefs) {
    266   if (!pref_path_)
    267     return;
    268   const base::Value* value = policies.GetValue(policy_name());
    269   int value_in_range;
    270   if (value && EnsureInRange(value, &value_in_range, NULL))
    271     prefs->SetInteger(pref_path_, value_in_range);
    272 }
    273 
    274 
    275 // IntPercentageToDoublePolicyHandler implementation ---------------------------
    276 
    277 IntPercentageToDoublePolicyHandler::IntPercentageToDoublePolicyHandler(
    278     const char* policy_name,
    279     const char* pref_path,
    280     int min,
    281     int max,
    282     bool clamp)
    283     : IntRangePolicyHandlerBase(policy_name, min, max, clamp),
    284       pref_path_(pref_path) {
    285 }
    286 
    287 IntPercentageToDoublePolicyHandler::~IntPercentageToDoublePolicyHandler() {
    288 }
    289 
    290 void IntPercentageToDoublePolicyHandler::ApplyPolicySettings(
    291     const PolicyMap& policies,
    292     PrefValueMap* prefs) {
    293   if (!pref_path_)
    294     return;
    295   const base::Value* value = policies.GetValue(policy_name());
    296   int percentage;
    297   if (value && EnsureInRange(value, &percentage, NULL))
    298     prefs->SetDouble(pref_path_, static_cast<double>(percentage) / 100.);
    299 }
    300 
    301 
    302 // SimplePolicyHandler implementation ------------------------------------------
    303 
    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) {
    310 }
    311 
    312 SimplePolicyHandler::~SimplePolicyHandler() {
    313 }
    314 
    315 void SimplePolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
    316                                               PrefValueMap* prefs) {
    317   if (!pref_path_)
    318     return;
    319   const base::Value* value = policies.GetValue(policy_name());
    320   if (value)
    321     prefs->SetValue(pref_path_, value->DeepCopy());
    322 }
    323 
    324 
    325 // SchemaValidatingPolicyHandler implementation --------------------------------
    326 
    327 SchemaValidatingPolicyHandler::SchemaValidatingPolicyHandler(
    328     const char* policy_name,
    329     Schema schema,
    330     SchemaOnErrorStrategy strategy)
    331     : policy_name_(policy_name), schema_(schema), strategy_(strategy) {
    332   DCHECK(schema_.valid());
    333 }
    334 
    335 SchemaValidatingPolicyHandler::~SchemaValidatingPolicyHandler() {
    336 }
    337 
    338 const char* SchemaValidatingPolicyHandler::policy_name() const {
    339   return policy_name_;
    340 }
    341 
    342 bool SchemaValidatingPolicyHandler::CheckPolicySettings(
    343     const PolicyMap& policies,
    344     PolicyErrorMap* errors) {
    345   const base::Value* value = policies.GetValue(policy_name());
    346   if (!value)
    347     return true;
    348 
    349   std::string error_path;
    350   std::string error;
    351   bool result = schema_.Validate(*value, strategy_, &error_path, &error);
    352 
    353   if (errors && !error.empty()) {
    354     if (error_path.empty())
    355       error_path = "(ROOT)";
    356     errors->AddError(policy_name_, error_path, error);
    357   }
    358 
    359   return result;
    360 }
    361 
    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());
    367   if (!value)
    368     return true;
    369 
    370   output->reset(value->DeepCopy());
    371   std::string error_path;
    372   std::string error;
    373   bool result =
    374       schema_.Normalize(output->get(), strategy_, &error_path, &error, NULL);
    375 
    376   if (errors && !error.empty()) {
    377     if (error_path.empty())
    378       error_path = "(ROOT)";
    379     errors->AddError(policy_name_, error_path, error);
    380   }
    381 
    382   return result;
    383 }
    384 
    385 // SimpleSchemaValidatingPolicyHandler implementation --------------------------
    386 
    387 SimpleSchemaValidatingPolicyHandler::SimpleSchemaValidatingPolicyHandler(
    388     const char* policy_name,
    389     const char* pref_path,
    390     Schema schema,
    391     SchemaOnErrorStrategy strategy,
    392     RecommendedPermission recommended_permission,
    393     MandatoryPermission mandatory_permission)
    394     : SchemaValidatingPolicyHandler(policy_name,
    395                                     schema.GetKnownProperty(policy_name),
    396                                     strategy),
    397       pref_path_(pref_path),
    398       allow_recommended_(recommended_permission == RECOMMENDED_ALLOWED),
    399       allow_mandatory_(mandatory_permission == MANDATORY_ALLOWED) {
    400 }
    401 
    402 SimpleSchemaValidatingPolicyHandler::~SimpleSchemaValidatingPolicyHandler() {
    403 }
    404 
    405 bool SimpleSchemaValidatingPolicyHandler::CheckPolicySettings(
    406     const PolicyMap& policies,
    407     PolicyErrorMap* errors) {
    408   const PolicyMap::Entry* policy_entry = policies.Get(policy_name());
    409   if (!policy_entry)
    410     return true;
    411   if ((policy_entry->level == policy::POLICY_LEVEL_MANDATORY &&
    412        !allow_mandatory_) ||
    413       (policy_entry->level == policy::POLICY_LEVEL_RECOMMENDED &&
    414        !allow_recommended_)) {
    415     if (errors)
    416       errors->AddError(policy_name(), IDS_POLICY_LEVEL_ERROR);
    417     return false;
    418   }
    419 
    420   return SchemaValidatingPolicyHandler::CheckPolicySettings(policies, errors);
    421 }
    422 
    423 void SimpleSchemaValidatingPolicyHandler::ApplyPolicySettings(
    424     const PolicyMap& policies,
    425     PrefValueMap* prefs) {
    426   if (!pref_path_)
    427     return;
    428   const base::Value* value = policies.GetValue(policy_name());
    429   if (value)
    430     prefs->SetValue(pref_path_, value->DeepCopy());
    431 }
    432 
    433 // LegacyPoliciesDeprecatingPolicyHandler implementation -----------------------
    434 
    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()) {
    444 }
    445 
    446 LegacyPoliciesDeprecatingPolicyHandler::
    447     ~LegacyPoliciesDeprecatingPolicyHandler() {
    448 }
    449 
    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);
    455   } else {
    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();
    461          ++handler) {
    462       if ((*handler)->CheckPolicySettings(policies, errors))
    463         valid_policy_found = true;
    464     }
    465     return valid_policy_found;
    466   }
    467 }
    468 
    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);
    474   } else {
    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();
    480          ++handler) {
    481       if ((*handler)->CheckPolicySettings(policies, &scoped_errors))
    482         (*handler)->ApplyPolicySettings(policies, prefs);
    483     }
    484   }
    485 }
    486 
    487 }  // namespace policy
    488