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

Side by Side Diff: chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.cc

Issue 9820003: Implementation of beginning of Declarative Web Request API backend (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments Created 8 years, 8 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 | Annotate | Revision Log
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/browser/extensions/api/declarative_webrequest/webrequest_condit ion.h"
6
7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
9 #include "base/logging.h"
10 #include "base/stringprintf.h"
11 #include "base/values.h"
12 #include "chrome/browser/extensions/api/declarative_webrequest/request_stages.h"
13 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condit ion_attribute.h"
14 #include "net/url_request/url_request.h"
15
16 namespace {
17 static extensions::URLMatcherConditionSet::ID g_next_id = 0;
18
19 // TODO(battre): improve error messaging to give more meaningful messages
20 // to the extension developer.
21 // Error messages:
22 const char kExpectedDictionary[] = "A condition has to be a dictionary.";
23 const char kConditionWithoutInstanceType[] = "A condition had no instanceType";
24 const char kExpectedOtherConditionType[] = "Expected a condition of type "
25 "experimental.webRequest.RequestMatcher";
26 const char kUnknownConditionAttribute[] = "UnKnown condition attribute '%s'";
27 const char kConditionExpectedString[] =
28 "Condition '%s' expected a string value";
29
30 // String literals from the JavaScript API:
31 const char kRequestMatcher[] = "experimental.webRequest.RequestMatcher";
32 const char kInstanceType[] = "instanceType";
33
34 const char kHostContainsKey[] = "host_contains";
35 const char kHostEqualsKey[] = "host_equals";
36 const char kHostPrefixKey[] = "host_prefix";
37 const char kHostSuffixKey[] = "host_suffix";
38 const char kHostSuffixPathPrefixKey[] = "host_suffix_path_prefix";
39 const char kPathContainsKey[] = "path_contains";
40 const char kPathEqualsKey[] = "path_equals";
41 const char kPathPrefixKey[] = "path_prefix";
42 const char kPathSuffixKey[] = "path_suffix";
43 const char kQueryContainsKey[] = "query_contains";
44 const char kQueryEqualsKey[] = "query_equals";
45 const char kQueryPrefixKey[] = "query_prefix";
46 const char kQuerySuffixKey[] = "query_suffix";
47 const char kURLContainsKey[] = "url_contains";
48 const char kURLEqualsKey[] = "url_equals";
49 const char kURLPrefixKey[] = "url_prefix";
50 const char kURLSuffixKey[] = "url_suffix";
51
52 // Registry for all factory methods of extensions::URLMatcherConditionFactory
53 // that allows translating string literals from the extension API into
54 // the corresponding factory method to be called.
55 class URLMatcherConditionFactoryMethods {
56 public:
57 URLMatcherConditionFactoryMethods() {
58 typedef extensions::URLMatcherConditionFactory F;
59 factory_methods_[kHostContainsKey] = &F::CreateHostContainsCondition;
60 factory_methods_[kHostEqualsKey] = &F::CreateHostEqualsCondition;
61 factory_methods_[kHostPrefixKey] = &F::CreateHostPrefixCondition;
62 factory_methods_[kHostSuffixKey] = &F::CreateHostSuffixCondition;
63 factory_methods_[kPathContainsKey] = &F::CreatePathContainsCondition;
64 factory_methods_[kPathEqualsKey] = &F::CreatePathEqualsCondition;
65 factory_methods_[kPathPrefixKey] = &F::CreatePathPrefixCondition;
66 factory_methods_[kPathSuffixKey] = &F::CreatePathSuffixCondition;
67 factory_methods_[kQueryContainsKey] = &F::CreateQueryContainsCondition;
68 factory_methods_[kQueryEqualsKey] = &F::CreateQueryEqualsCondition;
69 factory_methods_[kQueryPrefixKey] = &F::CreateQueryPrefixCondition;
70 factory_methods_[kQuerySuffixKey] = &F::CreateQuerySuffixCondition;
71 factory_methods_[kURLContainsKey] = &F::CreateURLContainsCondition;
72 factory_methods_[kURLEqualsKey] = &F::CreateURLEqualsCondition;
73 factory_methods_[kURLPrefixKey] = &F::CreateURLPrefixCondition;
74 factory_methods_[kURLSuffixKey] = &F::CreateURLSuffixCondition;
75 }
76
77 // Returns whether a factory method for the specified |pattern_type| (e.g.
78 // "host_suffix") is known.
79 bool Contains(const std::string& pattern_type) const {
80 return factory_methods_.find(pattern_type) != factory_methods_.end();
81 }
82
83 // Creates a URLMatcherCondition instance from |url_matcher_condition_factory|
84 // of the given |pattern_type| (e.g. "host_suffix") for the given
85 // |pattern_value| (e.g. "example.com").
86 // The |pattern_type| needs to be known to this class (see Contains()) or
87 // a CHECK is triggered.
88 extensions::URLMatcherCondition Call(
89 extensions::URLMatcherConditionFactory* url_matcher_condition_factory,
90 const std::string& pattern_type,
91 const std::string& pattern_value) const {
92 FactoryMethods::const_iterator i = factory_methods_.find(pattern_type);
93 CHECK(i != factory_methods_.end());
94 const FactoryMethod& method = i->second;
95 return base::Bind(method,
96 base::Unretained(url_matcher_condition_factory)).Run(pattern_value);
Matt Perry 2012/03/26 20:21:20 You don't need to use Bind to invoke here. The syn
battre 2012/03/26 20:38:10 Done.
97 }
98
99 private:
100 typedef extensions::URLMatcherCondition
101 (extensions::URLMatcherConditionFactory::* FactoryMethod)
102 (const std::string& prefix);
103 typedef std::map<std::string, FactoryMethod> FactoryMethods;
104
105 FactoryMethods factory_methods_;
106
107 DISALLOW_COPY_AND_ASSIGN(URLMatcherConditionFactoryMethods);
108 };
109
110 static base::LazyInstance<URLMatcherConditionFactoryMethods>
111 g_url_matcher_condition_factory_methods = LAZY_INSTANCE_INITIALIZER;
112
113 } // namespace
114
115 namespace extensions {
116
117 //
118 // WebRequestCondition
119 //
120
121 WebRequestCondition::WebRequestCondition(
122 const URLMatcherConditionSet& url_matcher_conditions,
123 const WebRequestConditionAttributes& condition_attributes)
124 : url_matcher_conditions_(url_matcher_conditions),
125 condition_attributes_(condition_attributes) {}
126
127 WebRequestCondition::~WebRequestCondition() {}
128
129 bool WebRequestCondition::IsFulfilled(net::URLRequest* request) const {
130 // All condition attributes must be fulfilled for a fulfilled condition.
131 for (WebRequestConditionAttributes::const_iterator i =
132 condition_attributes_.begin(); i != condition_attributes_.end(); ++i) {
133 if (!(*i)->IsFulfilled(request))
134 return false;
135 }
136 return true;
137 }
138
139 // static
140 scoped_ptr<WebRequestCondition> WebRequestCondition::Create(
141 URLMatcherConditionFactory* url_matcher_condition_factory,
142 const base::Value& condition,
143 std::string* error) {
144 const base::DictionaryValue* condition_dict = NULL;
145 if (!condition.GetAsDictionary(&condition_dict)) {
146 *error = kExpectedDictionary;
147 return scoped_ptr<WebRequestCondition>(NULL);
148 }
149
150 // Verify that we are dealing with a Condition whose type we understand.
151 std::string instance_type;
152 if (!condition_dict->GetString(kInstanceType, &instance_type)) {
153 *error = kConditionWithoutInstanceType;
154 return scoped_ptr<WebRequestCondition>(NULL);
155 }
156 if (instance_type != kRequestMatcher) {
157 *error = kExpectedOtherConditionType;
158 return scoped_ptr<WebRequestCondition>(NULL);
159 }
160
161 WebRequestConditionAttributes attributes;
162 URLMatcherConditionSet::Conditions url_matcher_conditions;
163
164 for (base::DictionaryValue::Iterator iter(*condition_dict);
165 iter.HasNext(); iter.Advance()) {
166 const std::string& condition_attribute_name = iter.key();
167 const Value& condition_attribute_value = iter.value();
168 if (condition_attribute_name == kInstanceType) {
169 // Skip this.
170 } else if (IsURLMatcherConditionAttribute(condition_attribute_name)) {
171 URLMatcherCondition url_matcher_condition =
172 CreateURLMatcherCondition(
173 url_matcher_condition_factory,
174 condition_attribute_name,
175 &condition_attribute_value,
176 error);
177 if (!error->empty())
178 return scoped_ptr<WebRequestCondition>(NULL);
179 url_matcher_conditions.insert(url_matcher_condition);
180 } else if (WebRequestConditionAttribute::IsKnownType(
181 condition_attribute_name)) {
182 scoped_ptr<WebRequestConditionAttribute> attribute =
183 WebRequestConditionAttribute::Create(
184 condition_attribute_name,
185 &condition_attribute_value,
186 error);
187 if (!error->empty())
188 return scoped_ptr<WebRequestCondition>(NULL);
189 attributes.push_back(make_linked_ptr(attribute.release()));
190 } else {
191 *error = base::StringPrintf(kUnknownConditionAttribute,
192 condition_attribute_name.c_str());
193 return scoped_ptr<WebRequestCondition>(NULL);
194 }
195 }
196
197 // As the URL is the preliminary matching criterion that triggers the tests
198 // for the remaining condition attributes, we insert an empty URL match if
199 // no other url match conditions were specified. Such an empty URL is always
200 // matched.
201 if (url_matcher_conditions.empty()) {
202 url_matcher_conditions.insert(
203 url_matcher_condition_factory->CreateHostPrefixCondition(""));
204 }
205
206 URLMatcherConditionSet url_matcher_condition_set(++g_next_id,
207 url_matcher_conditions);
208 return scoped_ptr<WebRequestCondition>(
209 new WebRequestCondition(url_matcher_condition_set, attributes));
210 }
211
212 // static
213 bool WebRequestCondition::IsURLMatcherConditionAttribute(
214 const std::string& condition_attribute_name) {
215 return g_url_matcher_condition_factory_methods.Get().Contains(
216 condition_attribute_name);
217 }
218
219 // static
220 URLMatcherCondition WebRequestCondition::CreateURLMatcherCondition(
221 URLMatcherConditionFactory* url_matcher_condition_factory,
222 const std::string& condition_attribute_name,
223 const base::Value* value,
224 std::string* error) {
225 std::string str_value;
226 if (!value->GetAsString(&str_value)) {
227 *error = base::StringPrintf(kConditionExpectedString,
228 condition_attribute_name.c_str());
229 return URLMatcherCondition();
230 }
231 return g_url_matcher_condition_factory_methods.Get().Call(
232 url_matcher_condition_factory, condition_attribute_name, str_value);
233 }
234
235
236 //
237 // WebRequestConditionCollection
238 //
239
240 WebRequestConditionCollection::WebRequestConditionCollection(
241 const std::vector<linked_ptr<WebRequestCondition> >& conditions)
242 : conditions_(conditions) {
243 for (Collection::iterator i = conditions_.begin(); i != conditions_.end();
244 ++i) {
245 URLMatcherConditionSet::ID trigger_id =
246 (*i)->url_matcher_condition_set_id();
247 match_triggers_[trigger_id] = i->get();
248 }
249 }
250
251 WebRequestConditionCollection::~WebRequestConditionCollection() {}
252
253 bool WebRequestConditionCollection::IsFulfilled(
254 URLMatcherConditionSet::ID url_match,
255 net::URLRequest* request) const {
256 MatchTriggers::const_iterator trigger = match_triggers_.find(url_match);
257 if (trigger == match_triggers_.end())
Matt Perry 2012/03/26 20:21:20 Should this be an error (DCHECK)? The caller knows
battre 2012/03/26 20:38:10 Done.
258 return false;
259 DCHECK_EQ(url_match, trigger->second->url_matcher_condition_set_id());
260 if (trigger->second->IsFulfilled(request))
Matt Perry 2012/03/26 20:21:20 nit: return trigger->second->IsFulfilled(request)
battre 2012/03/26 20:38:10 Done.
261 return true;
262 return false;
263 }
264
265 void WebRequestConditionCollection::AppendURLMatcherConditionSets(
266 std::vector<URLMatcherConditionSet>* condition_sets) const {
267 for (Collection::const_iterator i = conditions_.begin();
268 i != conditions_.end(); ++i) {
269 condition_sets->push_back((*i)->url_matcher_condition_set());
270 }
271 }
272
273 // static
274 scoped_ptr<WebRequestConditionCollection>
275 WebRequestConditionCollection::Create(
276 URLMatcherConditionFactory* url_matcher_condition_factory,
277 const AnyVector& conditions,
278 std::string* error) {
279 std::vector<linked_ptr<WebRequestCondition> > result;
280
281 for (AnyVector::const_iterator i = conditions.begin();
282 i != conditions.end(); ++i) {
283 CHECK(i->get());
284 scoped_ptr<WebRequestCondition> condition =
285 WebRequestCondition::Create(url_matcher_condition_factory,
286 (*i)->value(), error);
287 if (!error->empty())
288 return scoped_ptr<WebRequestConditionCollection>(NULL);
289 result.push_back(make_linked_ptr(condition.release()));
290 }
291
292 return scoped_ptr<WebRequestConditionCollection>(
293 new WebRequestConditionCollection(result));
294 }
295
296 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698