Home | History | Annotate | Download | only in extensions
      1 // Copyright 2013 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/extensions/policy_handlers.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/prefs/pref_value_map.h"
      9 #include "chrome/browser/extensions/external_policy_loader.h"
     10 #include "chrome/common/pref_names.h"
     11 #include "components/policy/core/browser/policy_error_map.h"
     12 #include "components/policy/core/common/policy_map.h"
     13 #include "extensions/common/extension.h"
     14 #include "grit/component_strings.h"
     15 #include "policy/policy_constants.h"
     16 
     17 namespace extensions {
     18 
     19 // ExtensionListPolicyHandler implementation -----------------------------------
     20 
     21 ExtensionListPolicyHandler::ExtensionListPolicyHandler(const char* policy_name,
     22                                                        const char* pref_path,
     23                                                        bool allow_wildcards)
     24     : policy::TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST),
     25       pref_path_(pref_path),
     26       allow_wildcards_(allow_wildcards) {}
     27 
     28 ExtensionListPolicyHandler::~ExtensionListPolicyHandler() {}
     29 
     30 bool ExtensionListPolicyHandler::CheckPolicySettings(
     31     const policy::PolicyMap& policies,
     32     policy::PolicyErrorMap* errors) {
     33   return CheckAndGetList(policies, errors, NULL);
     34 }
     35 
     36 void ExtensionListPolicyHandler::ApplyPolicySettings(
     37     const policy::PolicyMap& policies,
     38     PrefValueMap* prefs) {
     39   scoped_ptr<base::ListValue> list;
     40   policy::PolicyErrorMap errors;
     41   if (CheckAndGetList(policies, &errors, &list) && list)
     42     prefs->SetValue(pref_path(), list.release());
     43 }
     44 
     45 const char* ExtensionListPolicyHandler::pref_path() const {
     46   return pref_path_;
     47 }
     48 
     49 bool ExtensionListPolicyHandler::CheckAndGetList(
     50     const policy::PolicyMap& policies,
     51     policy::PolicyErrorMap* errors,
     52     scoped_ptr<base::ListValue>* extension_ids) {
     53   if (extension_ids)
     54     extension_ids->reset();
     55 
     56   const base::Value* value = NULL;
     57   if (!CheckAndGetValue(policies, errors, &value))
     58     return false;
     59 
     60   if (!value)
     61     return true;
     62 
     63   const base::ListValue* list_value = NULL;
     64   if (!value->GetAsList(&list_value)) {
     65     NOTREACHED();
     66     return false;
     67   }
     68 
     69   // Filter the list, rejecting any invalid extension IDs.
     70   scoped_ptr<base::ListValue> filtered_list(new base::ListValue());
     71   for (base::ListValue::const_iterator entry(list_value->begin());
     72        entry != list_value->end(); ++entry) {
     73     std::string id;
     74     if (!(*entry)->GetAsString(&id)) {
     75       errors->AddError(policy_name(),
     76                        entry - list_value->begin(),
     77                        IDS_POLICY_TYPE_ERROR,
     78                        ValueTypeToString(base::Value::TYPE_STRING));
     79       continue;
     80     }
     81     if (!(allow_wildcards_ && id == "*") &&
     82         !extensions::Extension::IdIsValid(id)) {
     83       errors->AddError(policy_name(),
     84                        entry - list_value->begin(),
     85                        IDS_POLICY_VALUE_FORMAT_ERROR);
     86       continue;
     87     }
     88     filtered_list->Append(base::Value::CreateStringValue(id));
     89   }
     90 
     91   if (extension_ids)
     92     *extension_ids = filtered_list.Pass();
     93 
     94   return true;
     95 }
     96 
     97 // ExtensionInstallForcelistPolicyHandler implementation -----------------------
     98 
     99 ExtensionInstallForcelistPolicyHandler::ExtensionInstallForcelistPolicyHandler()
    100     : policy::TypeCheckingPolicyHandler(policy::key::kExtensionInstallForcelist,
    101                                         base::Value::TYPE_LIST) {}
    102 
    103 ExtensionInstallForcelistPolicyHandler::
    104     ~ExtensionInstallForcelistPolicyHandler() {}
    105 
    106 bool ExtensionInstallForcelistPolicyHandler::CheckPolicySettings(
    107     const policy::PolicyMap& policies,
    108     policy::PolicyErrorMap* errors) {
    109   const base::Value* value;
    110   return CheckAndGetValue(policies, errors, &value) &&
    111       ParseList(value, NULL, errors);
    112 }
    113 
    114 void ExtensionInstallForcelistPolicyHandler::ApplyPolicySettings(
    115     const policy::PolicyMap& policies,
    116     PrefValueMap* prefs) {
    117   const base::Value* value = NULL;
    118   scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
    119   if (CheckAndGetValue(policies, NULL, &value) &&
    120       value &&
    121       ParseList(value, dict.get(), NULL)) {
    122     prefs->SetValue(prefs::kExtensionInstallForceList, dict.release());
    123   }
    124 }
    125 
    126 bool ExtensionInstallForcelistPolicyHandler::ParseList(
    127     const base::Value* policy_value,
    128     base::DictionaryValue* extension_dict,
    129     policy::PolicyErrorMap* errors) {
    130   if (!policy_value)
    131     return true;
    132 
    133   const base::ListValue* policy_list_value = NULL;
    134   if (!policy_value->GetAsList(&policy_list_value)) {
    135     // This should have been caught in CheckPolicySettings.
    136     NOTREACHED();
    137     return false;
    138   }
    139 
    140   for (base::ListValue::const_iterator entry(policy_list_value->begin());
    141        entry != policy_list_value->end(); ++entry) {
    142     std::string entry_string;
    143     if (!(*entry)->GetAsString(&entry_string)) {
    144       if (errors) {
    145         errors->AddError(policy_name(),
    146                          entry - policy_list_value->begin(),
    147                          IDS_POLICY_TYPE_ERROR,
    148                          ValueTypeToString(base::Value::TYPE_STRING));
    149       }
    150       continue;
    151     }
    152 
    153     // Each string item of the list has the following form:
    154     // <extension_id>;<update_url>
    155     // Note: The update URL might also contain semicolons.
    156     size_t pos = entry_string.find(';');
    157     if (pos == std::string::npos) {
    158       if (errors) {
    159         errors->AddError(policy_name(),
    160                          entry - policy_list_value->begin(),
    161                          IDS_POLICY_VALUE_FORMAT_ERROR);
    162       }
    163       continue;
    164     }
    165 
    166     std::string extension_id = entry_string.substr(0, pos);
    167     std::string update_url = entry_string.substr(pos+1);
    168     if (!extensions::Extension::IdIsValid(extension_id) ||
    169         !GURL(update_url).is_valid()) {
    170       if (errors) {
    171         errors->AddError(policy_name(),
    172                          entry - policy_list_value->begin(),
    173                          IDS_POLICY_VALUE_FORMAT_ERROR);
    174       }
    175       continue;
    176     }
    177 
    178     if (extension_dict) {
    179       extensions::ExternalPolicyLoader::AddExtension(
    180           extension_dict, extension_id, update_url);
    181     }
    182   }
    183 
    184   return true;
    185 }
    186 
    187 // ExtensionURLPatternListPolicyHandler implementation -------------------------
    188 
    189 ExtensionURLPatternListPolicyHandler::ExtensionURLPatternListPolicyHandler(
    190     const char* policy_name,
    191     const char* pref_path)
    192     : policy::TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST),
    193       pref_path_(pref_path) {}
    194 
    195 ExtensionURLPatternListPolicyHandler::~ExtensionURLPatternListPolicyHandler() {}
    196 
    197 bool ExtensionURLPatternListPolicyHandler::CheckPolicySettings(
    198     const policy::PolicyMap& policies,
    199     policy::PolicyErrorMap* errors) {
    200   const base::Value* value = NULL;
    201   if (!CheckAndGetValue(policies, errors, &value))
    202     return false;
    203 
    204   if (!value)
    205     return true;
    206 
    207   const base::ListValue* list_value = NULL;
    208   if (!value->GetAsList(&list_value)) {
    209     NOTREACHED();
    210     return false;
    211   }
    212 
    213   // Check that the list contains valid URLPattern strings only.
    214   for (base::ListValue::const_iterator entry(list_value->begin());
    215        entry != list_value->end(); ++entry) {
    216     std::string url_pattern_string;
    217     if (!(*entry)->GetAsString(&url_pattern_string)) {
    218       errors->AddError(policy_name(),
    219                        entry - list_value->begin(),
    220                        IDS_POLICY_TYPE_ERROR,
    221                        ValueTypeToString(base::Value::TYPE_STRING));
    222       return false;
    223     }
    224 
    225     URLPattern pattern(URLPattern::SCHEME_ALL);
    226     if (pattern.Parse(url_pattern_string) != URLPattern::PARSE_SUCCESS) {
    227       errors->AddError(policy_name(),
    228                        entry - list_value->begin(),
    229                        IDS_POLICY_VALUE_FORMAT_ERROR);
    230       return false;
    231     }
    232   }
    233 
    234   return true;
    235 }
    236 
    237 void ExtensionURLPatternListPolicyHandler::ApplyPolicySettings(
    238     const policy::PolicyMap& policies,
    239     PrefValueMap* prefs) {
    240   if (!pref_path_)
    241     return;
    242   const Value* value = policies.GetValue(policy_name());
    243   if (value)
    244     prefs->SetValue(pref_path_, value->DeepCopy());
    245 }
    246 
    247 }  // namespace extensions
    248