Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(591)

Side by Side Diff: chrome/common/extensions/matcher/url_matcher_factory.cc

Issue 12092096: Move c/c/extensions/matcher/ to top level extension dir (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: TOT Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/matcher/url_matcher_factory.h"
6
7 #include <algorithm>
8 #include <cctype>
9
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/stringprintf.h"
13 #include "base/values.h"
14 #include "chrome/common/extensions/matcher/url_matcher_constants.h"
15 #include "chrome/common/extensions/matcher/url_matcher_helpers.h"
16 #include "extensions/common/error_utils.h"
17 #include "third_party/re2/re2/re2.h"
18
19 namespace helpers = extensions::url_matcher_helpers;
20 namespace keys = extensions::url_matcher_constants;
21
22 namespace {
23 // Error messages:
24 const char kInvalidPortRanges[] = "Invalid port ranges in UrlFilter.";
25 const char kVectorOfStringsExpected[] =
26 "UrlFilter attribute '*' expected a vector of strings as parameter.";
27 const char kUnknownURLFilterAttribute[] =
28 "Unknown attribute '*' in UrlFilter.";
29 const char kAttributeExpectedString[] =
30 "UrlFilter attribute '*' expected a string value.";
31 const char kUnparseableRegexString[] =
32 "Could not parse regular expression '*': *";
33 const char kLowerCaseExpected[] = "* values need to be in lower case.";
34
35 // Registry for all factory methods of extensions::URLMatcherConditionFactory
36 // that allows translating string literals from the extension API into
37 // the corresponding factory method to be called.
38 class URLMatcherConditionFactoryMethods {
39 public:
40 URLMatcherConditionFactoryMethods() {
41 typedef extensions::URLMatcherConditionFactory F;
42 factory_methods_[keys::kHostContainsKey] = &F::CreateHostContainsCondition;
43 factory_methods_[keys::kHostEqualsKey] = &F::CreateHostEqualsCondition;
44 factory_methods_[keys::kHostPrefixKey] = &F::CreateHostPrefixCondition;
45 factory_methods_[keys::kHostSuffixKey] = &F::CreateHostSuffixCondition;
46 factory_methods_[keys::kPathContainsKey] = &F::CreatePathContainsCondition;
47 factory_methods_[keys::kPathEqualsKey] = &F::CreatePathEqualsCondition;
48 factory_methods_[keys::kPathPrefixKey] = &F::CreatePathPrefixCondition;
49 factory_methods_[keys::kPathSuffixKey] = &F::CreatePathSuffixCondition;
50 factory_methods_[keys::kQueryContainsKey] =
51 &F::CreateQueryContainsCondition;
52 factory_methods_[keys::kQueryEqualsKey] = &F::CreateQueryEqualsCondition;
53 factory_methods_[keys::kQueryPrefixKey] = &F::CreateQueryPrefixCondition;
54 factory_methods_[keys::kQuerySuffixKey] = &F::CreateQuerySuffixCondition;
55 factory_methods_[keys::kURLContainsKey] = &F::CreateURLContainsCondition;
56 factory_methods_[keys::kURLEqualsKey] = &F::CreateURLEqualsCondition;
57 factory_methods_[keys::kURLPrefixKey] = &F::CreateURLPrefixCondition;
58 factory_methods_[keys::kURLSuffixKey] = &F::CreateURLSuffixCondition;
59 factory_methods_[keys::kURLMatchesKey] = &F::CreateURLMatchesCondition;
60 }
61
62 // Returns whether a factory method for the specified |pattern_type| (e.g.
63 // "host_suffix") is known.
64 bool Contains(const std::string& pattern_type) const {
65 return factory_methods_.find(pattern_type) != factory_methods_.end();
66 }
67
68 // Creates a URLMatcherCondition instance from |url_matcher_condition_factory|
69 // of the given |pattern_type| (e.g. "host_suffix") for the given
70 // |pattern_value| (e.g. "example.com").
71 // The |pattern_type| needs to be known to this class (see Contains()) or
72 // a CHECK is triggered.
73 extensions::URLMatcherCondition Call(
74 extensions::URLMatcherConditionFactory* url_matcher_condition_factory,
75 const std::string& pattern_type,
76 const std::string& pattern_value) const {
77 FactoryMethods::const_iterator i = factory_methods_.find(pattern_type);
78 CHECK(i != factory_methods_.end());
79 const FactoryMethod& method = i->second;
80 return (url_matcher_condition_factory->*method)(pattern_value);
81 }
82
83 private:
84 typedef extensions::URLMatcherCondition
85 (extensions::URLMatcherConditionFactory::* FactoryMethod)
86 (const std::string& prefix);
87 typedef std::map<std::string, FactoryMethod> FactoryMethods;
88
89 FactoryMethods factory_methods_;
90
91 DISALLOW_COPY_AND_ASSIGN(URLMatcherConditionFactoryMethods);
92 };
93
94 static base::LazyInstance<URLMatcherConditionFactoryMethods>
95 g_url_matcher_condition_factory_methods = LAZY_INSTANCE_INITIALIZER;
96
97 } // namespace
98
99 namespace extensions {
100
101 // static
102 scoped_refptr<URLMatcherConditionSet>
103 URLMatcherFactory::CreateFromURLFilterDictionary(
104 URLMatcherConditionFactory* url_matcher_condition_factory,
105 const base::DictionaryValue* url_filter_dict,
106 URLMatcherConditionSet::ID id,
107 std::string* error) {
108 scoped_ptr<URLMatcherSchemeFilter> url_matcher_schema_filter;
109 scoped_ptr<URLMatcherPortFilter> url_matcher_port_filter;
110 URLMatcherConditionSet::Conditions url_matcher_conditions;
111
112 for (base::DictionaryValue::Iterator iter(*url_filter_dict);
113 iter.HasNext(); iter.Advance()) {
114 const std::string& condition_attribute_name = iter.key();
115 const Value& condition_attribute_value = iter.value();
116 if (IsURLMatcherConditionAttribute(condition_attribute_name)) {
117 // Handle {host, path, ...}{Prefix, Suffix, Contains, Equals}.
118 URLMatcherCondition url_matcher_condition =
119 CreateURLMatcherCondition(
120 url_matcher_condition_factory,
121 condition_attribute_name,
122 &condition_attribute_value,
123 error);
124 if (!error->empty())
125 return scoped_refptr<URLMatcherConditionSet>(NULL);
126 url_matcher_conditions.insert(url_matcher_condition);
127 } else if (condition_attribute_name == keys::kSchemesKey) {
128 // Handle scheme.
129 url_matcher_schema_filter = CreateURLMatcherScheme(
130 &condition_attribute_value, error);
131 if (!error->empty())
132 return scoped_refptr<URLMatcherConditionSet>(NULL);
133 } else if (condition_attribute_name == keys::kPortsKey) {
134 // Handle ports.
135 url_matcher_port_filter = CreateURLMatcherPorts(
136 &condition_attribute_value, error);
137 if (!error->empty())
138 return scoped_refptr<URLMatcherConditionSet>(NULL);
139 } else {
140 // Handle unknown attributes.
141 *error = ErrorUtils::FormatErrorMessage(
142 kUnknownURLFilterAttribute,
143 condition_attribute_name);
144 return scoped_refptr<URLMatcherConditionSet>(NULL);
145 }
146 }
147
148 // As the URL is the preliminary matching criterion that triggers the tests
149 // for the remaining condition attributes, we insert an empty URL match if
150 // no other url match conditions were specified. Such an empty URL is always
151 // matched.
152 if (url_matcher_conditions.empty()) {
153 url_matcher_conditions.insert(
154 url_matcher_condition_factory->CreateHostPrefixCondition(""));
155 }
156
157 scoped_refptr<URLMatcherConditionSet> url_matcher_condition_set(
158 new URLMatcherConditionSet(id, url_matcher_conditions,
159 url_matcher_schema_filter.Pass(), url_matcher_port_filter.Pass()));
160 return url_matcher_condition_set;
161 }
162
163 // static
164 bool URLMatcherFactory::IsURLMatcherConditionAttribute(
165 const std::string& condition_attribute_name) {
166 return g_url_matcher_condition_factory_methods.Get().Contains(
167 condition_attribute_name);
168 }
169
170 namespace {
171
172 // Returns true if some alphabetic characters in this string are upper case.
173 bool ContainsUpperCase(const std::string& str) {
174 return std::find_if(str.begin(), str.end(), ::isupper) != str.end();
175 }
176
177 } // namespace
178
179 // static
180 URLMatcherCondition URLMatcherFactory::CreateURLMatcherCondition(
181 URLMatcherConditionFactory* url_matcher_condition_factory,
182 const std::string& condition_attribute_name,
183 const base::Value* value,
184 std::string* error) {
185 std::string str_value;
186 if (!value->GetAsString(&str_value)) {
187 *error = ErrorUtils::FormatErrorMessage(kAttributeExpectedString,
188 condition_attribute_name);
189 return URLMatcherCondition();
190 }
191 if (condition_attribute_name == keys::kHostContainsKey ||
192 condition_attribute_name == keys::kHostPrefixKey ||
193 condition_attribute_name == keys::kHostSuffixKey ||
194 condition_attribute_name == keys::kHostEqualsKey) {
195 if (ContainsUpperCase(str_value)) {
196 *error = ErrorUtils::FormatErrorMessage(kLowerCaseExpected,
197 "Host");
198 return URLMatcherCondition();
199 }
200 }
201
202 // Test regular expressions for validity.
203 if (condition_attribute_name == keys::kURLMatchesKey) {
204 re2::RE2 regex(str_value);
205 if (!regex.ok()) {
206 *error = ErrorUtils::FormatErrorMessage(kUnparseableRegexString,
207 str_value, regex.error());
208 return URLMatcherCondition();
209 }
210 }
211 return g_url_matcher_condition_factory_methods.Get().Call(
212 url_matcher_condition_factory, condition_attribute_name, str_value);
213 }
214
215 // static
216 scoped_ptr<URLMatcherSchemeFilter> URLMatcherFactory::CreateURLMatcherScheme(
217 const base::Value* value,
218 std::string* error) {
219 std::vector<std::string> schemas;
220 if (!helpers::GetAsStringVector(value, &schemas)) {
221 *error = ErrorUtils::FormatErrorMessage(kVectorOfStringsExpected,
222 keys::kSchemesKey);
223 return scoped_ptr<URLMatcherSchemeFilter>(NULL);
224 }
225 for (std::vector<std::string>::const_iterator it = schemas.begin();
226 it != schemas.end(); ++it) {
227 if (ContainsUpperCase(*it)) {
228 *error = ErrorUtils::FormatErrorMessage(kLowerCaseExpected,
229 "Scheme");
230 return scoped_ptr<URLMatcherSchemeFilter>(NULL);
231 }
232 }
233 return scoped_ptr<URLMatcherSchemeFilter>(
234 new URLMatcherSchemeFilter(schemas));
235 }
236
237 // static
238 scoped_ptr<URLMatcherPortFilter> URLMatcherFactory::CreateURLMatcherPorts(
239 const base::Value* value,
240 std::string* error) {
241 std::vector<URLMatcherPortFilter::Range> ranges;
242 const base::ListValue* value_list = NULL;
243 if (!value->GetAsList(&value_list)) {
244 *error = kInvalidPortRanges;
245 return scoped_ptr<URLMatcherPortFilter>(NULL);
246 }
247
248 for (ListValue::const_iterator i = value_list->begin();
249 i != value_list->end(); ++i) {
250 Value* entry = *i;
251 int port = 0;
252 base::ListValue* range = NULL;
253 if (entry->GetAsInteger(&port)) {
254 ranges.push_back(URLMatcherPortFilter::CreateRange(port));
255 } else if (entry->GetAsList(&range)) {
256 int from = 0, to = 0;
257 if (range->GetSize() != 2u ||
258 !range->GetInteger(0, &from) ||
259 !range->GetInteger(1, &to)) {
260 *error = kInvalidPortRanges;
261 return scoped_ptr<URLMatcherPortFilter>(NULL);
262 }
263 ranges.push_back(URLMatcherPortFilter::CreateRange(from, to));
264 } else {
265 *error = kInvalidPortRanges;
266 return scoped_ptr<URLMatcherPortFilter>(NULL);
267 }
268 }
269
270 return scoped_ptr<URLMatcherPortFilter>(new URLMatcherPortFilter(ranges));
271 }
272
273 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698