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

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

Issue 11547033: Implement declarativeContent API. (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
(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 template<typename ConditionT>
Matt Perry 2012/12/13 20:27:48 Did you consider defining Condition and Action int
Jeffrey Yasskin 2012/12/14 00:38:20 Yes. It would be more verbose to implement, and bo
Matt Perry 2012/12/14 19:49:32 Fair enough :)
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;
36
37 explicit DeclarativeConditionSet(const Conditions& conditions);
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,
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;
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;
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 {
123 public:
124 typedef std::string ExtensionId;
125 typedef std::string RuleId;
126 typedef std::pair<ExtensionId, RuleId> GlobalRuleId;
127 typedef int Priority;
128 typedef DeclarativeConditionSet<ConditionT> ConditionSet;
129 typedef DeclarativeActionSet<ActionT> ActionSet;
130 typedef extensions::api::events::Rule JsonRule;
131
132 // Checks whether the set of |conditions| and |actions| are consistent.
133 // Returns true in case of consistency and MUST set |error| otherwise.
134 typedef bool (*ConsistencyChecker)(ConditionSet* conditions,
135 ActionSet* actions,
136 std::string* error);
137
138 DeclarativeRule(const GlobalRuleId& id,
139 base::Time extension_installation_time,
140 scoped_ptr<ConditionSet> conditions,
141 scoped_ptr<ActionSet> actions,
142 Priority priority);
143
144 // Calls check_consistency(conditions, actions, error) and returns
145 // NULL if it fails. Pass NULL if no consistency check is needed.
146 // If |error| is empty, the translation was successful and the
147 // returned rule is internally consistent.
148 static scoped_ptr<DeclarativeRule> Create(
149 URLMatcherConditionFactory* url_matcher_condition_factory,
150 const std::string& extension_id,
151 base::Time extension_installation_time,
152 linked_ptr<JsonRule> rule,
153 ConsistencyChecker check_consistency,
154 std::string* error);
155
156 const GlobalRuleId& id() const { return id_; }
157 const std::string& extension_id() const { return id_.first; }
158 const ConditionSet& conditions() const { return *conditions_; }
159 const ActionSet& actions() const { return *actions_; }
160 Priority priority() const { return priority_; }
161
162 // Creates all deltas resulting from the ActionSet and fills them into
163 // apply_info.deltas. This function should only be called when the conditions_
164 // are fulfilled (from a semantic point of view; no harm is done if this
165 // function is called at other times for testing purposes).
166 //
167 // If |extension| is set, deltas are suppressed if the |extension| does not
168 // have have sufficient permissions to modify the request. The returned list
169 // may be empty in this case.
170 void Apply(const typename ActionT::ApplyInfo& apply_info) const;
171
172 // Returns the minimum priority of rules that may be evaluated after
173 // this rule. Defaults to MAX_INT. Only valid if the conditions of this rule
174 // are fulfilled.
175 Priority GetMinimumPriority() const;
176
177 private:
178 GlobalRuleId id_;
179 base::Time extension_installation_time_; // For precedences of rules.
180 scoped_ptr<ConditionSet> conditions_;
181 scoped_ptr<ActionSet> actions_;
182 Priority priority_;
183
184 DISALLOW_COPY_AND_ASSIGN(DeclarativeRule);
185 };
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);
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
390 } // namespace extensions
391
392 #endif // CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_DECLARATIVE_RULE_H__
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698