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

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: Created 8 years, 9 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/logging.h"
8 #include "base/stringprintf.h"
9 #include "base/values.h"
10 #include "chrome/browser/extensions/api/declarative_webrequest/request_stages.h"
11 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condit ion_attribute.h"
12 #include "net/url_request/url_request.h"
13
14 namespace {
15 static extensions::URLMatcherConditionSet::ID g_next_id = 0;
16
17 // TODO(battre): improve error messaging to give more meaningful messages
18 // to the extension developer.
19 // Error messages:
20 const char kExpectedDictionary[] = "A condition has to be a dictionary.";
21 const char kConditionWithoutInstanceType[] = "A condition had no instanceType";
22 const char kExpectedOtherConditionType[] = "Expected a condition of type "
23 "experimental.webRequest.RequestMatcher";
24 const char kUnknownConditionAttribute[] = "UnKnown condition attribute '%s'";
25 const char kConditionExpectedString[] =
26 "Condition '%s' expected a string value";
27
28 // String literals from the JavaScript API:
29 const char kRequestMatcher[] = "experimental.webRequest.RequestMatcher";
30 const char kInstanceType[] = "instanceType";
31
32 const char kHostContainsKey[] = "host_contains";
33 const char kHostEqualsKey[] = "host_equals";
34 const char kHostPrefixKey[] = "host_prefix";
35 const char kHostSuffixKey[] = "host_suffix";
36 const char kHostSuffixPathPrefixKey[] = "host_suffix_path_prefix";
37 const char kPathContainsKey[] = "path_contains";
38 const char kPathEqualsKey[] = "path_equals";
39 const char kPathPrefixKey[] = "path_prefix";
40 const char kPathSuffixKey[] = "path_suffix";
41 const char kQueryContainsKey[] = "query_contains";
42 const char kQueryEqualsKey[] = "query_equals";
43 const char kQueryPrefixKey[] = "query_prefix";
44 const char kQuerySuffixKey[] = "query_suffix";
45 const char kURLContainsKey[] = "url_contains";
46 const char kURLEqualsKey[] = "url_equals";
47 const char kURLPrefixKey[] = "url_prefix";
48 const char kURLSuffixKey[] = "url_suffix";
49
50 // This is an array of all criteria that may be evaluated on the URL.
51 // These MUST appear in alphabetical order in order to allow a binary search
52 // on them.
53 const char* kAllPathAttributes[] = {
Matt Perry 2012/03/22 01:34:43 Putting these in a global map would remove the alp
battre 2012/03/26 18:35:51 Done.
54 kHostContainsKey,
55 kHostEqualsKey,
56 kHostPrefixKey,
57 kHostSuffixKey,
58 // kHostSuffixPathPrefixKey, // TODO(battre): support this.
59 kPathContainsKey,
60 kPathEqualsKey,
61 kPathPrefixKey,
62 kPathSuffixKey,
63 kQueryContainsKey,
64 kQueryEqualsKey,
65 kQueryPrefixKey,
66 kQuerySuffixKey,
67 kURLContainsKey,
68 kURLEqualsKey,
69 kURLPrefixKey,
70 kURLSuffixKey
71 };
72
73 } // namespace
74
75 namespace extensions {
76 namespace declarative_webrequest {
77
78 WebRequestCondition::WebRequestCondition(
79 const URLMatcherConditionSet& url_matcher_conditions,
80 const WebRequestConditionAttributes& condition_attributes)
81 : url_matcher_conditions_(url_matcher_conditions),
82 condition_attributes_(condition_attributes) {}
83
84 WebRequestCondition::~WebRequestCondition() {}
85
86 bool WebRequestCondition::IsFulfilled(
87 URLMatcherConditionSet::ID url_match,
88 net::URLRequest* request) const {
89 if (url_match != url_matcher_condition_set_id())
90 return false;
91
92 // All condition attributes must be fulfilled for a fulfilled condition.
93 for (WebRequestConditionAttributes::const_iterator i =
94 condition_attributes_.begin(); i != condition_attributes_.end(); ++i) {
95 if (!(*i)->IsFulfilled(request))
96 return false;
97 }
98 return true;
99 }
100
101 void WebRequestCondition::AppendURLMatcherConditionSet(
102 std::vector<URLMatcherConditionSet>* condition_sets) const {
103 condition_sets->push_back(url_matcher_conditions_);
104 }
105
106 WebRequestConditionCollection::WebRequestConditionCollection(
107 const std::vector<linked_ptr<WebRequestCondition> >& conditions)
108 : conditions_(conditions) {
109 for (Collection::iterator i = conditions_.begin(); i != conditions_.end();
110 ++i) {
111 URLMatcherConditionSet::ID trigger_id =
112 (*i)->url_matcher_condition_set_id();
113 match_triggers_[trigger_id] = i->get();
114 }
115 }
116
117 WebRequestConditionCollection::~WebRequestConditionCollection() {}
118
119 bool WebRequestConditionCollection::IsFulfilled(
120 const std::set<URLMatcherConditionSet::ID>& url_matches,
121 net::URLRequest* request) const {
122 // The URL matcher found all SubstringPattern::ID in |url_matches|.
123 // Let's see whether any of these is the primary SubstringPattern::ID
124 // of a WebRequestCondition.
125 for (std::set<URLMatcherConditionSet::ID>::const_iterator i =
126 url_matches.begin(); i != url_matches.end(); ++i) {
127 MatchTriggers::const_iterator trigger = match_triggers_.find(*i);
128 if (trigger == match_triggers_.end())
129 continue;
130 if (trigger->second->IsFulfilled(*i, request))
Matt Perry 2012/03/22 23:07:25 Is it necessary to pass in the set ID? If the cond
battre 2012/03/26 18:35:51 Done.
131 return true;
132 }
133 return false;
134 }
135
136 void WebRequestConditionCollection::AppendURLMatcherConditionSets(
137 std::vector<URLMatcherConditionSet>* condition_sets) const {
138 for (Collection::const_iterator i = conditions_.begin();
139 i != conditions_.end(); ++i) {
140 (*i)->AppendURLMatcherConditionSet(condition_sets);
141 }
142 }
143
144 // static
145 scoped_ptr<WebRequestCondition> WebRequestConditionFactory::CreateCondition(
146 URLMatcherConditionFactory* url_matcher_condition_factory,
147 const base::Value& condition,
148 std::string* error) {
149 const base::DictionaryValue* condition_dict = NULL;
150 if (!condition.GetAsDictionary(&condition_dict)) {
151 *error = kExpectedDictionary;
152 return scoped_ptr<WebRequestCondition>(NULL);
153 }
154
155 // Verify that we are dealing with a Condition whose type we understand.
156 std::string instance_type;
157 if (!condition_dict->GetString(kInstanceType, &instance_type)) {
158 *error = kConditionWithoutInstanceType;
159 return scoped_ptr<WebRequestCondition>(NULL);
160 }
161 if (instance_type != kRequestMatcher) {
162 *error = kExpectedOtherConditionType;
163 return scoped_ptr<WebRequestCondition>(NULL);
164 }
165
166 WebRequestConditionAttributes attributes;
167 URLMatcherConditionSet::Conditions url_matcher_conditions;
168 for (base::DictionaryValue::key_iterator key = condition_dict->begin_keys();
Matt Perry 2012/03/22 23:07:25 Give DictionaryValue::Iterator a try, since you ne
battre 2012/03/26 18:35:51 Done.
169 key != condition_dict->end_keys(); ++key) {
170 const std::string& condition_attribute_name = *key;
171 if (condition_attribute_name == kInstanceType)
172 continue;
173 Value* condition_attribute_value = NULL;
174 condition_dict->Get(condition_attribute_name, &condition_attribute_value);
175
176 if (condition_attribute_name == instance_type) {
Matt Perry 2012/03/22 23:07:25 When is this possible?
battre 2012/03/26 18:35:51 This was an error, I meant to compare to kInstance
177 // Skip this.
178 } else if (IsUrlMatcherConditionAttribute(condition_attribute_name)) {
179 URLMatcherCondition url_matcher_condition =
180 CreateURLMatcherCondition(
181 url_matcher_condition_factory,
182 condition_attribute_name,
183 condition_attribute_value,
184 error);
185 if (!error->empty())
186 return scoped_ptr<WebRequestCondition>(NULL);
187 url_matcher_conditions.insert(url_matcher_condition);
188 } else if (WebRequestConditionAttributeFactory::IsHandledByThisFactory(
189 condition_attribute_name)) {
190 scoped_ptr<WebRequestConditionAttribute> attribute =
191 WebRequestConditionAttributeFactory::Create(
192 condition_attribute_name,
193 condition_attribute_value,
194 error);
195 if (!error->empty())
196 return scoped_ptr<WebRequestCondition>(NULL);
197 attributes.push_back(make_linked_ptr(attribute.release()));
198 } else {
199 *error = base::StringPrintf(kUnknownConditionAttribute,
200 condition_attribute_name.c_str());
201 return scoped_ptr<WebRequestCondition>(NULL);
202 }
203 }
204
205 // As the URL is the preliminary matching criterion that triggers the tests
206 // for the remaining condition attributes, we insert an empty URL match if
207 // no other url match conditions were specified. Such an empty URL is always
208 // matched.
209 if (url_matcher_conditions.empty()) {
210 url_matcher_conditions.insert(
211 url_matcher_condition_factory->CreateHostPrefixCondition(""));
212 }
213
214 URLMatcherConditionSet url_matcher_condition_set(++g_next_id,
215 url_matcher_conditions);
216 return scoped_ptr<WebRequestCondition>(
217 new WebRequestCondition(url_matcher_condition_set, attributes));
218 }
219
220 // static
221 scoped_ptr<WebRequestConditionCollection>
222 WebRequestConditionFactory::CreateConditionCollection(
223 URLMatcherConditionFactory* url_matcher_condition_factory,
224 const AnyVector& conditions,
225 std::string* error) {
226 std::vector<linked_ptr<WebRequestCondition> > result;
227
228 for (AnyVector::const_iterator i = conditions.begin();
229 i != conditions.end(); ++i) {
230 CHECK(i->get());
231 scoped_ptr<WebRequestCondition> condition =
232 CreateCondition(url_matcher_condition_factory, (*i)->value(), error);
233 if (!error->empty())
234 return scoped_ptr<WebRequestConditionCollection>(NULL);
235 result.push_back(make_linked_ptr(condition.release()));
236 }
237
238 return scoped_ptr<WebRequestConditionCollection>(
239 new WebRequestConditionCollection(result));
240 }
241
242 // static
243 std::vector<std::string> WebRequestConditionFactory::GetAllPathAttributes() {
244 return std::vector<std::string>(
245 kAllPathAttributes, kAllPathAttributes + arraysize(kAllPathAttributes));
246 }
247
248 // static
249 bool WebRequestConditionFactory::IsUrlMatcherConditionAttribute(
250 const std::string& name) {
251 return std::binary_search(kAllPathAttributes,
252 kAllPathAttributes + arraysize(kAllPathAttributes),
253 name);
254 }
255
256 // static
257 URLMatcherCondition WebRequestConditionFactory::CreateURLMatcherCondition(
258 URLMatcherConditionFactory* url_matcher_condition_factory,
259 const std::string& condition_attribute_name,
260 const base::Value* value,
261 std::string* error) {
262
263 std::string str_value;
264 if (!value->GetAsString(&str_value)) {
265 *error = base::StringPrintf(kConditionExpectedString,
266 condition_attribute_name.c_str());
267 return URLMatcherCondition();
268 }
269
270 URLMatcherConditionFactory* factory = url_matcher_condition_factory;
271 if (condition_attribute_name == kHostContainsKey) {
272 return factory->CreateHostContainsCondition(str_value);
273 } else if (condition_attribute_name == kHostEqualsKey) {
274 return factory->CreateHostEqualsCondition(str_value);
275 } else if (condition_attribute_name == kHostPrefixKey) {
276 return factory->CreateHostPrefixCondition(str_value);
277 } else if (condition_attribute_name == kHostSuffixKey) {
278 return factory->CreateHostSuffixCondition(str_value);
279 } else if (condition_attribute_name == kHostSuffixPathPrefixKey) {
280 NOTREACHED(); // Not implemented, yet.
281 } else if (condition_attribute_name == kPathContainsKey) {
282 return factory->CreatePathContainsCondition(str_value);
283 } else if (condition_attribute_name == kPathEqualsKey) {
284 return factory->CreatePathEqualsCondition(str_value);
285 } else if (condition_attribute_name == kPathPrefixKey) {
286 return factory->CreatePathPrefixCondition(str_value);
287 } else if (condition_attribute_name == kPathSuffixKey) {
288 return factory->CreatePathSuffixCondition(str_value);
289 } else if (condition_attribute_name == kQueryContainsKey) {
290 return factory->CreatePathContainsCondition(str_value);
291 } else if (condition_attribute_name == kQueryEqualsKey) {
292 return factory->CreateQueryEqualsCondition(str_value);
293 } else if (condition_attribute_name == kQueryPrefixKey) {
294 return factory->CreateQueryPrefixCondition(str_value);
295 } else if (condition_attribute_name == kQuerySuffixKey) {
296 return factory->CreateQuerySuffixCondition(str_value);
297 } else if (condition_attribute_name == kURLContainsKey) {
298 return factory->CreateURLContainsCondition(str_value);
299 } else if (condition_attribute_name == kURLEqualsKey) {
300 return factory->CreateURLEqualsCondition(str_value);
301 } else if (condition_attribute_name == kURLPrefixKey) {
302 return factory->CreateURLPrefixCondition(str_value);
303 } else if (condition_attribute_name == kURLSuffixKey) {
304 return factory->CreateURLSuffixCondition(str_value);
305 }
306 *error = "Unsupported url matching condition";
307 return URLMatcherCondition();
308 }
309
310 } // namespace declarative_webrequest
311 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698