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