Home | History | Annotate | Download | only in policy
      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 "chrome/browser/policy/configuration_policy_handler.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/callback.h"
     10 #include "base/files/file_path.h"
     11 #include "base/json/json_writer.h"
     12 #include "base/logging.h"
     13 #include "base/prefs/pref_value_map.h"
     14 #include "base/stl_util.h"
     15 #include "base/strings/string16.h"
     16 #include "base/strings/string_number_conversions.h"
     17 #include "base/strings/string_util.h"
     18 #include "chrome/browser/chrome_notification_types.h"
     19 #include "chrome/browser/download/download_util.h"
     20 #include "chrome/browser/extensions/external_policy_loader.h"
     21 #include "chrome/browser/policy/configuration_policy_pref_store.h"
     22 #include "chrome/browser/policy/external_data_fetcher.h"
     23 #include "chrome/browser/policy/policy_error_map.h"
     24 #include "chrome/browser/policy/policy_map.h"
     25 #include "chrome/browser/prefs/proxy_config_dictionary.h"
     26 #include "chrome/browser/prefs/proxy_prefs.h"
     27 #include "chrome/browser/prefs/session_startup_pref.h"
     28 #include "chrome/browser/search_engines/search_terms_data.h"
     29 #include "chrome/browser/search_engines/template_url.h"
     30 #include "chrome/common/extensions/extension.h"
     31 #include "chrome/common/pref_names.h"
     32 #include "content/public/browser/notification_service.h"
     33 #include "grit/generated_resources.h"
     34 #include "policy/policy_constants.h"
     35 #include "url/gurl.h"
     36 
     37 #if !defined(OS_ANDROID)
     38 #include "chrome/browser/policy/policy_path_parser.h"
     39 #endif
     40 
     41 namespace policy {
     42 
     43 namespace {
     44 
     45 // Helper classes --------------------------------------------------------------
     46 
     47 // This is used to check whether for a given ProxyMode value, the ProxyPacUrl,
     48 // the ProxyBypassList and the ProxyServer policies are allowed to be specified.
     49 // |error_message_id| is the message id of the localized error message to show
     50 // when the policies are not specified as allowed. Each value of ProxyMode
     51 // has a ProxyModeValidationEntry in the |kProxyModeValidationMap| below.
     52 struct ProxyModeValidationEntry {
     53   const char* mode_value;
     54   bool pac_url_allowed;
     55   bool bypass_list_allowed;
     56   bool server_allowed;
     57   int error_message_id;
     58 };
     59 
     60 // Maps a policy type to a preference path, and to the expected value type.
     61 struct DefaultSearchSimplePolicyHandlerEntry {
     62   const char* policy_name;
     63   const char* preference_path;
     64   base::Value::Type value_type;
     65 };
     66 
     67 
     68 // Static data -----------------------------------------------------------------
     69 
     70 // List of policy types to preference names, for policies affecting the default
     71 // search provider.
     72 const DefaultSearchSimplePolicyHandlerEntry kDefaultSearchPolicyMap[] = {
     73   { key::kDefaultSearchProviderEnabled,
     74     prefs::kDefaultSearchProviderEnabled,
     75     Value::TYPE_BOOLEAN },
     76   { key::kDefaultSearchProviderName,
     77     prefs::kDefaultSearchProviderName,
     78     Value::TYPE_STRING },
     79   { key::kDefaultSearchProviderKeyword,
     80     prefs::kDefaultSearchProviderKeyword,
     81     Value::TYPE_STRING },
     82   { key::kDefaultSearchProviderSearchURL,
     83     prefs::kDefaultSearchProviderSearchURL,
     84     Value::TYPE_STRING },
     85   { key::kDefaultSearchProviderSuggestURL,
     86     prefs::kDefaultSearchProviderSuggestURL,
     87     Value::TYPE_STRING },
     88   { key::kDefaultSearchProviderInstantURL,
     89     prefs::kDefaultSearchProviderInstantURL,
     90     Value::TYPE_STRING },
     91   { key::kDefaultSearchProviderIconURL,
     92     prefs::kDefaultSearchProviderIconURL,
     93     Value::TYPE_STRING },
     94   { key::kDefaultSearchProviderEncodings,
     95     prefs::kDefaultSearchProviderEncodings,
     96     Value::TYPE_LIST },
     97   { key::kDefaultSearchProviderAlternateURLs,
     98     prefs::kDefaultSearchProviderAlternateURLs,
     99     Value::TYPE_LIST },
    100   { key::kDefaultSearchProviderSearchTermsReplacementKey,
    101     prefs::kDefaultSearchProviderSearchTermsReplacementKey,
    102     Value::TYPE_STRING },
    103   { key::kDefaultSearchProviderImageURL,
    104     prefs::kDefaultSearchProviderImageURL,
    105     Value::TYPE_STRING },
    106   { key::kDefaultSearchProviderSearchURLPostParams,
    107     prefs::kDefaultSearchProviderSearchURLPostParams,
    108     Value::TYPE_STRING },
    109   { key::kDefaultSearchProviderSuggestURLPostParams,
    110     prefs::kDefaultSearchProviderSuggestURLPostParams,
    111     Value::TYPE_STRING },
    112   { key::kDefaultSearchProviderInstantURLPostParams,
    113     prefs::kDefaultSearchProviderInstantURLPostParams,
    114     Value::TYPE_STRING },
    115   { key::kDefaultSearchProviderImageURLPostParams,
    116     prefs::kDefaultSearchProviderImageURLPostParams,
    117     Value::TYPE_STRING },
    118 };
    119 
    120 // List of entries determining which proxy policies can be specified, depending
    121 // on the ProxyMode.
    122 const ProxyModeValidationEntry kProxyModeValidationMap[] = {
    123   { ProxyPrefs::kDirectProxyModeName,
    124     false, false, false, IDS_POLICY_PROXY_MODE_DISABLED_ERROR },
    125   { ProxyPrefs::kAutoDetectProxyModeName,
    126     false, false, false, IDS_POLICY_PROXY_MODE_AUTO_DETECT_ERROR },
    127   { ProxyPrefs::kPacScriptProxyModeName,
    128     true, false, false, IDS_POLICY_PROXY_MODE_PAC_URL_ERROR },
    129   { ProxyPrefs::kFixedServersProxyModeName,
    130     false, true, true, IDS_POLICY_PROXY_MODE_FIXED_SERVERS_ERROR },
    131   { ProxyPrefs::kSystemProxyModeName,
    132     false, false, false, IDS_POLICY_PROXY_MODE_SYSTEM_ERROR },
    133 };
    134 
    135 
    136 // Helper function -------------------------------------------------------------
    137 
    138 // Utility function that returns a JSON representation of the given |dict| as
    139 // a StringValue. The caller owns the returned object.
    140 base::StringValue* DictionaryToJSONString(const base::DictionaryValue* dict) {
    141   std::string json_string;
    142   base::JSONWriter::WriteWithOptions(
    143       dict,
    144       base::JSONWriter::OPTIONS_DO_NOT_ESCAPE |
    145           base::JSONWriter::OPTIONS_PRETTY_PRINT,
    146       &json_string);
    147   return Value::CreateStringValue(json_string);
    148 }
    149 
    150 
    151 }  // namespace
    152 
    153 
    154 // ConfigurationPolicyHandler implementation -----------------------------------
    155 
    156 // static
    157 std::string ConfigurationPolicyHandler::ValueTypeToString(Value::Type type) {
    158   static const char* strings[] = {
    159     "null",
    160     "boolean",
    161     "integer",
    162     "double",
    163     "string",
    164     "binary",
    165     "dictionary",
    166     "list"
    167   };
    168   CHECK(static_cast<size_t>(type) < arraysize(strings));
    169   return std::string(strings[type]);
    170 }
    171 
    172 ConfigurationPolicyHandler::ConfigurationPolicyHandler() {
    173 }
    174 
    175 ConfigurationPolicyHandler::~ConfigurationPolicyHandler() {
    176 }
    177 
    178 void ConfigurationPolicyHandler::PrepareForDisplaying(
    179     PolicyMap* policies) const {
    180   // jstemplate can't render DictionaryValues/objects. Convert those values to
    181   // a string representation.
    182   base::DictionaryValue* dict;
    183   base::ListValue* list;
    184   for (PolicyMap::const_iterator it = policies->begin();
    185        it != policies->end(); ++it) {
    186     const PolicyMap::Entry& entry = it->second;
    187     if (entry.value->GetAsDictionary(&dict)) {
    188       base::StringValue* value = DictionaryToJSONString(dict);
    189       policies->Set(it->first, entry.level, entry.scope,
    190                     value, entry.external_data_fetcher ?
    191                         new ExternalDataFetcher(*entry.external_data_fetcher) :
    192                         NULL);
    193     } else if (entry.value->GetAsList(&list)) {
    194       for (size_t i = 0; i < list->GetSize(); ++i) {
    195         if (list->GetDictionary(i, &dict)) {
    196           list->Set(i, DictionaryToJSONString(dict));
    197         }
    198       }
    199     }
    200   }
    201 }
    202 
    203 
    204 // TypeCheckingPolicyHandler implementation ------------------------------------
    205 
    206 TypeCheckingPolicyHandler::TypeCheckingPolicyHandler(
    207     const char* policy_name,
    208     Value::Type value_type)
    209     : policy_name_(policy_name),
    210       value_type_(value_type) {
    211 }
    212 
    213 TypeCheckingPolicyHandler::~TypeCheckingPolicyHandler() {
    214 }
    215 
    216 const char* TypeCheckingPolicyHandler::policy_name() const {
    217   return policy_name_;
    218 }
    219 
    220 bool TypeCheckingPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
    221                                                     PolicyErrorMap* errors) {
    222   const Value* value = NULL;
    223   return CheckAndGetValue(policies, errors, &value);
    224 }
    225 
    226 bool TypeCheckingPolicyHandler::CheckAndGetValue(const PolicyMap& policies,
    227                                                  PolicyErrorMap* errors,
    228                                                  const Value** value) {
    229   *value = policies.GetValue(policy_name_);
    230   if (*value && !(*value)->IsType(value_type_)) {
    231     errors->AddError(policy_name_,
    232                      IDS_POLICY_TYPE_ERROR,
    233                      ValueTypeToString(value_type_));
    234     return false;
    235   }
    236   return true;
    237 }
    238 
    239 // IntRangePolicyHandlerBase implementation ------------------------------------
    240 
    241 IntRangePolicyHandlerBase::IntRangePolicyHandlerBase(
    242     const char* policy_name,
    243     int min,
    244     int max,
    245     bool clamp)
    246     : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_INTEGER),
    247       min_(min),
    248       max_(max),
    249       clamp_(clamp) {
    250 }
    251 
    252 bool IntRangePolicyHandlerBase::CheckPolicySettings(const PolicyMap& policies,
    253                                                     PolicyErrorMap* errors) {
    254   const base::Value* value;
    255   return CheckAndGetValue(policies, errors, &value) &&
    256       EnsureInRange(value, NULL, errors);
    257 }
    258 
    259 IntRangePolicyHandlerBase::~IntRangePolicyHandlerBase() {
    260 }
    261 
    262 bool IntRangePolicyHandlerBase::EnsureInRange(const base::Value* input,
    263                                               int* output,
    264                                               PolicyErrorMap* errors) {
    265   if (!input)
    266     return true;
    267 
    268   int value;
    269   if (!input->GetAsInteger(&value)) {
    270     NOTREACHED();
    271     return false;
    272   }
    273 
    274   if (value < min_ || value > max_) {
    275     if (errors) {
    276       errors->AddError(policy_name(),
    277                        IDS_POLICY_OUT_OF_RANGE_ERROR,
    278                        base::IntToString(value));
    279     }
    280 
    281     if (!clamp_)
    282       return false;
    283 
    284     value = std::min(std::max(value, min_), max_);
    285   }
    286 
    287   if (output)
    288     *output = value;
    289   return true;
    290 }
    291 
    292 // StringToIntEnumListPolicyHandler implementation -----------------------------
    293 
    294 StringToIntEnumListPolicyHandler::StringToIntEnumListPolicyHandler(
    295     const char* policy_name,
    296     const char* pref_path,
    297     const MappingEntry* mapping_begin,
    298     const MappingEntry* mapping_end)
    299     : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST),
    300       pref_path_(pref_path),
    301       mapping_begin_(mapping_begin),
    302       mapping_end_(mapping_end) {}
    303 
    304 bool StringToIntEnumListPolicyHandler::CheckPolicySettings(
    305     const PolicyMap& policies,
    306     PolicyErrorMap* errors) {
    307   const base::Value* value;
    308   return CheckAndGetValue(policies, errors, &value) &&
    309       Convert(value, NULL, errors);
    310 }
    311 
    312 void StringToIntEnumListPolicyHandler::ApplyPolicySettings(
    313     const PolicyMap& policies,
    314     PrefValueMap* prefs) {
    315   if (!pref_path_)
    316     return;
    317   const base::Value* value = policies.GetValue(policy_name());
    318   scoped_ptr<base::ListValue> list(new base::ListValue());
    319   if (value && Convert(value, list.get(), NULL))
    320     prefs->SetValue(pref_path_, list.release());
    321 }
    322 
    323 bool StringToIntEnumListPolicyHandler::Convert(const base::Value* input,
    324                                                base::ListValue* output,
    325                                                PolicyErrorMap* errors) {
    326   if (!input)
    327     return true;
    328 
    329   const base::ListValue* list_value = NULL;
    330   if (!input->GetAsList(&list_value)) {
    331     NOTREACHED();
    332     return false;
    333   }
    334 
    335   for (base::ListValue::const_iterator entry(list_value->begin());
    336        entry != list_value->end(); ++entry) {
    337     std::string entry_value;
    338     if (!(*entry)->GetAsString(&entry_value)) {
    339       if (errors) {
    340         errors->AddError(policy_name(),
    341                          entry - list_value->begin(),
    342                          IDS_POLICY_TYPE_ERROR,
    343                          ValueTypeToString(base::Value::TYPE_STRING));
    344       }
    345       continue;
    346     }
    347     bool found = false;
    348     for (const MappingEntry* mapping_entry(mapping_begin_);
    349          mapping_entry != mapping_end_; ++mapping_entry) {
    350       if (mapping_entry->enum_value == entry_value) {
    351         found = true;
    352         if (output)
    353           output->AppendInteger(mapping_entry->int_value);
    354         break;
    355       }
    356     }
    357     if (!found) {
    358       if (errors) {
    359         errors->AddError(policy_name(),
    360                          entry - list_value->begin(),
    361                          IDS_POLICY_OUT_OF_RANGE_ERROR);
    362       }
    363     }
    364   }
    365 
    366   return true;
    367 }
    368 
    369 // IntRangePolicyHandler implementation ----------------------------------------
    370 
    371 IntRangePolicyHandler::IntRangePolicyHandler(const char* policy_name,
    372                                              const char* pref_path,
    373                                              int min,
    374                                              int max,
    375                                              bool clamp)
    376     : IntRangePolicyHandlerBase(policy_name, min, max, clamp),
    377       pref_path_(pref_path) {
    378 }
    379 
    380 IntRangePolicyHandler::~IntRangePolicyHandler() {
    381 }
    382 
    383 void IntRangePolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
    384                                                 PrefValueMap* prefs) {
    385   if (!pref_path_)
    386     return;
    387   const base::Value* value = policies.GetValue(policy_name());
    388   int value_in_range;
    389   if (value && EnsureInRange(value, &value_in_range, NULL)) {
    390     prefs->SetValue(pref_path_,
    391                     base::Value::CreateIntegerValue(value_in_range));
    392   }
    393 }
    394 
    395 // IntPercentageToDoublePolicyHandler implementation ---------------------------
    396 
    397 IntPercentageToDoublePolicyHandler::IntPercentageToDoublePolicyHandler(
    398     const char* policy_name,
    399     const char* pref_path,
    400     int min,
    401     int max,
    402     bool clamp)
    403     : IntRangePolicyHandlerBase(policy_name, min, max, clamp),
    404       pref_path_(pref_path) {
    405 }
    406 
    407 IntPercentageToDoublePolicyHandler::~IntPercentageToDoublePolicyHandler() {
    408 }
    409 
    410 void IntPercentageToDoublePolicyHandler::ApplyPolicySettings(
    411     const PolicyMap& policies,
    412     PrefValueMap* prefs) {
    413   if (!pref_path_)
    414     return;
    415   const base::Value* value = policies.GetValue(policy_name());
    416   int percentage;
    417   if (value && EnsureInRange(value, &percentage, NULL)) {
    418     prefs->SetValue(pref_path_, base::Value::CreateDoubleValue(
    419         static_cast<double>(percentage) / 100.));
    420   }
    421 }
    422 
    423 // ExtensionListPolicyHandler implementation -----------------------------------
    424 
    425 ExtensionListPolicyHandler::ExtensionListPolicyHandler(const char* policy_name,
    426                                                        const char* pref_path,
    427                                                        bool allow_wildcards)
    428     : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST),
    429       pref_path_(pref_path),
    430       allow_wildcards_(allow_wildcards) {}
    431 
    432 ExtensionListPolicyHandler::~ExtensionListPolicyHandler() {}
    433 
    434 bool ExtensionListPolicyHandler::CheckPolicySettings(
    435     const PolicyMap& policies,
    436     PolicyErrorMap* errors) {
    437   return CheckAndGetList(policies, errors, NULL);
    438 }
    439 
    440 void ExtensionListPolicyHandler::ApplyPolicySettings(
    441     const PolicyMap& policies,
    442     PrefValueMap* prefs) {
    443   scoped_ptr<base::ListValue> list;
    444   PolicyErrorMap errors;
    445   if (CheckAndGetList(policies, &errors, &list) && list)
    446     prefs->SetValue(pref_path(), list.release());
    447 }
    448 
    449 const char* ExtensionListPolicyHandler::pref_path() const {
    450   return pref_path_;
    451 }
    452 
    453 bool ExtensionListPolicyHandler::CheckAndGetList(
    454     const PolicyMap& policies,
    455     PolicyErrorMap* errors,
    456     scoped_ptr<base::ListValue>* extension_ids) {
    457   if (extension_ids)
    458     extension_ids->reset();
    459 
    460   const base::Value* value = NULL;
    461   if (!CheckAndGetValue(policies, errors, &value))
    462     return false;
    463 
    464   if (!value)
    465     return true;
    466 
    467   const base::ListValue* list_value = NULL;
    468   if (!value->GetAsList(&list_value)) {
    469     NOTREACHED();
    470     return false;
    471   }
    472 
    473   // Filter the list, rejecting any invalid extension IDs.
    474   scoped_ptr<base::ListValue> filtered_list(new base::ListValue());
    475   for (base::ListValue::const_iterator entry(list_value->begin());
    476        entry != list_value->end(); ++entry) {
    477     std::string id;
    478     if (!(*entry)->GetAsString(&id)) {
    479       errors->AddError(policy_name(),
    480                        entry - list_value->begin(),
    481                        IDS_POLICY_TYPE_ERROR,
    482                        ValueTypeToString(base::Value::TYPE_STRING));
    483       continue;
    484     }
    485     if (!(allow_wildcards_ && id == "*") &&
    486         !extensions::Extension::IdIsValid(id)) {
    487       errors->AddError(policy_name(),
    488                        entry - list_value->begin(),
    489                        IDS_POLICY_VALUE_FORMAT_ERROR);
    490       continue;
    491     }
    492     filtered_list->Append(base::Value::CreateStringValue(id));
    493   }
    494 
    495   if (extension_ids)
    496     *extension_ids = filtered_list.Pass();
    497 
    498   return true;
    499 }
    500 
    501 // ExtensionInstallForcelistPolicyHandler implementation -----------------------
    502 
    503 ExtensionInstallForcelistPolicyHandler::
    504     ExtensionInstallForcelistPolicyHandler()
    505         : TypeCheckingPolicyHandler(key::kExtensionInstallForcelist,
    506                                     base::Value::TYPE_LIST) {}
    507 
    508 ExtensionInstallForcelistPolicyHandler::
    509     ~ExtensionInstallForcelistPolicyHandler() {}
    510 
    511 bool ExtensionInstallForcelistPolicyHandler::CheckPolicySettings(
    512     const PolicyMap& policies,
    513     PolicyErrorMap* errors) {
    514   const base::Value* value;
    515   return CheckAndGetValue(policies, errors, &value) &&
    516       ParseList(value, NULL, errors);
    517 }
    518 
    519 void ExtensionInstallForcelistPolicyHandler::ApplyPolicySettings(
    520     const PolicyMap& policies,
    521     PrefValueMap* prefs) {
    522   const base::Value* value = NULL;
    523   scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
    524   if (CheckAndGetValue(policies, NULL, &value) &&
    525       value &&
    526       ParseList(value, dict.get(), NULL)) {
    527     prefs->SetValue(prefs::kExtensionInstallForceList, dict.release());
    528   }
    529 }
    530 
    531 bool ExtensionInstallForcelistPolicyHandler::ParseList(
    532     const base::Value* policy_value,
    533     base::DictionaryValue* extension_dict,
    534     PolicyErrorMap* errors) {
    535   if (!policy_value)
    536     return true;
    537 
    538   const base::ListValue* policy_list_value = NULL;
    539   if (!policy_value->GetAsList(&policy_list_value)) {
    540     // This should have been caught in CheckPolicySettings.
    541     NOTREACHED();
    542     return false;
    543   }
    544 
    545   for (base::ListValue::const_iterator entry(policy_list_value->begin());
    546        entry != policy_list_value->end(); ++entry) {
    547     std::string entry_string;
    548     if (!(*entry)->GetAsString(&entry_string)) {
    549       if (errors) {
    550         errors->AddError(policy_name(),
    551                          entry - policy_list_value->begin(),
    552                          IDS_POLICY_TYPE_ERROR,
    553                          ValueTypeToString(base::Value::TYPE_STRING));
    554       }
    555       continue;
    556     }
    557 
    558     // Each string item of the list has the following form:
    559     // <extension_id>;<update_url>
    560     // Note: The update URL might also contain semicolons.
    561     size_t pos = entry_string.find(';');
    562     if (pos == std::string::npos) {
    563       if (errors) {
    564         errors->AddError(policy_name(),
    565                          entry - policy_list_value->begin(),
    566                          IDS_POLICY_VALUE_FORMAT_ERROR);
    567       }
    568       continue;
    569     }
    570 
    571     std::string extension_id = entry_string.substr(0, pos);
    572     std::string update_url = entry_string.substr(pos+1);
    573     if (!extensions::Extension::IdIsValid(extension_id) ||
    574         !GURL(update_url).is_valid()) {
    575       if (errors) {
    576         errors->AddError(policy_name(),
    577                          entry - policy_list_value->begin(),
    578                          IDS_POLICY_VALUE_FORMAT_ERROR);
    579       }
    580       continue;
    581     }
    582 
    583     if (extension_dict) {
    584       extensions::ExternalPolicyLoader::AddExtension(
    585           extension_dict, extension_id, update_url);
    586     }
    587   }
    588 
    589   return true;
    590 }
    591 
    592 // ExtensionURLPatternListPolicyHandler implementation -------------------------
    593 
    594 ExtensionURLPatternListPolicyHandler::ExtensionURLPatternListPolicyHandler(
    595     const char* policy_name,
    596     const char* pref_path)
    597     : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST),
    598       pref_path_(pref_path) {}
    599 
    600 ExtensionURLPatternListPolicyHandler::~ExtensionURLPatternListPolicyHandler() {}
    601 
    602 bool ExtensionURLPatternListPolicyHandler::CheckPolicySettings(
    603     const PolicyMap& policies,
    604     PolicyErrorMap* errors) {
    605   const base::Value* value = NULL;
    606   if (!CheckAndGetValue(policies, errors, &value))
    607     return false;
    608 
    609   if (!value)
    610     return true;
    611 
    612   const base::ListValue* list_value = NULL;
    613   if (!value->GetAsList(&list_value)) {
    614     NOTREACHED();
    615     return false;
    616   }
    617 
    618   // Check that the list contains valid URLPattern strings only.
    619   for (base::ListValue::const_iterator entry(list_value->begin());
    620        entry != list_value->end(); ++entry) {
    621     std::string url_pattern_string;
    622     if (!(*entry)->GetAsString(&url_pattern_string)) {
    623       errors->AddError(policy_name(),
    624                        entry - list_value->begin(),
    625                        IDS_POLICY_TYPE_ERROR,
    626                        ValueTypeToString(base::Value::TYPE_STRING));
    627       return false;
    628     }
    629 
    630     URLPattern pattern(URLPattern::SCHEME_ALL);
    631     if (pattern.Parse(url_pattern_string) != URLPattern::PARSE_SUCCESS) {
    632       errors->AddError(policy_name(),
    633                        entry - list_value->begin(),
    634                        IDS_POLICY_VALUE_FORMAT_ERROR);
    635       return false;
    636     }
    637   }
    638 
    639   return true;
    640 }
    641 
    642 void ExtensionURLPatternListPolicyHandler::ApplyPolicySettings(
    643     const PolicyMap& policies,
    644     PrefValueMap* prefs) {
    645   if (!pref_path_)
    646     return;
    647   const Value* value = policies.GetValue(policy_name());
    648   if (value)
    649     prefs->SetValue(pref_path_, value->DeepCopy());
    650 }
    651 
    652 // SimplePolicyHandler implementation ------------------------------------------
    653 
    654 SimplePolicyHandler::SimplePolicyHandler(
    655     const char* policy_name,
    656     const char* pref_path,
    657     Value::Type value_type)
    658     : TypeCheckingPolicyHandler(policy_name, value_type),
    659       pref_path_(pref_path) {
    660 }
    661 
    662 SimplePolicyHandler::~SimplePolicyHandler() {
    663 }
    664 
    665 void SimplePolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
    666                                               PrefValueMap* prefs) {
    667   if (!pref_path_)
    668     return;
    669   const Value* value = policies.GetValue(policy_name());
    670   if (value)
    671     prefs->SetValue(pref_path_, value->DeepCopy());
    672 }
    673 
    674 
    675 // SyncPolicyHandler implementation --------------------------------------------
    676 
    677 SyncPolicyHandler::SyncPolicyHandler()
    678     : TypeCheckingPolicyHandler(key::kSyncDisabled,
    679                                 Value::TYPE_BOOLEAN) {
    680 }
    681 
    682 SyncPolicyHandler::~SyncPolicyHandler() {
    683 }
    684 
    685 void SyncPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
    686                                             PrefValueMap* prefs) {
    687   const Value* value = policies.GetValue(policy_name());
    688   bool disable_sync;
    689   if (value && value->GetAsBoolean(&disable_sync) && disable_sync)
    690     prefs->SetValue(prefs::kSyncManaged, value->DeepCopy());
    691 }
    692 
    693 
    694 // AutofillPolicyHandler implementation ----------------------------------------
    695 
    696 AutofillPolicyHandler::AutofillPolicyHandler()
    697     : TypeCheckingPolicyHandler(key::kAutoFillEnabled,
    698                                 Value::TYPE_BOOLEAN) {
    699 }
    700 
    701 AutofillPolicyHandler::~AutofillPolicyHandler() {
    702 }
    703 
    704 void AutofillPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
    705                                                 PrefValueMap* prefs) {
    706   const Value* value = policies.GetValue(policy_name());
    707   bool auto_fill_enabled;
    708   if (value && value->GetAsBoolean(&auto_fill_enabled) && !auto_fill_enabled) {
    709     prefs->SetValue(autofill::prefs::kAutofillEnabled,
    710                     Value::CreateBooleanValue(false));
    711   }
    712 }
    713 
    714 // Android doesn't support these policies, and doesn't have a policy_path_parser
    715 // implementation.
    716 #if !defined(OS_ANDROID)
    717 
    718 // DownloadDirPolicyHandler implementation -------------------------------------
    719 
    720 DownloadDirPolicyHandler::DownloadDirPolicyHandler()
    721     : TypeCheckingPolicyHandler(key::kDownloadDirectory,
    722                                 Value::TYPE_STRING) {
    723 }
    724 
    725 DownloadDirPolicyHandler::~DownloadDirPolicyHandler() {
    726 }
    727 
    728 void DownloadDirPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
    729                                                    PrefValueMap* prefs) {
    730   const Value* value = policies.GetValue(policy_name());
    731   base::FilePath::StringType string_value;
    732   if (!value || !value->GetAsString(&string_value))
    733     return;
    734 
    735   base::FilePath::StringType expanded_value =
    736       policy::path_parser::ExpandPathVariables(string_value);
    737   // Make sure the path isn't empty, since that will point to an undefined
    738   // location; the default location is used instead in that case.
    739   // This is checked after path expansion because a non-empty policy value can
    740   // lead to an empty path value after expansion (e.g. "\"\"").
    741   if (expanded_value.empty())
    742     expanded_value = download_util::GetDefaultDownloadDirectory().value();
    743   prefs->SetValue(prefs::kDownloadDefaultDirectory,
    744                   Value::CreateStringValue(expanded_value));
    745   prefs->SetValue(prefs::kPromptForDownload,
    746                   Value::CreateBooleanValue(false));
    747 }
    748 
    749 
    750 // DiskCacheDirPolicyHandler implementation ------------------------------------
    751 
    752 DiskCacheDirPolicyHandler::DiskCacheDirPolicyHandler()
    753     : TypeCheckingPolicyHandler(key::kDiskCacheDir,
    754                                 Value::TYPE_STRING) {
    755 }
    756 
    757 DiskCacheDirPolicyHandler::~DiskCacheDirPolicyHandler() {
    758 }
    759 
    760 void DiskCacheDirPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
    761                                                     PrefValueMap* prefs) {
    762   const Value* value = policies.GetValue(policy_name());
    763   base::FilePath::StringType string_value;
    764   if (value && value->GetAsString(&string_value)) {
    765     base::FilePath::StringType expanded_value =
    766         policy::path_parser::ExpandPathVariables(string_value);
    767     prefs->SetValue(prefs::kDiskCacheDir,
    768                     Value::CreateStringValue(expanded_value));
    769   }
    770 }
    771 
    772 #endif  // !defined(OS_ANDROID)
    773 
    774 // FileSelectionDialogsHandler implementation ----------------------------------
    775 
    776 FileSelectionDialogsHandler::FileSelectionDialogsHandler()
    777     : TypeCheckingPolicyHandler(key::kAllowFileSelectionDialogs,
    778                                 Value::TYPE_BOOLEAN) {
    779 }
    780 
    781 FileSelectionDialogsHandler::~FileSelectionDialogsHandler() {
    782 }
    783 
    784 void FileSelectionDialogsHandler::ApplyPolicySettings(const PolicyMap& policies,
    785                                                       PrefValueMap* prefs) {
    786   bool allow_dialogs;
    787   const Value* value = policies.GetValue(policy_name());
    788   if (value && value->GetAsBoolean(&allow_dialogs)) {
    789     prefs->SetValue(prefs::kAllowFileSelectionDialogs,
    790                     Value::CreateBooleanValue(allow_dialogs));
    791     // Disallow selecting the download location if file dialogs are disabled.
    792     if (!allow_dialogs) {
    793       prefs->SetValue(prefs::kPromptForDownload,
    794                       Value::CreateBooleanValue(false));
    795     }
    796   }
    797 }
    798 
    799 
    800 // IncognitoModePolicyHandler implementation -----------------------------------
    801 
    802 IncognitoModePolicyHandler::IncognitoModePolicyHandler() {
    803 }
    804 
    805 IncognitoModePolicyHandler::~IncognitoModePolicyHandler() {
    806 }
    807 
    808 bool IncognitoModePolicyHandler::CheckPolicySettings(const PolicyMap& policies,
    809                                                      PolicyErrorMap* errors) {
    810   int int_value = IncognitoModePrefs::ENABLED;
    811   const Value* availability =
    812       policies.GetValue(key::kIncognitoModeAvailability);
    813 
    814   if (availability) {
    815     if (availability->GetAsInteger(&int_value)) {
    816       IncognitoModePrefs::Availability availability_enum_value;
    817       if (!IncognitoModePrefs::IntToAvailability(int_value,
    818                                                  &availability_enum_value)) {
    819         errors->AddError(key::kIncognitoModeAvailability,
    820                          IDS_POLICY_OUT_OF_RANGE_ERROR,
    821                          base::IntToString(int_value));
    822         return false;
    823       }
    824     } else {
    825       errors->AddError(key::kIncognitoModeAvailability,
    826                        IDS_POLICY_TYPE_ERROR,
    827                        ValueTypeToString(Value::TYPE_INTEGER));
    828       return false;
    829     }
    830   } else {
    831     const Value* deprecated_enabled = policies.GetValue(key::kIncognitoEnabled);
    832     if (deprecated_enabled &&
    833         !deprecated_enabled->IsType(Value::TYPE_BOOLEAN)) {
    834       errors->AddError(key::kIncognitoEnabled,
    835                        IDS_POLICY_TYPE_ERROR,
    836                        ValueTypeToString(Value::TYPE_BOOLEAN));
    837       return false;
    838     }
    839   }
    840   return true;
    841 }
    842 
    843 void IncognitoModePolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
    844                                                      PrefValueMap* prefs) {
    845   const Value* availability =
    846       policies.GetValue(key::kIncognitoModeAvailability);
    847   const Value* deprecated_enabled = policies.GetValue(key::kIncognitoEnabled);
    848   if (availability) {
    849     int int_value = IncognitoModePrefs::ENABLED;
    850     IncognitoModePrefs::Availability availability_enum_value;
    851     if (availability->GetAsInteger(&int_value) &&
    852         IncognitoModePrefs::IntToAvailability(int_value,
    853                                               &availability_enum_value)) {
    854       prefs->SetValue(prefs::kIncognitoModeAvailability,
    855                       Value::CreateIntegerValue(availability_enum_value));
    856     } else {
    857       NOTREACHED();
    858     }
    859   } else if (deprecated_enabled) {
    860     // If kIncognitoModeAvailability is not specified, check the obsolete
    861     // kIncognitoEnabled.
    862     bool enabled = true;
    863     if (deprecated_enabled->GetAsBoolean(&enabled)) {
    864       prefs->SetInteger(prefs::kIncognitoModeAvailability,
    865                         enabled ? IncognitoModePrefs::ENABLED :
    866                                   IncognitoModePrefs::DISABLED);
    867     } else {
    868       NOTREACHED();
    869     }
    870   }
    871 }
    872 
    873 
    874 // DefaultSearchEncodingsPolicyHandler implementation --------------------------
    875 
    876 DefaultSearchEncodingsPolicyHandler::DefaultSearchEncodingsPolicyHandler()
    877     : TypeCheckingPolicyHandler(key::kDefaultSearchProviderEncodings,
    878                                 Value::TYPE_LIST) {
    879 }
    880 
    881 DefaultSearchEncodingsPolicyHandler::~DefaultSearchEncodingsPolicyHandler() {
    882 }
    883 
    884 void DefaultSearchEncodingsPolicyHandler::ApplyPolicySettings(
    885     const PolicyMap& policies, PrefValueMap* prefs) {
    886   // The DefaultSearchProviderEncodings policy has type list, but the related
    887   // preference has type string. Convert one into the other here, using
    888   // ';' as a separator.
    889   const Value* value = policies.GetValue(policy_name());
    890   const ListValue* list;
    891   if (!value || !value->GetAsList(&list))
    892     return;
    893 
    894   ListValue::const_iterator iter(list->begin());
    895   ListValue::const_iterator end(list->end());
    896   std::vector<std::string> string_parts;
    897   for (; iter != end; ++iter) {
    898     std::string s;
    899     if ((*iter)->GetAsString(&s)) {
    900       string_parts.push_back(s);
    901     }
    902   }
    903   std::string encodings = JoinString(string_parts, ';');
    904   prefs->SetValue(prefs::kDefaultSearchProviderEncodings,
    905                   Value::CreateStringValue(encodings));
    906 }
    907 
    908 
    909 // DefaultSearchPolicyHandler implementation -----------------------------------
    910 
    911 DefaultSearchPolicyHandler::DefaultSearchPolicyHandler() {
    912   for (size_t i = 0; i < arraysize(kDefaultSearchPolicyMap); ++i) {
    913     const char* policy_name = kDefaultSearchPolicyMap[i].policy_name;
    914     if (policy_name == key::kDefaultSearchProviderEncodings) {
    915       handlers_.push_back(new DefaultSearchEncodingsPolicyHandler());
    916     } else {
    917       handlers_.push_back(
    918           new SimplePolicyHandler(policy_name,
    919                                   kDefaultSearchPolicyMap[i].preference_path,
    920                                   kDefaultSearchPolicyMap[i].value_type));
    921     }
    922   }
    923 }
    924 
    925 DefaultSearchPolicyHandler::~DefaultSearchPolicyHandler() {
    926   STLDeleteElements(&handlers_);
    927 }
    928 
    929 bool DefaultSearchPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
    930                                                      PolicyErrorMap* errors) {
    931   if (!CheckIndividualPolicies(policies, errors))
    932     return false;
    933 
    934   if (DefaultSearchProviderIsDisabled(policies)) {
    935     // Add an error for all specified default search policies except
    936     // DefaultSearchProviderEnabled.
    937     for (size_t i = 0; i < arraysize(kDefaultSearchPolicyMap); ++i) {
    938       const char* policy_name = kDefaultSearchPolicyMap[i].policy_name;
    939       if (policy_name != key::kDefaultSearchProviderEnabled &&
    940           HasDefaultSearchPolicy(policies, policy_name)) {
    941         errors->AddError(policy_name, IDS_POLICY_DEFAULT_SEARCH_DISABLED);
    942       }
    943     }
    944     return true;
    945   }
    946 
    947   const Value* url;
    948   std::string dummy;
    949   if (DefaultSearchURLIsValid(policies, &url, &dummy) ||
    950       !AnyDefaultSearchPoliciesSpecified(policies))
    951     return true;
    952   errors->AddError(key::kDefaultSearchProviderSearchURL, url ?
    953       IDS_POLICY_INVALID_SEARCH_URL_ERROR : IDS_POLICY_NOT_SPECIFIED_ERROR);
    954   return false;
    955 }
    956 
    957 void DefaultSearchPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
    958                                                      PrefValueMap* prefs) {
    959   if (DefaultSearchProviderIsDisabled(policies)) {
    960     prefs->SetBoolean(prefs::kDefaultSearchProviderEnabled, false);
    961 
    962     // If default search is disabled, the other fields are ignored.
    963     prefs->SetString(prefs::kDefaultSearchProviderName, std::string());
    964     prefs->SetString(prefs::kDefaultSearchProviderSearchURL, std::string());
    965     prefs->SetString(prefs::kDefaultSearchProviderSuggestURL, std::string());
    966     prefs->SetString(prefs::kDefaultSearchProviderIconURL, std::string());
    967     prefs->SetString(prefs::kDefaultSearchProviderEncodings, std::string());
    968     prefs->SetString(prefs::kDefaultSearchProviderKeyword, std::string());
    969     prefs->SetString(prefs::kDefaultSearchProviderInstantURL, std::string());
    970     prefs->SetValue(prefs::kDefaultSearchProviderAlternateURLs,
    971                     new ListValue());
    972     prefs->SetString(prefs::kDefaultSearchProviderSearchTermsReplacementKey,
    973                      std::string());
    974     prefs->SetString(prefs::kDefaultSearchProviderImageURL, std::string());
    975     prefs->SetString(prefs::kDefaultSearchProviderSearchURLPostParams,
    976                      std::string());
    977     prefs->SetString(prefs::kDefaultSearchProviderSuggestURLPostParams,
    978                      std::string());
    979     prefs->SetString(prefs::kDefaultSearchProviderInstantURLPostParams,
    980                      std::string());
    981     prefs->SetString(prefs::kDefaultSearchProviderImageURLPostParams,
    982                      std::string());
    983   } else {
    984     // The search URL is required.  The other entries are optional.  Just make
    985     // sure that they are all specified via policy, so that the regular prefs
    986     // aren't used.
    987     const Value* dummy;
    988     std::string url;
    989     if (DefaultSearchURLIsValid(policies, &dummy, &url)) {
    990       for (std::vector<ConfigurationPolicyHandler*>::const_iterator handler =
    991            handlers_.begin(); handler != handlers_.end(); ++handler)
    992         (*handler)->ApplyPolicySettings(policies, prefs);
    993 
    994       EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderSuggestURL);
    995       EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderIconURL);
    996       EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderEncodings);
    997       EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderKeyword);
    998       EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderInstantURL);
    999       EnsureListPrefExists(prefs, prefs::kDefaultSearchProviderAlternateURLs);
   1000       EnsureStringPrefExists(prefs,
   1001           prefs::kDefaultSearchProviderSearchTermsReplacementKey);
   1002       EnsureStringPrefExists(prefs,
   1003           prefs::kDefaultSearchProviderImageURL);
   1004       EnsureStringPrefExists(prefs,
   1005           prefs::kDefaultSearchProviderSearchURLPostParams);
   1006       EnsureStringPrefExists(prefs,
   1007           prefs::kDefaultSearchProviderSuggestURLPostParams);
   1008       EnsureStringPrefExists(prefs,
   1009           prefs::kDefaultSearchProviderInstantURLPostParams);
   1010       EnsureStringPrefExists(prefs,
   1011           prefs::kDefaultSearchProviderImageURLPostParams);
   1012 
   1013       // For the name and keyword, default to the host if not specified.  If
   1014       // there is no host (file: URLs?  Not sure), use "_" to guarantee that the
   1015       // keyword is non-empty.
   1016       std::string name, keyword;
   1017       std::string host(GURL(url).host());
   1018       if (host.empty())
   1019         host = "_";
   1020       if (!prefs->GetString(prefs::kDefaultSearchProviderName, &name) ||
   1021           name.empty())
   1022         prefs->SetString(prefs::kDefaultSearchProviderName, host);
   1023       if (!prefs->GetString(prefs::kDefaultSearchProviderKeyword, &keyword) ||
   1024           keyword.empty())
   1025         prefs->SetString(prefs::kDefaultSearchProviderKeyword, host);
   1026 
   1027       // And clear the IDs since these are not specified via policy.
   1028       prefs->SetString(prefs::kDefaultSearchProviderID, std::string());
   1029       prefs->SetString(prefs::kDefaultSearchProviderPrepopulateID,
   1030                        std::string());
   1031     }
   1032   }
   1033   content::NotificationService::current()->Notify(
   1034       chrome::NOTIFICATION_DEFAULT_SEARCH_POLICY_CHANGED,
   1035       content::NotificationService::AllSources(),
   1036       content::NotificationService::NoDetails());
   1037 }
   1038 
   1039 bool DefaultSearchPolicyHandler::CheckIndividualPolicies(
   1040     const PolicyMap& policies,
   1041     PolicyErrorMap* errors) {
   1042   std::vector<ConfigurationPolicyHandler*>::const_iterator handler;
   1043   for (handler = handlers_.begin() ; handler != handlers_.end(); ++handler) {
   1044     if (!(*handler)->CheckPolicySettings(policies, errors))
   1045       return false;
   1046   }
   1047   return true;
   1048 }
   1049 
   1050 bool DefaultSearchPolicyHandler::HasDefaultSearchPolicy(
   1051     const PolicyMap& policies,
   1052     const char* policy_name) {
   1053   return policies.Get(policy_name) != NULL;
   1054 }
   1055 
   1056 bool DefaultSearchPolicyHandler::AnyDefaultSearchPoliciesSpecified(
   1057     const PolicyMap& policies) {
   1058   for (size_t i = 0; i < arraysize(kDefaultSearchPolicyMap); ++i) {
   1059     if (policies.Get(kDefaultSearchPolicyMap[i].policy_name))
   1060       return true;
   1061   }
   1062   return false;
   1063 }
   1064 
   1065 bool DefaultSearchPolicyHandler::DefaultSearchProviderIsDisabled(
   1066     const PolicyMap& policies) {
   1067   const Value* provider_enabled =
   1068       policies.GetValue(key::kDefaultSearchProviderEnabled);
   1069   bool enabled = true;
   1070   return provider_enabled && provider_enabled->GetAsBoolean(&enabled) &&
   1071       !enabled;
   1072 }
   1073 
   1074 bool DefaultSearchPolicyHandler::DefaultSearchURLIsValid(
   1075     const PolicyMap& policies,
   1076     const Value** url_value,
   1077     std::string* url_string) {
   1078   *url_value = policies.GetValue(key::kDefaultSearchProviderSearchURL);
   1079   if (!*url_value || !(*url_value)->GetAsString(url_string) ||
   1080       url_string->empty())
   1081     return false;
   1082   TemplateURLData data;
   1083   data.SetURL(*url_string);
   1084   SearchTermsData search_terms_data;
   1085   return TemplateURL(NULL, data).SupportsReplacementUsingTermsData(
   1086       search_terms_data);
   1087 }
   1088 
   1089 void DefaultSearchPolicyHandler::EnsureStringPrefExists(
   1090     PrefValueMap* prefs,
   1091     const std::string& path) {
   1092   std::string value;
   1093   if (!prefs->GetString(path, &value))
   1094     prefs->SetString(path, value);
   1095 }
   1096 
   1097 void DefaultSearchPolicyHandler::EnsureListPrefExists(
   1098     PrefValueMap* prefs,
   1099     const std::string& path) {
   1100   base::Value* value;
   1101   base::ListValue* list_value;
   1102   if (!prefs->GetValue(path, &value) || !value->GetAsList(&list_value))
   1103     prefs->SetValue(path, new ListValue());
   1104 }
   1105 
   1106 
   1107 // ProxyPolicyHandler implementation -------------------------------------------
   1108 
   1109 // The proxy policies have the peculiarity that they are loaded from individual
   1110 // policies, but the providers then expose them through a unified
   1111 // DictionaryValue. Once Dictionary policies are fully supported, the individual
   1112 // proxy policies will be deprecated. http://crbug.com/108996
   1113 
   1114 ProxyPolicyHandler::ProxyPolicyHandler() {
   1115 }
   1116 
   1117 ProxyPolicyHandler::~ProxyPolicyHandler() {
   1118 }
   1119 
   1120 bool ProxyPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
   1121                                              PolicyErrorMap* errors) {
   1122   const Value* mode = GetProxyPolicyValue(policies, key::kProxyMode);
   1123   const Value* server = GetProxyPolicyValue(policies, key::kProxyServer);
   1124   const Value* server_mode =
   1125       GetProxyPolicyValue(policies, key::kProxyServerMode);
   1126   const Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl);
   1127   const Value* bypass_list =
   1128       GetProxyPolicyValue(policies, key::kProxyBypassList);
   1129 
   1130   if ((server || pac_url || bypass_list) && !(mode || server_mode)) {
   1131     errors->AddError(key::kProxySettings,
   1132                      key::kProxyMode,
   1133                      IDS_POLICY_NOT_SPECIFIED_ERROR);
   1134     return false;
   1135   }
   1136 
   1137   std::string mode_value;
   1138   if (!CheckProxyModeAndServerMode(policies, errors, &mode_value))
   1139     return false;
   1140 
   1141   // If neither ProxyMode nor ProxyServerMode are specified, mode_value will be
   1142   // empty and the proxy shouldn't be configured at all.
   1143   if (mode_value.empty())
   1144     return true;
   1145 
   1146   bool is_valid_mode = false;
   1147   for (size_t i = 0; i != arraysize(kProxyModeValidationMap); ++i) {
   1148     const ProxyModeValidationEntry& entry = kProxyModeValidationMap[i];
   1149     if (entry.mode_value != mode_value)
   1150       continue;
   1151 
   1152     is_valid_mode = true;
   1153 
   1154     if (!entry.pac_url_allowed && pac_url) {
   1155       errors->AddError(key::kProxySettings,
   1156                        key::kProxyPacUrl,
   1157                        entry.error_message_id);
   1158     }
   1159     if (!entry.bypass_list_allowed && bypass_list) {
   1160       errors->AddError(key::kProxySettings,
   1161                        key::kProxyBypassList,
   1162                        entry.error_message_id);
   1163     }
   1164     if (!entry.server_allowed && server) {
   1165       errors->AddError(key::kProxySettings,
   1166                        key::kProxyServer,
   1167                        entry.error_message_id);
   1168     }
   1169 
   1170     if ((!entry.pac_url_allowed && pac_url) ||
   1171         (!entry.bypass_list_allowed && bypass_list) ||
   1172         (!entry.server_allowed && server)) {
   1173       return false;
   1174     }
   1175   }
   1176 
   1177   if (!is_valid_mode) {
   1178     errors->AddError(key::kProxySettings,
   1179                      mode ? key::kProxyMode : key::kProxyServerMode,
   1180                      IDS_POLICY_OUT_OF_RANGE_ERROR,
   1181                      mode_value);
   1182     return false;
   1183   }
   1184   return true;
   1185 }
   1186 
   1187 void ProxyPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
   1188                                              PrefValueMap* prefs) {
   1189   const Value* mode = GetProxyPolicyValue(policies, key::kProxyMode);
   1190   const Value* server = GetProxyPolicyValue(policies, key::kProxyServer);
   1191   const Value* server_mode =
   1192       GetProxyPolicyValue(policies, key::kProxyServerMode);
   1193   const Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl);
   1194   const Value* bypass_list =
   1195       GetProxyPolicyValue(policies, key::kProxyBypassList);
   1196 
   1197   ProxyPrefs::ProxyMode proxy_mode;
   1198   if (mode) {
   1199     std::string string_mode;
   1200     CHECK(mode->GetAsString(&string_mode));
   1201     CHECK(ProxyPrefs::StringToProxyMode(string_mode, &proxy_mode));
   1202   } else if (server_mode) {
   1203     int int_mode = 0;
   1204     CHECK(server_mode->GetAsInteger(&int_mode));
   1205 
   1206     switch (int_mode) {
   1207       case PROXY_SERVER_MODE:
   1208         proxy_mode = ProxyPrefs::MODE_DIRECT;
   1209         break;
   1210       case PROXY_AUTO_DETECT_PROXY_SERVER_MODE:
   1211         proxy_mode = ProxyPrefs::MODE_AUTO_DETECT;
   1212         break;
   1213       case PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE:
   1214         proxy_mode = ProxyPrefs::MODE_FIXED_SERVERS;
   1215         if (pac_url)
   1216           proxy_mode = ProxyPrefs::MODE_PAC_SCRIPT;
   1217         break;
   1218       case PROXY_USE_SYSTEM_PROXY_SERVER_MODE:
   1219         proxy_mode = ProxyPrefs::MODE_SYSTEM;
   1220         break;
   1221       default:
   1222         proxy_mode = ProxyPrefs::MODE_DIRECT;
   1223         NOTREACHED();
   1224     }
   1225   } else {
   1226     return;
   1227   }
   1228 
   1229   switch (proxy_mode) {
   1230     case ProxyPrefs::MODE_DIRECT:
   1231       prefs->SetValue(prefs::kProxy, ProxyConfigDictionary::CreateDirect());
   1232       break;
   1233     case ProxyPrefs::MODE_AUTO_DETECT:
   1234       prefs->SetValue(prefs::kProxy, ProxyConfigDictionary::CreateAutoDetect());
   1235       break;
   1236     case ProxyPrefs::MODE_PAC_SCRIPT: {
   1237       std::string pac_url_string;
   1238       if (pac_url && pac_url->GetAsString(&pac_url_string)) {
   1239         prefs->SetValue(prefs::kProxy,
   1240             ProxyConfigDictionary::CreatePacScript(pac_url_string, false));
   1241       } else {
   1242         NOTREACHED();
   1243       }
   1244       break;
   1245     }
   1246     case ProxyPrefs::MODE_FIXED_SERVERS: {
   1247       std::string proxy_server;
   1248       std::string bypass_list_string;
   1249       if (server->GetAsString(&proxy_server)) {
   1250         if (bypass_list)
   1251           bypass_list->GetAsString(&bypass_list_string);
   1252         prefs->SetValue(prefs::kProxy,
   1253                         ProxyConfigDictionary::CreateFixedServers(
   1254                             proxy_server, bypass_list_string));
   1255       }
   1256       break;
   1257     }
   1258     case ProxyPrefs::MODE_SYSTEM:
   1259       prefs->SetValue(prefs::kProxy,
   1260                       ProxyConfigDictionary::CreateSystem());
   1261       break;
   1262     case ProxyPrefs::kModeCount:
   1263       NOTREACHED();
   1264   }
   1265 }
   1266 
   1267 const Value* ProxyPolicyHandler::GetProxyPolicyValue(
   1268     const PolicyMap& policies, const char* policy_name) {
   1269   // See note on the ProxyPolicyHandler implementation above.
   1270   const Value* value = policies.GetValue(key::kProxySettings);
   1271   const DictionaryValue* settings;
   1272   if (!value || !value->GetAsDictionary(&settings))
   1273     return NULL;
   1274 
   1275   const Value* policy_value = NULL;
   1276   std::string tmp;
   1277   if (!settings->Get(policy_name, &policy_value) ||
   1278       policy_value->IsType(Value::TYPE_NULL) ||
   1279       (policy_value->IsType(Value::TYPE_STRING) &&
   1280        policy_value->GetAsString(&tmp) &&
   1281        tmp.empty())) {
   1282     return NULL;
   1283   }
   1284   return policy_value;
   1285 }
   1286 
   1287 bool ProxyPolicyHandler::CheckProxyModeAndServerMode(const PolicyMap& policies,
   1288                                                      PolicyErrorMap* errors,
   1289                                                      std::string* mode_value) {
   1290   const Value* mode = GetProxyPolicyValue(policies, key::kProxyMode);
   1291   const Value* server = GetProxyPolicyValue(policies, key::kProxyServer);
   1292   const Value* server_mode =
   1293       GetProxyPolicyValue(policies, key::kProxyServerMode);
   1294   const Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl);
   1295 
   1296   // If there's a server mode, convert it into a mode.
   1297   // When both are specified, the mode takes precedence.
   1298   if (mode) {
   1299     if (server_mode) {
   1300       errors->AddError(key::kProxySettings,
   1301                        key::kProxyServerMode,
   1302                        IDS_POLICY_OVERRIDDEN,
   1303                        key::kProxyMode);
   1304     }
   1305     if (!mode->GetAsString(mode_value)) {
   1306       errors->AddError(key::kProxySettings,
   1307                        key::kProxyMode,
   1308                        IDS_POLICY_TYPE_ERROR,
   1309                        ValueTypeToString(Value::TYPE_BOOLEAN));
   1310       return false;
   1311     }
   1312 
   1313     ProxyPrefs::ProxyMode mode;
   1314     if (!ProxyPrefs::StringToProxyMode(*mode_value, &mode)) {
   1315       errors->AddError(key::kProxySettings,
   1316                        key::kProxyMode,
   1317                        IDS_POLICY_INVALID_PROXY_MODE_ERROR);
   1318       return false;
   1319     }
   1320 
   1321     if (mode == ProxyPrefs::MODE_PAC_SCRIPT && !pac_url) {
   1322       errors->AddError(key::kProxySettings,
   1323                        key::kProxyPacUrl,
   1324                        IDS_POLICY_NOT_SPECIFIED_ERROR);
   1325       return false;
   1326     } else if (mode == ProxyPrefs::MODE_FIXED_SERVERS && !server) {
   1327       errors->AddError(key::kProxySettings,
   1328                        key::kProxyServer,
   1329                        IDS_POLICY_NOT_SPECIFIED_ERROR);
   1330       return false;
   1331     }
   1332   } else if (server_mode) {
   1333     int server_mode_value;
   1334     if (!server_mode->GetAsInteger(&server_mode_value)) {
   1335       errors->AddError(key::kProxySettings,
   1336                        key::kProxyServerMode,
   1337                        IDS_POLICY_TYPE_ERROR,
   1338                        ValueTypeToString(Value::TYPE_INTEGER));
   1339       return false;
   1340     }
   1341 
   1342     switch (server_mode_value) {
   1343       case PROXY_SERVER_MODE:
   1344         *mode_value = ProxyPrefs::kDirectProxyModeName;
   1345         break;
   1346       case PROXY_AUTO_DETECT_PROXY_SERVER_MODE:
   1347         *mode_value = ProxyPrefs::kAutoDetectProxyModeName;
   1348         break;
   1349       case PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE:
   1350         if (server && pac_url) {
   1351           int message_id = IDS_POLICY_PROXY_BOTH_SPECIFIED_ERROR;
   1352           errors->AddError(key::kProxySettings,
   1353                            key::kProxyServer,
   1354                            message_id);
   1355           errors->AddError(key::kProxySettings,
   1356                            key::kProxyPacUrl,
   1357                            message_id);
   1358           return false;
   1359         }
   1360         if (!server && !pac_url) {
   1361           int message_id = IDS_POLICY_PROXY_NEITHER_SPECIFIED_ERROR;
   1362           errors->AddError(key::kProxySettings,
   1363                            key::kProxyServer,
   1364                            message_id);
   1365           errors->AddError(key::kProxySettings,
   1366                            key::kProxyPacUrl,
   1367                            message_id);
   1368           return false;
   1369         }
   1370         if (pac_url)
   1371           *mode_value = ProxyPrefs::kPacScriptProxyModeName;
   1372         else
   1373           *mode_value = ProxyPrefs::kFixedServersProxyModeName;
   1374         break;
   1375       case PROXY_USE_SYSTEM_PROXY_SERVER_MODE:
   1376         *mode_value = ProxyPrefs::kSystemProxyModeName;
   1377         break;
   1378       default:
   1379         errors->AddError(key::kProxySettings,
   1380                          key::kProxyServerMode,
   1381                          IDS_POLICY_OUT_OF_RANGE_ERROR,
   1382                          base::IntToString(server_mode_value));
   1383         return false;
   1384     }
   1385   }
   1386   return true;
   1387 }
   1388 
   1389 
   1390 // JavascriptPolicyHandler implementation --------------------------------------
   1391 
   1392 JavascriptPolicyHandler::JavascriptPolicyHandler() {
   1393 }
   1394 
   1395 JavascriptPolicyHandler::~JavascriptPolicyHandler() {
   1396 }
   1397 
   1398 bool JavascriptPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
   1399                                                   PolicyErrorMap* errors) {
   1400   const Value* javascript_enabled = policies.GetValue(key::kJavascriptEnabled);
   1401   const Value* default_setting =
   1402       policies.GetValue(key::kDefaultJavaScriptSetting);
   1403 
   1404   if (javascript_enabled && !javascript_enabled->IsType(Value::TYPE_BOOLEAN)) {
   1405     errors->AddError(key::kJavascriptEnabled,
   1406                      IDS_POLICY_TYPE_ERROR,
   1407                      ValueTypeToString(Value::TYPE_BOOLEAN));
   1408   }
   1409 
   1410   if (default_setting && !default_setting->IsType(Value::TYPE_INTEGER)) {
   1411     errors->AddError(key::kDefaultJavaScriptSetting,
   1412                      IDS_POLICY_TYPE_ERROR,
   1413                      ValueTypeToString(Value::TYPE_INTEGER));
   1414   }
   1415 
   1416   if (javascript_enabled && default_setting) {
   1417     errors->AddError(key::kJavascriptEnabled,
   1418                      IDS_POLICY_OVERRIDDEN,
   1419                      key::kDefaultJavaScriptSetting);
   1420   }
   1421 
   1422   return true;
   1423 }
   1424 
   1425 void JavascriptPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
   1426                                                   PrefValueMap* prefs) {
   1427   int setting = CONTENT_SETTING_DEFAULT;
   1428   const Value* default_setting =
   1429       policies.GetValue(key::kDefaultJavaScriptSetting);
   1430 
   1431   if (default_setting) {
   1432     default_setting->GetAsInteger(&setting);
   1433   } else {
   1434     const Value* javascript_enabled =
   1435         policies.GetValue(key::kJavascriptEnabled);
   1436     bool enabled = true;
   1437     if (javascript_enabled &&
   1438         javascript_enabled->GetAsBoolean(&enabled) &&
   1439         !enabled) {
   1440       setting = CONTENT_SETTING_BLOCK;
   1441     }
   1442   }
   1443 
   1444   if (setting != CONTENT_SETTING_DEFAULT) {
   1445     prefs->SetValue(prefs::kManagedDefaultJavaScriptSetting,
   1446                     Value::CreateIntegerValue(setting));
   1447   }
   1448 }
   1449 
   1450 // URLBlacklistPolicyHandler implementation ------------------------------------
   1451 
   1452 URLBlacklistPolicyHandler::URLBlacklistPolicyHandler() {
   1453 }
   1454 
   1455 URLBlacklistPolicyHandler::~URLBlacklistPolicyHandler() {
   1456 }
   1457 
   1458 bool URLBlacklistPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
   1459                                                     PolicyErrorMap* errors) {
   1460   const Value* disabled_schemes = policies.GetValue(key::kDisabledSchemes);
   1461   const Value* url_blacklist = policies.GetValue(key::kURLBlacklist);
   1462 
   1463   if (disabled_schemes && !disabled_schemes->IsType(Value::TYPE_LIST)) {
   1464     errors->AddError(key::kDisabledSchemes,
   1465                      IDS_POLICY_TYPE_ERROR,
   1466                      ValueTypeToString(Value::TYPE_LIST));
   1467   }
   1468 
   1469   if (url_blacklist && !url_blacklist->IsType(Value::TYPE_LIST)) {
   1470       errors->AddError(key::kURLBlacklist,
   1471                        IDS_POLICY_TYPE_ERROR,
   1472                        ValueTypeToString(Value::TYPE_LIST));
   1473   }
   1474 
   1475   return true;
   1476 }
   1477 
   1478 void URLBlacklistPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
   1479                                                     PrefValueMap* prefs) {
   1480   const base::Value* url_blacklist_policy =
   1481       policies.GetValue(key::kURLBlacklist);
   1482   const base::ListValue* url_blacklist = NULL;
   1483   if (url_blacklist_policy)
   1484     url_blacklist_policy->GetAsList(&url_blacklist);
   1485   const base::Value* disabled_schemes_policy =
   1486       policies.GetValue(key::kDisabledSchemes);
   1487   const base::ListValue* disabled_schemes = NULL;
   1488   if (disabled_schemes_policy)
   1489     disabled_schemes_policy->GetAsList(&disabled_schemes);
   1490 
   1491   scoped_ptr<base::ListValue> merged_url_blacklist(new base::ListValue());
   1492 
   1493   // We start with the DisabledSchemes because we have size limit when
   1494   // handling URLBacklists.
   1495   if (disabled_schemes_policy) {
   1496     for (base::ListValue::const_iterator entry(disabled_schemes->begin());
   1497          entry != disabled_schemes->end(); ++entry) {
   1498       std::string entry_value;
   1499       if ((*entry)->GetAsString(&entry_value)) {
   1500         entry_value.append("://*");
   1501         merged_url_blacklist->AppendString(entry_value);
   1502       }
   1503     }
   1504   }
   1505 
   1506   if (url_blacklist_policy) {
   1507     for (base::ListValue::const_iterator entry(url_blacklist->begin());
   1508          entry != url_blacklist->end(); ++entry) {
   1509       if ((*entry)->IsType(Value::TYPE_STRING))
   1510         merged_url_blacklist->Append((*entry)->DeepCopy());
   1511     }
   1512   }
   1513 
   1514   if (disabled_schemes_policy || url_blacklist_policy)
   1515     prefs->SetValue(prefs::kUrlBlacklist, merged_url_blacklist.release());
   1516 }
   1517 
   1518 // RestoreOnStartupPolicyHandler implementation --------------------------------
   1519 
   1520 RestoreOnStartupPolicyHandler::RestoreOnStartupPolicyHandler()
   1521     : TypeCheckingPolicyHandler(key::kRestoreOnStartup,
   1522                                 Value::TYPE_INTEGER) {
   1523 }
   1524 
   1525 RestoreOnStartupPolicyHandler::~RestoreOnStartupPolicyHandler() {
   1526 }
   1527 
   1528 void RestoreOnStartupPolicyHandler::ApplyPolicySettings(
   1529     const PolicyMap& policies,
   1530     PrefValueMap* prefs) {
   1531   const Value* restore_on_startup_value = policies.GetValue(policy_name());
   1532   if (restore_on_startup_value) {
   1533     int restore_on_startup;
   1534     if (!restore_on_startup_value->GetAsInteger(&restore_on_startup))
   1535       return;
   1536 
   1537     if (restore_on_startup == SessionStartupPref::kPrefValueHomePage)
   1538       ApplyPolicySettingsFromHomePage(policies, prefs);
   1539     else
   1540       prefs->SetInteger(prefs::kRestoreOnStartup, restore_on_startup);
   1541   }
   1542 }
   1543 
   1544 void RestoreOnStartupPolicyHandler::ApplyPolicySettingsFromHomePage(
   1545     const PolicyMap& policies,
   1546     PrefValueMap* prefs) {
   1547   const base::Value* homepage_is_new_tab_page_value =
   1548       policies.GetValue(key::kHomepageIsNewTabPage);
   1549   if (!homepage_is_new_tab_page_value) {
   1550     // The policy is enforcing 'open the homepage on startup' but not
   1551     // enforcing what the homepage should be. Don't set any prefs.
   1552     return;
   1553   }
   1554 
   1555   bool homepage_is_new_tab_page;
   1556   if (!homepage_is_new_tab_page_value->GetAsBoolean(&homepage_is_new_tab_page))
   1557     return;
   1558 
   1559   if (homepage_is_new_tab_page) {
   1560     prefs->SetInteger(prefs::kRestoreOnStartup,
   1561                       SessionStartupPref::kPrefValueNewTab);
   1562   } else {
   1563     const base::Value* homepage_value =
   1564         policies.GetValue(key::kHomepageLocation);
   1565     if (!homepage_value || !homepage_value->IsType(base::Value::TYPE_STRING)) {
   1566       // The policy is enforcing 'open the homepage on startup' but not
   1567       // enforcing what the homepage should be. Don't set any prefs.
   1568       return;
   1569     }
   1570     ListValue* url_list = new ListValue();
   1571     url_list->Append(homepage_value->DeepCopy());
   1572     prefs->SetInteger(prefs::kRestoreOnStartup,
   1573                       SessionStartupPref::kPrefValueURLs);
   1574     prefs->SetValue(prefs::kURLsToRestoreOnStartup, url_list);
   1575   }
   1576 }
   1577 
   1578 bool RestoreOnStartupPolicyHandler::CheckPolicySettings(
   1579     const PolicyMap& policies,
   1580     PolicyErrorMap* errors) {
   1581   if (!TypeCheckingPolicyHandler::CheckPolicySettings(policies, errors))
   1582     return false;
   1583 
   1584   const base::Value* restore_policy = policies.GetValue(key::kRestoreOnStartup);
   1585 
   1586   if (restore_policy) {
   1587     int restore_value;
   1588     if (restore_policy->GetAsInteger(&restore_value)) {
   1589       switch (restore_value) {
   1590         case SessionStartupPref::kPrefValueHomePage:
   1591           errors->AddError(policy_name(), IDS_POLICY_VALUE_DEPRECATED);
   1592           break;
   1593         case SessionStartupPref::kPrefValueLast: {
   1594           // If the "restore last session" policy is set, session cookies are
   1595           // treated as permanent cookies and site data needed to restore the
   1596           // session is not cleared so we have to warn the user in that case.
   1597           const base::Value* cookies_policy =
   1598               policies.GetValue(key::kCookiesSessionOnlyForUrls);
   1599           const base::ListValue *cookies_value;
   1600           if (cookies_policy && cookies_policy->GetAsList(&cookies_value) &&
   1601               !cookies_value->empty()) {
   1602             errors->AddError(key::kCookiesSessionOnlyForUrls,
   1603                              IDS_POLICY_OVERRIDDEN,
   1604                              key::kRestoreOnStartup);
   1605           }
   1606 
   1607           const base::Value* exit_policy =
   1608               policies.GetValue(key::kClearSiteDataOnExit);
   1609           bool exit_value;
   1610           if (exit_policy &&
   1611               exit_policy->GetAsBoolean(&exit_value) && exit_value) {
   1612             errors->AddError(key::kClearSiteDataOnExit,
   1613                              IDS_POLICY_OVERRIDDEN,
   1614                              key::kRestoreOnStartup);
   1615           }
   1616           break;
   1617         }
   1618         case SessionStartupPref::kPrefValueURLs:
   1619         case SessionStartupPref::kPrefValueNewTab:
   1620           // No error
   1621           break;
   1622         default:
   1623           errors->AddError(policy_name(),
   1624                            IDS_POLICY_OUT_OF_RANGE_ERROR,
   1625                            base::IntToString(restore_value));
   1626       }
   1627     }
   1628   }
   1629   return true;
   1630 }
   1631 
   1632 }  // namespace policy
   1633