OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "extensions/common/features/base_feature_provider.h" | 5 #include "extensions/common/features/base_feature_provider.h" |
6 | 6 |
7 #include <stddef.h> | |
8 | |
9 #include <stack> | |
10 #include <utility> | |
11 | |
12 #include "base/strings/string_split.h" | 7 #include "base/strings/string_split.h" |
13 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
14 #include "base/values.h" | 9 #include "extensions/common/features/feature.h" |
15 #include "extensions/common/extensions_client.h" | |
16 #include "extensions/common/features/complex_feature.h" | |
17 #include "extensions/common/features/simple_feature.h" | |
18 | 10 |
19 namespace extensions { | 11 namespace extensions { |
20 | 12 |
21 namespace { | 13 BaseFeatureProvider::BaseFeatureProvider() {} |
22 | 14 BaseFeatureProvider::~BaseFeatureProvider() {} |
23 bool IsNocompile(const base::Value& value) { | |
24 bool nocompile = false; | |
25 const base::DictionaryValue* as_dict = nullptr; | |
26 if (value.GetAsDictionary(&as_dict)) { | |
27 as_dict->GetBoolean("nocompile", &nocompile); | |
28 } else { | |
29 // "nocompile" is not supported for any other feature type. | |
30 } | |
31 return nocompile; | |
32 } | |
33 | |
34 bool ParseFeature(const base::DictionaryValue* value, | |
35 const std::string& name, | |
36 SimpleFeature* feature) { | |
37 feature->set_name(name); | |
38 std::string error = feature->Parse(value); | |
39 if (!error.empty()) | |
40 LOG(ERROR) << error; | |
41 return error.empty(); | |
42 } | |
43 | |
44 } // namespace | |
45 | |
46 BaseFeatureProvider::BaseFeatureProvider(const base::DictionaryValue& root, | |
47 FeatureFactory factory) | |
48 : factory_(factory) { | |
49 for (base::DictionaryValue::Iterator iter(root); !iter.IsAtEnd(); | |
50 iter.Advance()) { | |
51 if (IsNocompile(iter.value())) { | |
52 continue; | |
53 } | |
54 | |
55 if (iter.value().GetType() == base::Value::TYPE_DICTIONARY) { | |
56 std::unique_ptr<SimpleFeature> feature((*factory_)()); | |
57 | |
58 std::vector<std::string> split = base::SplitString( | |
59 iter.key(), ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
60 | |
61 // Push parent features on the stack, starting with the current feature. | |
62 // If one of the features has "noparent" set, stop pushing features on | |
63 // the stack. The features will then be parsed in order, starting with | |
64 // the farthest parent that is either top level or has "noparent" set. | |
65 std::stack<std::pair<std::string, const base::DictionaryValue*> > | |
66 parse_stack; | |
67 while (!split.empty()) { | |
68 std::string parent_name = base::JoinString(split, "."); | |
69 split.pop_back(); | |
70 if (root.HasKey(parent_name)) { | |
71 const base::DictionaryValue* parent = nullptr; | |
72 if (!root.GetDictionaryWithoutPathExpansion(parent_name, &parent)) { | |
73 // If the parent is a complex feature, find the parent with the | |
74 // 'default_parent' flag. | |
75 const base::ListValue* parent_list = nullptr; | |
76 CHECK(root.GetListWithoutPathExpansion(parent_name, &parent_list)); | |
77 for (size_t i = 0; i < parent_list->GetSize(); ++i) { | |
78 CHECK(parent_list->GetDictionary(i, &parent)); | |
79 if (parent->HasKey("default_parent")) | |
80 break; | |
81 parent = nullptr; | |
82 } | |
83 CHECK(parent) << parent_name << " must declare one of its features" | |
84 << " the default parent, with {\"default_parent\": true}."; | |
85 } | |
86 parse_stack.push(std::make_pair(parent_name, parent)); | |
87 bool no_parent = false; | |
88 parent->GetBoolean("noparent", &no_parent); | |
89 if (no_parent) | |
90 break; | |
91 } | |
92 } | |
93 | |
94 CHECK(!parse_stack.empty()); | |
95 // Parse all parent features. | |
96 bool parse_error = false; | |
97 while (!parse_stack.empty()) { | |
98 if (!ParseFeature(parse_stack.top().second, | |
99 parse_stack.top().first, | |
100 feature.get())) { | |
101 parse_error = true; | |
102 break; | |
103 } | |
104 parse_stack.pop(); | |
105 } | |
106 | |
107 if (parse_error) | |
108 continue; | |
109 | |
110 features_[iter.key()] = std::move(feature); | |
111 } else if (iter.value().GetType() == base::Value::TYPE_LIST) { | |
112 // This is a complex feature. | |
113 const base::ListValue* list = | |
114 static_cast<const base::ListValue*>(&iter.value()); | |
115 CHECK_GT(list->GetSize(), 0UL); | |
116 | |
117 std::unique_ptr<ComplexFeature::FeatureList> features( | |
118 new ComplexFeature::FeatureList()); | |
119 | |
120 // Parse and add all SimpleFeatures from the list. | |
121 for (const auto& entry : *list) { | |
122 base::DictionaryValue* dict; | |
123 if (!entry->GetAsDictionary(&dict)) { | |
124 LOG(ERROR) << iter.key() << ": Feature rules must be dictionaries."; | |
125 continue; | |
126 } | |
127 | |
128 std::unique_ptr<SimpleFeature> feature((*factory_)()); | |
129 if (!ParseFeature(dict, iter.key(), feature.get())) | |
130 continue; | |
131 | |
132 features->push_back(std::move(feature)); | |
133 } | |
134 | |
135 std::unique_ptr<ComplexFeature> feature( | |
136 new ComplexFeature(std::move(features))); | |
137 feature->set_name(iter.key()); | |
138 | |
139 features_[iter.key()] = std::move(feature); | |
140 } else { | |
141 LOG(ERROR) << iter.key() << ": Feature description must be dictionary or" | |
142 << " list of dictionaries."; | |
143 } | |
144 } | |
145 } | |
146 | |
147 BaseFeatureProvider::~BaseFeatureProvider() { | |
148 } | |
149 | 15 |
150 const FeatureMap& BaseFeatureProvider::GetAllFeatures() const { | 16 const FeatureMap& BaseFeatureProvider::GetAllFeatures() const { |
151 return features_; | 17 return features_; |
152 } | 18 } |
153 | 19 |
154 Feature* BaseFeatureProvider::GetFeature(const std::string& name) const { | 20 Feature* BaseFeatureProvider::GetFeature(const std::string& name) const { |
155 FeatureMap::const_iterator iter = features_.find(name); | 21 FeatureMap::const_iterator iter = features_.find(name); |
156 if (iter != features_.end()) | 22 if (iter != features_.end()) |
157 return iter->second.get(); | 23 return iter->second.get(); |
158 else | 24 else |
(...skipping 28 matching lines...) Expand all Loading... |
187 std::vector<Feature*> result; | 53 std::vector<Feature*> result; |
188 result.reserve(std::distance(first_child, after_children)); | 54 result.reserve(std::distance(first_child, after_children)); |
189 for (FeatureMap::const_iterator it = first_child; it != after_children; | 55 for (FeatureMap::const_iterator it = first_child; it != after_children; |
190 ++it) { | 56 ++it) { |
191 result.push_back(it->second.get()); | 57 result.push_back(it->second.get()); |
192 } | 58 } |
193 return result; | 59 return result; |
194 } | 60 } |
195 | 61 |
196 } // namespace extensions | 62 } // namespace extensions |
OLD | NEW |