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

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: Rebase to Vaclav's CL and fix Dominic's comments 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
(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 // 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.
9
10 #ifndef CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_DECLARATIVE_RULE_H__
11 #define CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_DECLARATIVE_RULE_H__
12
13 #include <limits>
14
15 #include "base/memory/linked_ptr.h"
16 #include "base/memory/scoped_vector.h"
17 #include "base/time.h"
18 #include "chrome/common/extensions/api/events.h"
19 #include "chrome/common/extensions/matcher/url_matcher.h"
20
21 namespace base {
22 class Time;
23 }
24
25 namespace extensions {
26
27 // This class stores a set of conditions that may be part of a DeclarativeRule.
28 // If any condition is fulfilled, the Actions of the DeclarativeRule can be
29 // triggered.
30 //
31 // ConditionT should be immutable after creation. It must define the following
32 // members:
33 //
34 // // Arguments passed through from ConditionSet::Create.
35 // static scoped_ptr<ConditionT> Create(
36 // URLMatcherConditionFactory*,
37 // // Except this argument gets elements of the AnyVector.
38 // const base::Value& definition,
39 // std::string* error);
40 // // If the Condition needs to be filtered by some
41 // // URLMatcherConditionSets, append them to this argument.
42 // // DeclarativeConditionSet::GetURLMatcherConditionSets forwards here.
43 // void GetURLMatcherConditionSets(
44 // URLMatcherConditionSet::Vector* condition_sets)
45 // // True if GetURLMatcherConditionSets would append anything to its
46 // // argument.
47 // bool has_url_matcher_condition_set();
48 // // MatchData passed through from ConditionSet::IsFulfilled.
49 // bool condition->IsFulfilled(const ConditionT::MatchData&);
50 template<typename ConditionT>
51 class DeclarativeConditionSet {
52 public:
53 typedef std::vector<linked_ptr<json_schema_compiler::any::Any> > AnyVector;
54 typedef std::vector<linked_ptr<const ConditionT> > Conditions;
55 typedef typename Conditions::const_iterator const_iterator;
56
57 explicit DeclarativeConditionSet(const Conditions& conditions);
58
59 // Factory method that creates an WebRequestConditionSet according to the JSON
60 // array |conditions| passed by the extension API.
61 // Sets |error| and returns NULL in case of an error.
62 static scoped_ptr<DeclarativeConditionSet> Create(
63 URLMatcherConditionFactory* url_matcher_condition_factory,
64 const AnyVector& conditions,
65 std::string* error);
66
67 const Conditions& conditions() const {
68 return conditions_;
69 }
70
71 const_iterator begin() const { return conditions_.begin(); }
72 const_iterator end() const { return conditions_.end(); }
73
74 // Returns whether any condition in the condition set is fulfilled on
75 // |match_data|.
76 bool IsFulfilled(const typename ConditionT::MatchData& match_data) const;
77
78 // Appends the URLMatcherConditionSet from all conditions to |condition_sets|.
79 void GetURLMatcherConditionSets(
80 URLMatcherConditionSet::Vector* condition_sets) const;
81
82 // Returns whether there are some conditions without UrlFilter attributes.
83 bool has_conditions_without_urls() const {
84 return has_conditions_without_urls_;
85 }
86
87 private:
88 static bool HasConditionsWithoutUrls(const Conditions& conditions);
89
90 const Conditions conditions_;
91 const bool has_conditions_without_urls_;
92
93 DISALLOW_COPY_AND_ASSIGN(DeclarativeConditionSet);
94 };
95
96 // Immutable container for multiple actions.
97 //
98 // ActionT should be immutable after creation. It must define the following
99 // members:
100 //
101 // // Arguments passed through from ActionSet::Create.
102 // static scoped_ptr<ActionT> Create(
103 // // Except this argument gets elements of the AnyVector.
104 // const base::Value& definition,
105 // std::string* error, bool* bad_message);
106 // void Apply(const std::string& extension_id,
107 // const base::Time& extension_install_time,
108 // // Contains action-type-specific in/out parameters.
109 // typename ActionT::ApplyInfo* apply_info) const;
110 // // Only needed if the RulesRegistry calls DeclarativeActionSet::Revert().
111 // void Revert(const std::string& extension_id,
112 // const base::Time& extension_install_time,
113 // // Contains action-type-specific in/out parameters.
114 // typename ActionT::ApplyInfo* apply_info) const;
115 // // Return the minimum priority of rules that can be evaluated after this
vabr (Chromium) 2012/12/19 15:33:42 nit: are rules evaluated or applied? I suggest to
Jeffrey Yasskin 2012/12/20 01:27:35 I'm somewhat reluctant to go through and rename Ac
vabr (Chromium) 2012/12/20 10:51:30 It's fine to leave as it is. Definitively no need
116 // // action runs. Return MIN_INT by default.
117 // int GetMinimumPriority const;
118 //
119 // TODO(battre): As DeclarativeActionSet can become the single owner of all
120 // actions, we can optimize here by making some of them singletons (e.g. Cancel
121 // actions).
122 template<typename ActionT>
123 class DeclarativeActionSet {
124 public:
125 typedef std::vector<linked_ptr<json_schema_compiler::any::Any> > AnyVector;
126 typedef std::vector<linked_ptr<const ActionT> > Actions;
127
128 explicit DeclarativeActionSet(const Actions& actions);
129
130 // Factory method that instantiates a DeclarativeActionSet according to
131 // |actions| which represents the array of actions received from the
132 // extension API.
133 static scoped_ptr<DeclarativeActionSet> Create(const AnyVector& actions,
134 std::string* error,
135 bool* bad_message);
136
137 // Rules call this method when their conditions are fulfilled.
138 void Apply(const std::string& extension_id,
139 const base::Time& extension_install_time,
140 typename ActionT::ApplyInfo* apply_info) const;
141
142 // Rules call this method when they have stateful conditions, and those
143 // conditions stop being fulfilled. Rules with event-based conditions (e.g. a
144 // network request happened) will never Revert() an action.
145 void Revert(const std::string& extension_id,
146 const base::Time& extension_install_time,
147 typename ActionT::ApplyInfo* apply_info) const;
148
149 // Returns the minimum priority of rules that may be evaluated after
150 // this rule. Defaults to MIN_INT.
vabr (Chromium) 2012/12/19 15:33:42 nit: again evaluate vs. apply (see above). Also, "
151 int GetMinimumPriority() const;
152
153 const Actions& actions() const { return actions_; }
154
155 private:
156 Actions actions_;
157
158 DISALLOW_COPY_AND_ASSIGN(DeclarativeActionSet);
159 };
160
161 // Representation of a rule of a declarative API:
162 // https://developer.chrome.com/beta/extensions/events.html#declarative.
163 // Generally a RulesRegistry will hold a collection of Rules for a given
164 // declarative API and contain the logic for matching and applying them.
165 //
166 // See DeclarativeConditionSet and DeclarativeActionSet for the requirements on
167 // ConditionT and ActionT.
168 template<typename ConditionT, typename ActionT>
169 class DeclarativeRule {
170 public:
171 typedef std::string ExtensionId;
172 typedef std::string RuleId;
173 typedef std::pair<ExtensionId, RuleId> GlobalRuleId;
174 typedef int Priority;
175 typedef DeclarativeConditionSet<ConditionT> ConditionSet;
176 typedef DeclarativeActionSet<ActionT> ActionSet;
177 typedef extensions::api::events::Rule JsonRule;
178
179 // Checks whether the set of |conditions| and |actions| are consistent.
180 // Returns true in case of consistency and MUST set |error| otherwise.
181 typedef bool (*ConsistencyChecker)(ConditionSet* conditions,
182 ActionSet* actions,
183 std::string* error);
184
185 DeclarativeRule(const GlobalRuleId& id,
186 base::Time extension_installation_time,
187 scoped_ptr<ConditionSet> conditions,
188 scoped_ptr<ActionSet> actions,
189 Priority priority);
190
191 // Creates a DeclarativeRule for an extension given a json definition. The
192 // format of each condition and action's json is up to the specific ConditionT
193 // and ActionT.
194 //
195 // Before constructing the final rule, calls check_consistency(conditions,
196 // actions, error) and returns NULL if it fails. Pass NULL if no consistency
197 // check is needed. If |error| is empty, the translation was successful and
198 // the returned rule is internally consistent.
199 static scoped_ptr<DeclarativeRule> Create(
200 URLMatcherConditionFactory* url_matcher_condition_factory,
201 const std::string& extension_id,
202 base::Time extension_installation_time,
203 linked_ptr<JsonRule> rule,
204 ConsistencyChecker check_consistency,
205 std::string* error);
206
207 const GlobalRuleId& id() const { return id_; }
208 const std::string& extension_id() const { return id_.first; }
209 const ConditionSet& conditions() const { return *conditions_; }
210 const ActionSet& actions() const { return *actions_; }
211 Priority priority() const { return priority_; }
212
213 // Calls actions().Apply(extension_id(), extension_installation_time_,
214 // apply_info). This function should only be called when the conditions_ are
215 // fulfilled (from a semantic point of view; no harm is done if this function
216 // is called at other times for testing purposes).
217 void Apply(typename ActionT::ApplyInfo* apply_info) const;
218
219 // Returns the minimum priority of rules that may be evaluated after
vabr (Chromium) 2012/12/19 15:33:42 nit: evaluated or applied? (See comments above.)
220 // this rule. Defaults to MAX_INT. Only valid if the conditions of this rule
vabr (Chromium) 2012/12/19 15:33:42 How does this default to MAX_INT? In the implement
Jeffrey Yasskin 2012/12/20 01:27:35 I think that's a typo I copied from webrequest_rul
221 // are fulfilled.
222 Priority GetMinimumPriority() const;
223
224 private:
225 GlobalRuleId id_;
226 base::Time extension_installation_time_; // For precedences of rules.
227 scoped_ptr<ConditionSet> conditions_;
228 scoped_ptr<ActionSet> actions_;
229 Priority priority_;
230
231 DISALLOW_COPY_AND_ASSIGN(DeclarativeRule);
232 };
233
234 // Implementation details below here.
235
236 //
237 // DeclarativeConditionSet
238 //
239
240 template<typename ConditionT>
vabr (Chromium) 2012/12/19 15:33:42 Please prepend // static for consistency with the
Jeffrey Yasskin 2012/12/20 01:27:35 Oops, but this function's gone now.
241 bool DeclarativeConditionSet<ConditionT>::HasConditionsWithoutUrls(
242 const Conditions& conditions) {
243 for (typename Conditions::const_iterator i = conditions.begin();
244 i != conditions.end(); ++i) {
245 if (!(*i)->has_url_matcher_condition_set())
246 return true;
247 }
248 return false;
249 }
250
251 template<typename ConditionT>
252 DeclarativeConditionSet<ConditionT>::DeclarativeConditionSet(
253 const DeclarativeConditionSet::Conditions& conditions)
254 : conditions_(conditions),
255 has_conditions_without_urls_(HasConditionsWithoutUrls(conditions)) {
256 }
257
258 template<typename ConditionT>
259 bool DeclarativeConditionSet<ConditionT>::IsFulfilled(
260 const typename ConditionT::MatchData& match_data) const {
261 for (typename Conditions::const_iterator i = conditions_.begin();
262 i != conditions_.end(); ++i) {
263 if ((*i)->IsFulfilled(match_data))
264 return true;
265 }
266 return false;
267 }
268
269 template<typename ConditionT>
270 void DeclarativeConditionSet<ConditionT>::GetURLMatcherConditionSets(
271 URLMatcherConditionSet::Vector* condition_sets) const {
272 for (typename Conditions::const_iterator i = conditions_.begin();
273 i != conditions_.end(); ++i) {
274 (*i)->GetURLMatcherConditionSets(condition_sets);
275 }
276 }
277
278 // static
279 template<typename ConditionT>
280 scoped_ptr<DeclarativeConditionSet<ConditionT> >
281 DeclarativeConditionSet<ConditionT>::Create(
282 URLMatcherConditionFactory* url_matcher_condition_factory,
283 const AnyVector& conditions,
284 std::string* error) {
285 DeclarativeConditionSet::Conditions result;
286
287 for (AnyVector::const_iterator i = conditions.begin();
288 i != conditions.end(); ++i) {
289 CHECK(i->get());
290 scoped_ptr<ConditionT> condition =
291 ConditionT::Create(url_matcher_condition_factory,
292 (*i)->value(), error);
293 if (!error->empty())
294 return scoped_ptr<DeclarativeConditionSet>(NULL);
295 result.push_back(make_linked_ptr(condition.release()));
296 }
297
298 return make_scoped_ptr(new DeclarativeConditionSet(result));
299 }
300
301 //
302 // DeclarativeActionSet
303 //
304
305 template<typename ActionT>
306 DeclarativeActionSet<ActionT>::DeclarativeActionSet(const Actions& actions)
307 : actions_(actions) {}
308
309 // static
310 template<typename ActionT>
311 scoped_ptr<DeclarativeActionSet<ActionT> >
312 DeclarativeActionSet<ActionT>::Create(
313 const AnyVector& actions,
314 std::string* error,
315 bool* bad_message) {
316 *error = "";
317 *bad_message = false;
318 Actions result;
319
320 for (AnyVector::const_iterator i = actions.begin();
321 i != actions.end(); ++i) {
322 CHECK(i->get());
323 scoped_ptr<ActionT> action =
324 ActionT::Create((*i)->value(), error, bad_message);
325 if (!error->empty() || *bad_message)
326 return scoped_ptr<DeclarativeActionSet>(NULL);
327 result.push_back(make_linked_ptr(action.release()));
328 }
329
330 return scoped_ptr<DeclarativeActionSet>(new DeclarativeActionSet(result));
331 }
332
333 template<typename ActionT>
334 void DeclarativeActionSet<ActionT>::Apply(
335 const std::string& extension_id,
336 const base::Time& extension_install_time,
337 typename ActionT::ApplyInfo* apply_info) const {
338 for (typename Actions::const_iterator i = actions_.begin();
339 i != actions_.end(); ++i)
340 (*i)->Apply(extension_id, extension_install_time, apply_info);
341 }
342
343 template<typename ActionT>
344 void DeclarativeActionSet<ActionT>::Revert(
345 const std::string& extension_id,
346 const base::Time& extension_install_time,
347 typename ActionT::ApplyInfo* apply_info) const {
348 for (typename Actions::const_iterator i = actions_.begin();
349 i != actions_.end(); ++i)
350 (*i)->Revert(extension_id, extension_install_time, apply_info);
351 }
352
353 template<typename ActionT>
354 int DeclarativeActionSet<ActionT>::GetMinimumPriority() const {
355 int minimum_priority = std::numeric_limits<int>::min();
356 for (typename Actions::const_iterator i = actions_.begin();
357 i != actions_.end(); ++i) {
358 minimum_priority = std::max(minimum_priority, (*i)->GetMinimumPriority());
359 }
360 return minimum_priority;
361 }
362
363 //
364 // DeclarativeRule
365 //
366
367 template<typename ConditionT, typename ActionT>
368 DeclarativeRule<ConditionT, ActionT>::DeclarativeRule(
369 const GlobalRuleId& id,
370 base::Time extension_installation_time,
371 scoped_ptr<ConditionSet> conditions,
372 scoped_ptr<ActionSet> actions,
373 Priority priority)
374 : id_(id),
375 extension_installation_time_(extension_installation_time),
376 conditions_(conditions.release()),
377 actions_(actions.release()),
378 priority_(priority) {
379 CHECK(conditions_.get());
380 CHECK(actions_.get());
381 }
382
383 // static
384 template<typename ConditionT, typename ActionT>
385 scoped_ptr<DeclarativeRule<ConditionT, ActionT> >
386 DeclarativeRule<ConditionT, ActionT>::Create(
387 URLMatcherConditionFactory* url_matcher_condition_factory,
388 const std::string& extension_id,
389 base::Time extension_installation_time,
390 linked_ptr<JsonRule> rule,
391 ConsistencyChecker check_consistency,
392 std::string* error) {
393 scoped_ptr<DeclarativeRule> error_result;
394
395 scoped_ptr<ConditionSet> conditions = ConditionSet::Create(
396 url_matcher_condition_factory, rule->conditions, error);
397 if (!error->empty())
398 return error_result.Pass();
399 CHECK(conditions.get());
400
401 bool bad_message = false;
402 scoped_ptr<ActionSet> actions =
403 ActionSet::Create(rule->actions, error, &bad_message);
404 if (bad_message) {
405 // TODO(battre) Export concept of bad_message to caller, the extension
406 // should be killed in case it is true.
407 *error = "An action of a rule set had an invalid "
408 "structure that should have been caught by the JSON validator.";
409 return error_result.Pass();
410 }
411 if (!error->empty() || bad_message)
412 return error_result.Pass();
413 CHECK(actions.get());
414
415 if (check_consistency &&
416 !check_consistency(conditions.get(), actions.get(), error)) {
417 DCHECK(!error->empty());
418 return error_result.Pass();
419 }
420
421 CHECK(rule->priority.get());
422 int priority = *(rule->priority);
423
424 GlobalRuleId rule_id(extension_id, *(rule->id));
425 return scoped_ptr<DeclarativeRule>(
426 new DeclarativeRule(rule_id, extension_installation_time,
427 conditions.Pass(), actions.Pass(), priority));
428 }
429
430 template<typename ConditionT, typename ActionT>
431 void DeclarativeRule<ConditionT, ActionT>::Apply(
432 typename ActionT::ApplyInfo* apply_info) const {
433 return actions_->Apply(extension_id(),
434 extension_installation_time_,
435 apply_info);
436 }
437
438 template<typename ConditionT, typename ActionT>
439 int DeclarativeRule<ConditionT, ActionT>::GetMinimumPriority() const {
440 return actions_->GetMinimumPriority();
441 }
442
443 } // namespace extensions
444
445 #endif // CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_DECLARATIVE_RULE_H__
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698