Home | History | Annotate | Download | only in features
      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/common/extensions/features/base_feature_provider.h"
      6 
      7 #include <stack>
      8 
      9 #include "base/json/json_reader.h"
     10 #include "base/lazy_instance.h"
     11 #include "base/strings/string_split.h"
     12 #include "base/strings/string_util.h"
     13 #include "chrome/common/extensions/features/api_feature.h"
     14 #include "chrome/common/extensions/features/complex_feature.h"
     15 #include "chrome/common/extensions/features/manifest_feature.h"
     16 #include "chrome/common/extensions/features/permission_feature.h"
     17 #include "grit/common_resources.h"
     18 #include "ui/base/resource/resource_bundle.h"
     19 
     20 namespace extensions {
     21 
     22 namespace {
     23 
     24 template<class FeatureClass>
     25 SimpleFeature* CreateFeature() {
     26   return new FeatureClass();
     27 }
     28 
     29 static BaseFeatureProvider* LoadProvider(
     30       const std::string& name,
     31       BaseFeatureProvider::FeatureFactory factory,
     32       int resource_id) {
     33   const std::string& features_file =
     34       ResourceBundle::GetSharedInstance().GetRawDataResource(
     35           resource_id).as_string();
     36   int error_code = 0;
     37   std::string error_message;
     38   scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
     39       features_file, base::JSON_PARSE_RFC,
     40       &error_code, &error_message));
     41   DCHECK(value) << "Could not load features: " << name << " "
     42       << error_message;
     43   scoped_ptr<base::DictionaryValue> value_as_dict;
     44   if (value) {
     45     CHECK(value->IsType(base::Value::TYPE_DICTIONARY)) << name;
     46     value_as_dict.reset(static_cast<base::DictionaryValue*>(value.release()));
     47   } else {
     48     // http://crbug.com/176381
     49     value_as_dict.reset(new base::DictionaryValue());
     50   }
     51   return new BaseFeatureProvider(*value_as_dict, factory);
     52 }
     53 
     54 struct Static {
     55   Static() {
     56     feature_providers["api"] = make_linked_ptr(
     57         LoadProvider("api",
     58                      &CreateFeature<APIFeature>,
     59                      IDR_EXTENSION_API_FEATURES));
     60     feature_providers["permission"] = make_linked_ptr(
     61         LoadProvider("permission",
     62                      &CreateFeature<PermissionFeature>,
     63                      IDR_EXTENSION_PERMISSION_FEATURES));
     64     feature_providers["manifest"] = make_linked_ptr(
     65         LoadProvider("manifest",
     66                      &CreateFeature<ManifestFeature>,
     67                      IDR_EXTENSION_MANIFEST_FEATURES));
     68   }
     69 
     70   typedef std::map<std::string, linked_ptr<FeatureProvider> >
     71       FeatureProviderMap;
     72 
     73   FeatureProvider* GetFeatures(const std::string& name) const {
     74     FeatureProviderMap::const_iterator it = feature_providers.find(name);
     75     CHECK(it != feature_providers.end());
     76     return it->second.get();
     77   }
     78 
     79   FeatureProviderMap feature_providers;
     80 };
     81 
     82 base::LazyInstance<Static> g_static = LAZY_INSTANCE_INITIALIZER;
     83 
     84 bool ParseFeature(const base::DictionaryValue* value,
     85                   const std::string& name,
     86                   SimpleFeature* feature) {
     87   feature->set_name(name);
     88   std::string error = feature->Parse(value);
     89   if (!error.empty())
     90     LOG(ERROR) << error;
     91   return error.empty();
     92 }
     93 
     94 }  // namespace
     95 
     96 BaseFeatureProvider::BaseFeatureProvider(const base::DictionaryValue& root,
     97                                          FeatureFactory factory)
     98     : factory_(factory ? factory :
     99                static_cast<FeatureFactory>(&CreateFeature<SimpleFeature>)) {
    100   for (base::DictionaryValue::Iterator iter(root); !iter.IsAtEnd();
    101        iter.Advance()) {
    102     if (iter.value().GetType() == base::Value::TYPE_DICTIONARY) {
    103       linked_ptr<SimpleFeature> feature((*factory_)());
    104 
    105       std::vector<std::string> split;
    106       base::SplitString(iter.key(), '.', &split);
    107 
    108       // Push parent features on the stack, starting with the current feature.
    109       // If one of the features has "noparent" set, stop pushing features on
    110       // the stack. The features will then be parsed in order, starting with
    111       // the farthest parent that is either top level or has "noparent" set.
    112       std::stack<std::pair<std::string, const base::DictionaryValue*> >
    113           parse_stack;
    114       while (!split.empty()) {
    115         std::string parent_name = JoinString(split, '.');
    116         split.pop_back();
    117         if (root.HasKey(parent_name)) {
    118           const base::DictionaryValue* parent = NULL;
    119           CHECK(root.GetDictionaryWithoutPathExpansion(parent_name, &parent));
    120           parse_stack.push(std::make_pair(parent_name, parent));
    121           bool no_parent = false;
    122           parent->GetBoolean("noparent", &no_parent);
    123           if (no_parent)
    124             break;
    125         }
    126       }
    127 
    128       CHECK(!parse_stack.empty());
    129       // Parse all parent features.
    130       bool parse_error = false;
    131       while (!parse_stack.empty()) {
    132         if (!ParseFeature(parse_stack.top().second,
    133                           parse_stack.top().first,
    134                           feature.get())) {
    135           parse_error = true;
    136           break;
    137         }
    138         parse_stack.pop();
    139       }
    140 
    141       if (parse_error)
    142         continue;
    143 
    144       features_[iter.key()] = feature;
    145     } else if (iter.value().GetType() == base::Value::TYPE_LIST) {
    146       // This is a complex feature.
    147       const base::ListValue* list =
    148           static_cast<const base::ListValue*>(&iter.value());
    149       CHECK_GT(list->GetSize(), 0UL);
    150 
    151       scoped_ptr<ComplexFeature::FeatureList> features(
    152           new ComplexFeature::FeatureList());
    153 
    154       // Parse and add all SimpleFeatures from the list.
    155       for (base::ListValue::const_iterator list_iter = list->begin();
    156            list_iter != list->end(); ++list_iter) {
    157         if ((*list_iter)->GetType() != base::Value::TYPE_DICTIONARY) {
    158           LOG(ERROR) << iter.key() << ": Feature rules must be dictionaries.";
    159           continue;
    160         }
    161 
    162         scoped_ptr<SimpleFeature> feature((*factory_)());
    163         if (!ParseFeature(static_cast<const base::DictionaryValue*>(*list_iter),
    164                           iter.key(),
    165                           feature.get()))
    166           continue;
    167 
    168         features->push_back(feature.release());
    169       }
    170 
    171       linked_ptr<ComplexFeature> feature(new ComplexFeature(features.Pass()));
    172       feature->set_name(iter.key());
    173 
    174       features_[iter.key()] = feature;
    175     } else {
    176       LOG(ERROR) << iter.key() << ": Feature description must be dictionary or"
    177                  << " list of dictionaries.";
    178     }
    179   }
    180 }
    181 
    182 BaseFeatureProvider::~BaseFeatureProvider() {
    183 }
    184 
    185 // static
    186 FeatureProvider* BaseFeatureProvider::GetByName(
    187     const std::string& name) {
    188   return g_static.Get().GetFeatures(name);
    189 }
    190 
    191 const std::vector<std::string>& BaseFeatureProvider::GetAllFeatureNames() {
    192   if (feature_names_.empty()) {
    193     for (FeatureMap::const_iterator iter = features_.begin();
    194          iter != features_.end(); ++iter) {
    195       feature_names_.push_back(iter->first);
    196     }
    197   }
    198   return feature_names_;
    199 }
    200 
    201 Feature* BaseFeatureProvider::GetFeature(const std::string& name) {
    202   FeatureMap::iterator iter = features_.find(name);
    203   if (iter != features_.end())
    204     return iter->second.get();
    205   else
    206     return NULL;
    207 }
    208 
    209 Feature* BaseFeatureProvider::GetParent(Feature* feature) {
    210   CHECK(feature);
    211   if (feature->no_parent())
    212     return NULL;
    213 
    214   std::vector<std::string> split;
    215   base::SplitString(feature->name(), '.', &split);
    216   if (split.size() < 2)
    217     return NULL;
    218   split.pop_back();
    219   return GetFeature(JoinString(split, '.'));
    220 }
    221 
    222 } // namespace extensions
    223