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

Side by Side Diff: chrome/browser/extensions/api/declarative/declarative_rule.h

Issue 11572061: Create DeclarativeConditionSet, DeclarativeActionSet, and DeclarativeRule templates (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 //
5 // DeclarativeRule<>, DeclarativeConditionSet<>, and DeclarativeActionSet<>
6 // templates usable with multiple different declarativeFoo systems. These are
7 // templated on the Condition and Action types that define the behavior of a
8 // particular declarative event.
4 9
5 #ifndef CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_RULE_H_ 10 #ifndef CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_DECLARATIVE_RULE_H__
6 #define CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_RULE_H_ 11 #define CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_DECLARATIVE_RULE_H__
7 12
8 #include <list> 13 #include <limits>
9 #include <vector>
10 14
11 #include "base/compiler_specific.h" 15 #include "base/memory/linked_ptr.h"
16 #include "base/memory/scoped_vector.h"
12 #include "base/time.h" 17 #include "base/time.h"
13 #include "chrome/browser/extensions/api/declarative/rules_registry.h" 18 #include "chrome/common/extensions/api/events.h"
14 #include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h" 19 #include "chrome/common/extensions/matcher/url_matcher.h"
15 20
16 class ExtensionInfoMap; 21 namespace base {
17 class WebRequestPermissions; 22 class Time;
18
19 namespace extensions {
20 class Extension;
21 class URLMatcherConditionFactory;
22 class WebRequestActionSet;
23 class WebRequestConditionSet;
24 }
25
26 namespace extension_web_request_api_helpers {
27 struct EventResponseDelta;
28 }
29
30 namespace net {
31 class HttpResponseHeaders;
32 class URLRequest;
33 } 23 }
34 24
35 namespace extensions { 25 namespace extensions {
36 26
37 typedef linked_ptr<extension_web_request_api_helpers::EventResponseDelta> 27 // This class stores a set of conditions that may be part of a DeclarativeRule.
38 LinkedPtrEventResponseDelta; 28 // If any condition is fulfilled, the Actions of the DeclarativeRule can be
29 // triggered.
30 template<typename ConditionT>
battre 2012/12/17 11:46:06 The problem I see with template parameters is that
Jeffrey Yasskin 2012/12/19 08:23:06 Done.
31 class DeclarativeConditionSet {
32 public:
33 typedef std::vector<linked_ptr<json_schema_compiler::any::Any> > AnyVector;
34 typedef std::vector<linked_ptr<ConditionT> > Conditions;
35 typedef typename Conditions::const_iterator const_iterator;
39 36
40 // Representation of a rule of the declarative Web Request API 37 explicit DeclarativeConditionSet(const Conditions& conditions);
41 class WebRequestRule { 38
39 // Factory method that creates an WebRequestConditionSet according to the JSON
40 // array |conditions| passed by the extension API.
41 // Sets |error| and returns NULL in case of an error.
42 static scoped_ptr<DeclarativeConditionSet> Create(
43 URLMatcherConditionFactory* url_matcher_condition_factory,
44 const AnyVector& conditions,
45 std::string* error);
46
47 const Conditions& conditions() const {
48 return conditions_;
49 }
50
51 const_iterator begin() const { return conditions_.begin(); }
52 const_iterator end() const { return conditions_.end(); }
53
54 // Returns whether any condition in the condition set is fulfilled
55 // based on a match |url_match| and the value of |request_data.request|.
56 // This function should be called for each URLMatcherConditionSet::ID
57 // that was found by the URLMatcher to ensure that the each trigger in
58 // |match_triggers_| is found.
59 bool IsFulfilled(
60 URLMatcherConditionSet::ID url_match,
battre 2012/12/17 11:46:06 This one will break with vabr's change: He is impl
Jeffrey Yasskin 2012/12/18 02:44:26 I've commented on https://codereview.chromium.org/
61 const typename ConditionT::MatchData& match_data) const;
62
63 // Appends the URLMatcherConditionSet from all conditions to |condition_sets|.
64 void GetURLMatcherConditionSets(
65 URLMatcherConditionSet::Vector* condition_sets) const;
66
67 private:
68 Conditions conditions_;
69
70 typedef std::map<URLMatcherConditionSet::ID, ConditionT*>
71 MatchTriggers;
72 MatchTriggers match_triggers_;
73
74 DISALLOW_COPY_AND_ASSIGN(DeclarativeConditionSet);
75 };
76
77 // Immutable container for multiple actions.
78 //
79 // TODO(battre): As DeclarativeActionSet can become the single owner of all
80 // actions, we can optimize here by making some of them singletons (e.g. Cancel
81 // actions).
82 template<typename ActionT>
83 class DeclarativeActionSet {
84 public:
85 typedef std::vector<linked_ptr<json_schema_compiler::any::Any> > AnyVector;
86 typedef std::vector<linked_ptr<ActionT> > Actions;
87
88 explicit DeclarativeActionSet(const Actions& actions);
89
90 // Factory method that instantiates a DeclarativeActionSet according to
91 // |actions| which represents the array of actions received from the
92 // extension API.
93 static scoped_ptr<DeclarativeActionSet> Create(const AnyVector& actions,
94 std::string* error,
95 bool* bad_message);
96
97 // Rules call this method when their conditions are fulfilled.
98 void Apply(const std::string& extension_id,
99 const base::Time& extension_install_time,
100 const typename ActionT::ApplyInfo& apply_info) const;
battre 2012/12/17 11:46:06 const apply_info?
Jeffrey Yasskin 2012/12/18 02:44:26 It's already a const reference. What do you mean?
battre 2012/12/18 08:38:49 That's my point. Why is it const. This is the vari
Jeffrey Yasskin 2012/12/19 08:23:06 It was const because it holds a non-const pointer
101
102 // Rules call this method when they have stateful conditions, and those
103 // conditions stop being fulfilled. Rules with event-based conditions (e.g. a
104 // network request happened) will never Revert() an action.
105 void Revert(const std::string& extension_id,
106 const base::Time& extension_install_time,
107 const typename ActionT::ApplyInfo& apply_info) const;
battre 2012/12/17 11:46:06 const apply_info?
Jeffrey Yasskin 2012/12/19 08:23:06 Done.
108
109 // Returns the minimum priority of rules that may be evaluated after
110 // this rule. Defaults to MIN_INT.
111 int GetMinimumPriority() const;
112
113 const Actions& actions() const { return actions_; }
114
115 private:
116 Actions actions_;
117
118 DISALLOW_COPY_AND_ASSIGN(DeclarativeActionSet);
119 };
120
121 template<typename ConditionT, typename ActionT>
122 class DeclarativeRule {
Jeffrey Yasskin 2012/12/19 08:23:06 What? No complaint that I completely forgot a comm
42 public: 123 public:
43 typedef std::string ExtensionId; 124 typedef std::string ExtensionId;
44 typedef std::string RuleId; 125 typedef std::string RuleId;
45 typedef std::pair<ExtensionId, RuleId> GlobalRuleId; 126 typedef std::pair<ExtensionId, RuleId> GlobalRuleId;
46 typedef int Priority; 127 typedef int Priority;
128 typedef DeclarativeConditionSet<ConditionT> ConditionSet;
129 typedef DeclarativeActionSet<ActionT> ActionSet;
130 typedef extensions::api::events::Rule JsonRule;
47 131
48 struct RequestData { 132 // Checks whether the set of |conditions| and |actions| are consistent.
49 RequestData(net::URLRequest* request, RequestStage stage) 133 // Returns true in case of consistency and MUST set |error| otherwise.
50 : request(request), stage(stage), 134 typedef bool (*ConsistencyChecker)(ConditionSet* conditions,
51 original_response_headers(NULL) {} 135 ActionSet* actions,
52 RequestData(net::URLRequest* request, RequestStage stage, 136 std::string* error);
53 const net::HttpResponseHeaders* original_response_headers)
54 : request(request), stage(stage),
55 original_response_headers(original_response_headers) {}
56 net::URLRequest* request;
57 RequestStage stage;
58 // Additional information about requests that is not
59 // available in all request stages.
60 const net::HttpResponseHeaders* original_response_headers;
61 };
62 137
63 WebRequestRule(const GlobalRuleId& id, 138 DeclarativeRule(const GlobalRuleId& id,
64 base::Time extension_installation_time, 139 base::Time extension_installation_time,
65 scoped_ptr<WebRequestConditionSet> conditions, 140 scoped_ptr<ConditionSet> conditions,
66 scoped_ptr<WebRequestActionSet> actions, 141 scoped_ptr<ActionSet> actions,
67 Priority priority); 142 Priority priority);
68 virtual ~WebRequestRule();
69 143
70 // If |error| is empty, the translation was successful and the returned 144 // Calls check_consistency(conditions, actions, error) and returns
71 // rule is internally consistent. 145 // NULL if it fails. Pass NULL if no consistency check is needed.
72 static scoped_ptr<WebRequestRule> Create( 146 // If |error| is empty, the translation was successful and the
147 // returned rule is internally consistent.
148 static scoped_ptr<DeclarativeRule> Create(
73 URLMatcherConditionFactory* url_matcher_condition_factory, 149 URLMatcherConditionFactory* url_matcher_condition_factory,
74 const std::string& extension_id, 150 const std::string& extension_id,
75 base::Time extension_installation_time, 151 base::Time extension_installation_time,
76 linked_ptr<RulesRegistry::Rule> rule, 152 linked_ptr<JsonRule> rule,
153 ConsistencyChecker check_consistency,
77 std::string* error); 154 std::string* error);
78 155
79 const GlobalRuleId& id() const { return id_; } 156 const GlobalRuleId& id() const { return id_; }
80 const std::string& extension_id() const { return id_.first; } 157 const std::string& extension_id() const { return id_.first; }
81 const WebRequestConditionSet& conditions() const { return *conditions_; } 158 const ConditionSet& conditions() const { return *conditions_; }
82 const WebRequestActionSet& actions() const { return *actions_; } 159 const ActionSet& actions() const { return *actions_; }
83 Priority priority() const { return priority_; } 160 Priority priority() const { return priority_; }
84 161
85 // Creates all deltas resulting from the ActionSet. This function should 162 // Creates all deltas resulting from the ActionSet and fills them into
86 // only be called when the conditions_ are fulfilled (from a semantic point 163 // apply_info.deltas. This function should only be called when the conditions_
87 // of view; no harm is done if this function is called at other times for 164 // are fulfilled (from a semantic point of view; no harm is done if this
88 // testing purposes). 165 // function is called at other times for testing purposes).
166 //
89 // If |extension| is set, deltas are suppressed if the |extension| does not 167 // If |extension| is set, deltas are suppressed if the |extension| does not
90 // have have sufficient permissions to modify the request. The returned list 168 // have have sufficient permissions to modify the request. The returned list
91 // may be empty in this case. 169 // may be empty in this case.
battre 2012/12/17 11:46:06 nit: there is no returned list.
Jeffrey Yasskin 2012/12/19 08:23:06 Indeed. I've rewritten this comment to avoid discu
92 std::list<LinkedPtrEventResponseDelta> CreateDeltas( 170 void Apply(const typename ActionT::ApplyInfo& apply_info) const;
battre 2012/12/17 11:46:06 const?
Jeffrey Yasskin 2012/12/19 08:23:06 Done.
93 const ExtensionInfoMap* extension_info_map,
94 const RequestData& request_data,
95 bool crosses_incognito) const;
96 171
97 // Returns the minimum priority of rules that may be evaluated after 172 // Returns the minimum priority of rules that may be evaluated after
98 // this rule. Defaults to MAX_INT. Only valid if the conditions of this rule 173 // this rule. Defaults to MAX_INT. Only valid if the conditions of this rule
99 // are fulfilled. 174 // are fulfilled.
100 Priority GetMinimumPriority() const; 175 Priority GetMinimumPriority() const;
101 176
102 private: 177 private:
103 // Checks whether the set of |conditions| and |actions| are consistent,
104 // meaning for example that we do not allow combining an |action| that needs
105 // to be executed before the |condition| can be fulfilled.
106 // Returns true in case of consistency and MUST set |error| otherwise.
107 static bool CheckConsistency(WebRequestConditionSet* conditions,
108 WebRequestActionSet* actions,
109 std::string* error);
110
111 GlobalRuleId id_; 178 GlobalRuleId id_;
112 base::Time extension_installation_time_; // For precedences of rules. 179 base::Time extension_installation_time_; // For precedences of rules.
113 scoped_ptr<WebRequestConditionSet> conditions_; 180 scoped_ptr<ConditionSet> conditions_;
114 scoped_ptr<WebRequestActionSet> actions_; 181 scoped_ptr<ActionSet> actions_;
115 Priority priority_; 182 Priority priority_;
116 183
117 DISALLOW_COPY_AND_ASSIGN(WebRequestRule); 184 DISALLOW_COPY_AND_ASSIGN(DeclarativeRule);
118 }; 185 };
119 186
187 // Implementation details below here.
188
189 //
190 // DeclarativeConditionSet
191 //
192
193 template<typename ConditionT>
194 DeclarativeConditionSet<ConditionT>::DeclarativeConditionSet(
195 const DeclarativeConditionSet::Conditions& conditions)
196 : conditions_(conditions) {
197 for (typename Conditions::iterator i = conditions_.begin();
198 i != conditions_.end(); ++i) {
199 URLMatcherConditionSet::ID trigger_id =
200 (*i)->url_matcher_condition_set_id();
201 match_triggers_[trigger_id] = i->get();
202 }
203 }
204
205 template<typename ConditionT>
206 bool DeclarativeConditionSet<ConditionT>::IsFulfilled(
207 URLMatcherConditionSet::ID url_match,
208 const typename ConditionT::MatchData& match_data) const {
209 typename MatchTriggers::const_iterator trigger =
210 match_triggers_.find(url_match);
211 DCHECK(trigger != match_triggers_.end());
212 DCHECK_EQ(url_match, trigger->second->url_matcher_condition_set_id());
213 return trigger->second->IsFulfilled(match_data);
battre 2012/12/17 11:46:06 should we do return const_cast<const ConditionT*>(
Jeffrey Yasskin 2012/12/18 02:44:26 We could make match_triggers_ into a std::map<URLM
battre 2012/12/18 08:38:49 SGTM
Jeffrey Yasskin 2012/12/19 08:23:06 match_triggers_ is gone, but I made all the lists
214 }
215
216 template<typename ConditionT>
217 void DeclarativeConditionSet<ConditionT>::GetURLMatcherConditionSets(
218 URLMatcherConditionSet::Vector* condition_sets) const {
219 for (typename Conditions::const_iterator i = conditions_.begin();
220 i != conditions_.end(); ++i) {
221 condition_sets->push_back((*i)->url_matcher_condition_set());
222 }
223 }
224
225 // static
226 template<typename ConditionT>
227 scoped_ptr<DeclarativeConditionSet<ConditionT> >
228 DeclarativeConditionSet<ConditionT>::Create(
229 URLMatcherConditionFactory* url_matcher_condition_factory,
230 const AnyVector& conditions,
231 std::string* error) {
232 DeclarativeConditionSet::Conditions result;
233
234 for (AnyVector::const_iterator i = conditions.begin();
235 i != conditions.end(); ++i) {
236 CHECK(i->get());
237 scoped_ptr<ConditionT> condition =
238 ConditionT::Create(url_matcher_condition_factory,
239 (*i)->value(), error);
240 if (!error->empty())
241 return scoped_ptr<DeclarativeConditionSet>(NULL);
242 result.push_back(make_linked_ptr(condition.release()));
243 }
244
245 return make_scoped_ptr(new DeclarativeConditionSet(result));
246 }
247
248 //
249 // DeclarativeActionSet
250 //
251
252 template<typename ActionT>
253 DeclarativeActionSet<ActionT>::DeclarativeActionSet(const Actions& actions)
254 : actions_(actions) {}
255
256 // static
257 template<typename ActionT>
258 scoped_ptr<DeclarativeActionSet<ActionT> >
259 DeclarativeActionSet<ActionT>::Create(
260 const AnyVector& actions,
261 std::string* error,
262 bool* bad_message) {
263 *error = "";
264 *bad_message = false;
265 Actions result;
266
267 for (AnyVector::const_iterator i = actions.begin();
268 i != actions.end(); ++i) {
269 CHECK(i->get());
270 scoped_ptr<ActionT> action =
271 ActionT::Create((*i)->value(), error, bad_message);
272 if (!error->empty() || *bad_message)
273 return scoped_ptr<DeclarativeActionSet>(NULL);
274 result.push_back(make_linked_ptr(action.release()));
275 }
276
277 return scoped_ptr<DeclarativeActionSet>(new DeclarativeActionSet(result));
278 }
279
280 template<typename ActionT>
281 void DeclarativeActionSet<ActionT>::Apply(
282 const std::string& extension_id,
283 const base::Time& extension_install_time,
284 const typename ActionT::ApplyInfo& apply_info) const {
285 for (typename Actions::const_iterator i = actions_.begin();
286 i != actions_.end(); ++i)
287 (*i)->Apply(extension_id, extension_install_time, apply_info);
288 }
289
290 template<typename ActionT>
291 void DeclarativeActionSet<ActionT>::Revert(
292 const std::string& extension_id,
293 const base::Time& extension_install_time,
294 const typename ActionT::ApplyInfo& apply_info) const {
295 for (typename Actions::const_iterator i = actions_.begin();
296 i != actions_.end(); ++i)
297 (*i)->Revert(extension_id, extension_install_time, apply_info);
298 }
299
300 template<typename ActionT>
301 int DeclarativeActionSet<ActionT>::GetMinimumPriority() const {
302 int minimum_priority = std::numeric_limits<int>::min();
303 for (typename Actions::const_iterator i = actions_.begin();
304 i != actions_.end(); ++i) {
305 minimum_priority = std::max(minimum_priority, (*i)->GetMinimumPriority());
306 }
307 return minimum_priority;
308 }
309
310 //
311 // DeclarativeRule
312 //
313
314 template<typename ConditionT, typename ActionT>
315 DeclarativeRule<ConditionT, ActionT>::DeclarativeRule(
316 const GlobalRuleId& id,
317 base::Time extension_installation_time,
318 scoped_ptr<ConditionSet> conditions,
319 scoped_ptr<ActionSet> actions,
320 Priority priority)
321 : id_(id),
322 extension_installation_time_(extension_installation_time),
323 conditions_(conditions.release()),
324 actions_(actions.release()),
325 priority_(priority) {
326 CHECK(conditions_.get());
327 CHECK(actions_.get());
328 }
329
330 // static
331 template<typename ConditionT, typename ActionT>
332 scoped_ptr<DeclarativeRule<ConditionT, ActionT> >
333 DeclarativeRule<ConditionT, ActionT>::Create(
334 URLMatcherConditionFactory* url_matcher_condition_factory,
335 const std::string& extension_id,
336 base::Time extension_installation_time,
337 linked_ptr<JsonRule> rule,
338 ConsistencyChecker check_consistency,
339 std::string* error) {
340 scoped_ptr<DeclarativeRule> error_result;
341
342 scoped_ptr<ConditionSet> conditions = ConditionSet::Create(
343 url_matcher_condition_factory, rule->conditions, error);
344 if (!error->empty())
345 return error_result.Pass();
346 CHECK(conditions.get());
347
348 bool bad_message = false;
349 scoped_ptr<ActionSet> actions =
350 ActionSet::Create(rule->actions, error, &bad_message);
351 if (bad_message) {
352 // TODO(battre) Export concept of bad_message to caller, the extension
353 // should be killed in case it is true.
354 *error = "An action of a rule set had an invalid "
355 "structure that should have been caught by the JSON validator.";
356 return error_result.Pass();
357 }
358 if (!error->empty() || bad_message)
359 return error_result.Pass();
360 CHECK(actions.get());
361
362 if (check_consistency &&
363 !check_consistency(conditions.get(), actions.get(), error)) {
364 DCHECK(!error->empty());
365 return error_result.Pass();
366 }
367
368 CHECK(rule->priority.get());
369 int priority = *(rule->priority);
370
371 GlobalRuleId rule_id(extension_id, *(rule->id));
372 return scoped_ptr<DeclarativeRule>(
373 new DeclarativeRule(rule_id, extension_installation_time,
374 conditions.Pass(), actions.Pass(), priority));
375 }
376
377 template<typename ConditionT, typename ActionT>
378 void DeclarativeRule<ConditionT, ActionT>::Apply(
379 const typename ActionT::ApplyInfo& apply_info) const {
380 return actions_->Apply(extension_id(),
381 extension_installation_time_,
382 apply_info);
383 }
384
385 template<typename ConditionT, typename ActionT>
386 int DeclarativeRule<ConditionT, ActionT>::GetMinimumPriority() const {
387 return actions_->GetMinimumPriority();
388 }
389
120 } // namespace extensions 390 } // namespace extensions
121 391
122 #endif // CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_WEBREQUEST_WEBREQUEST_RULE_ H_ 392 #endif // CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_DECLARATIVE_RULE_H__
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698