| Index: chrome/common/extensions/features/base_feature_provider.cc
|
| diff --git a/chrome/common/extensions/features/base_feature_provider.cc b/chrome/common/extensions/features/base_feature_provider.cc
|
| index 285426d147d108f684711b6ef13a51a177ddc7e8..4d4d06d0900d30201f6e93e57d4b384e4c4edf70 100644
|
| --- a/chrome/common/extensions/features/base_feature_provider.cc
|
| +++ b/chrome/common/extensions/features/base_feature_provider.cc
|
| @@ -4,8 +4,12 @@
|
|
|
| #include "chrome/common/extensions/features/base_feature_provider.h"
|
|
|
| +#include <stack>
|
| +
|
| #include "base/json/json_reader.h"
|
| #include "base/lazy_instance.h"
|
| +#include "base/strings/string_split.h"
|
| +#include "base/strings/string_util.h"
|
| #include "chrome/common/extensions/features/api_feature.h"
|
| #include "chrome/common/extensions/features/complex_feature.h"
|
| #include "chrome/common/extensions/features/manifest_feature.h"
|
| @@ -36,7 +40,11 @@ class LazyFeatureProvider : public FeatureProvider {
|
| return GetBaseFeatureProvider()->GetFeature(name);
|
| }
|
|
|
| - virtual std::set<std::string> GetAllFeatureNames() OVERRIDE {
|
| + virtual Feature* GetParent(Feature* feature) OVERRIDE {
|
| + return GetBaseFeatureProvider()->GetParent(feature);
|
| + }
|
| +
|
| + virtual const std::vector<std::string>& GetAllFeatureNames() OVERRIDE {
|
| return GetBaseFeatureProvider()->GetAllFeatureNames();
|
| }
|
|
|
| @@ -125,9 +133,42 @@ BaseFeatureProvider::BaseFeatureProvider(const DictionaryValue& root,
|
| if (iter.value().GetType() == Value::TYPE_DICTIONARY) {
|
| linked_ptr<SimpleFeature> feature((*factory_)());
|
|
|
| - if (!ParseFeature(static_cast<const DictionaryValue*>(&iter.value()),
|
| - iter.key(),
|
| - feature.get()))
|
| + std::vector<std::string> split;
|
| + base::SplitString(iter.key(), '.', &split);
|
| +
|
| + // Push parent features on the stack, starting with the current feature.
|
| + // If one of the features has "noparent" set, stop pushing features on
|
| + // the stack. The features will then be parsed in order, starting with
|
| + // the farthest parent that is either top level or has "noparent" set.
|
| + std::stack<std::pair<std::string, const DictionaryValue*> > parse_stack;
|
| + while (!split.empty()) {
|
| + std::string parent_name = JoinString(split, '.');
|
| + split.pop_back();
|
| + if (root.HasKey(parent_name)) {
|
| + const DictionaryValue* parent = NULL;
|
| + CHECK(root.GetDictionaryWithoutPathExpansion(parent_name, &parent));
|
| + parse_stack.push(std::make_pair(parent_name, parent));
|
| + bool no_parent = false;
|
| + parent->GetBoolean("noparent", &no_parent);
|
| + if (no_parent)
|
| + break;
|
| + }
|
| + }
|
| +
|
| + CHECK(!parse_stack.empty());
|
| + // Parse all parent features.
|
| + bool parse_error = false;
|
| + while (!parse_stack.empty()) {
|
| + if (!ParseFeature(parse_stack.top().second,
|
| + parse_stack.top().first,
|
| + feature.get())) {
|
| + parse_error = true;
|
| + break;
|
| + }
|
| + parse_stack.pop();
|
| + }
|
| +
|
| + if (parse_error)
|
| continue;
|
|
|
| features_[iter.key()] = feature;
|
| @@ -176,13 +217,14 @@ FeatureProvider* BaseFeatureProvider::GetByName(
|
| return g_static.Get().LazyGetFeatures(name);
|
| }
|
|
|
| -std::set<std::string> BaseFeatureProvider::GetAllFeatureNames() {
|
| - std::set<std::string> result;
|
| - for (FeatureMap::const_iterator iter = features_.begin();
|
| - iter != features_.end(); ++iter) {
|
| - result.insert(iter->first);
|
| +const std::vector<std::string>& BaseFeatureProvider::GetAllFeatureNames() {
|
| + if (feature_names_.empty()) {
|
| + for (FeatureMap::const_iterator iter = features_.begin();
|
| + iter != features_.end(); ++iter) {
|
| + feature_names_.push_back(iter->first);
|
| + }
|
| }
|
| - return result;
|
| + return feature_names_;
|
| }
|
|
|
| Feature* BaseFeatureProvider::GetFeature(const std::string& name) {
|
| @@ -193,4 +235,17 @@ Feature* BaseFeatureProvider::GetFeature(const std::string& name) {
|
| return NULL;
|
| }
|
|
|
| -} // namespace
|
| +Feature* BaseFeatureProvider::GetParent(Feature* feature) {
|
| + CHECK(feature);
|
| + if (feature->no_parent())
|
| + return NULL;
|
| +
|
| + std::vector<std::string> split;
|
| + base::SplitString(feature->name(), '.', &split);
|
| + if (split.size() < 2)
|
| + return NULL;
|
| + split.pop_back();
|
| + return GetFeature(JoinString(split, '.'));
|
| +}
|
| +
|
| +} // namespace extensions
|
|
|