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.
5 #ifndef CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_CONTENT_CHROME_CONTENT_RULES_REGISTRY_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_CONTENT_CHROME_CONTENT_RULES_REGISTRY_H_
14 #include "base/callback.h"
15 #include "base/memory/linked_ptr.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/memory/scoped_vector.h"
18 #include "chrome/browser/extensions/api/declarative_content/content_action.h"
19 #include "chrome/browser/extensions/api/declarative_content/declarative_content_condition_tracker_delegate.h"
20 #include "chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.h"
21 #include "chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.h"
22 #include "chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.h"
23 #include "components/url_matcher/url_matcher.h"
24 #include "content/public/browser/notification_observer.h"
25 #include "content/public/browser/notification_registrar.h"
26 #include "extensions/browser/api/declarative_content/content_rules_registry.h"
28 class ContentPermissions
;
32 class RenderProcessHost
;
34 struct FrameNavigateParams
;
35 struct LoadCommittedDetails
;
38 namespace extension_web_request_api_helpers
{
39 struct EventResponseDelta
;
46 namespace extensions
{
50 // Representation of a condition in the Declarative Content API. A condition
51 // consists of a set of predicates on the page state, all of which must be
52 // satisified for the condition to be fulfilled.
53 struct ContentCondition
{
56 scoped_ptr
<DeclarativeContentPageUrlPredicate
> page_url_predicate
,
57 scoped_ptr
<DeclarativeContentCssPredicate
> css_predicate
,
58 scoped_ptr
<DeclarativeContentIsBookmarkedPredicate
>
59 is_bookmarked_predicate
);
62 scoped_ptr
<DeclarativeContentPageUrlPredicate
> page_url_predicate
;
63 scoped_ptr
<DeclarativeContentCssPredicate
> css_predicate
;
64 scoped_ptr
<DeclarativeContentIsBookmarkedPredicate
> is_bookmarked_predicate
;
67 DISALLOW_COPY_AND_ASSIGN(ContentCondition
);
70 // Defines the interface for a predicate factory. Temporary, until we can
71 // introduce an interface to be implemented by the trackers that returns a
74 using PredicateFactory
=
75 base::Callback
<scoped_ptr
<T
>(const Extension
* extension
,
76 const base::Value
& value
,
79 // Factory function that instantiates a ContentCondition according to the
80 // description |condition| passed by the extension API. |condition| should be
81 // an instance of declarativeContent.PageStateMatcher.
82 scoped_ptr
<ContentCondition
> CreateContentCondition(
83 const Extension
* extension
,
84 const PredicateFactory
<DeclarativeContentCssPredicate
>&
85 css_predicate_factory
,
86 const PredicateFactory
<DeclarativeContentIsBookmarkedPredicate
>&
87 is_bookmarked_predicate_factory
,
88 const PredicateFactory
<DeclarativeContentPageUrlPredicate
>&
89 page_url_predicate_factory
,
90 const base::Value
& condition
,
93 // The ChromeContentRulesRegistry is responsible for managing
94 // the internal representation of rules for the Declarative Content API.
96 // Here is the high level overview of this functionality:
98 // api::events::Rule consists of conditions and actions, these are
99 // represented as a ContentRule with ContentConditions and ContentRuleActions.
101 // The evaluation of URL related condition attributes (host_suffix, path_prefix)
102 // is delegated to a URLMatcher, because this is capable of evaluating many
103 // of such URL related condition attributes in parallel.
105 // A note on incognito support: separate instances of ChromeContentRulesRegistry
106 // are created for incognito and non-incognito contexts. The incognito instance,
107 // however, is only responsible for applying rules registered by the incognito
108 // side of split-mode extensions to incognito tabs. The non-incognito instance
109 // handles incognito tabs for spanning-mode extensions, plus all non-incognito
111 class ChromeContentRulesRegistry
112 : public ContentRulesRegistry
,
113 public content::NotificationObserver
,
114 public DeclarativeContentConditionTrackerDelegate
{
116 // For testing, |ui_part| can be NULL. In that case it constructs the
117 // registry with storage functionality suspended.
118 ChromeContentRulesRegistry(content::BrowserContext
* browser_context
,
119 RulesCacheDelegate
* cache_delegate
);
121 // ContentRulesRegistry:
122 void MonitorWebContentsForRuleEvaluation(
123 content::WebContents
* contents
) override
;
124 void DidNavigateMainFrame(
125 content::WebContents
* tab
,
126 const content::LoadCommittedDetails
& details
,
127 const content::FrameNavigateParams
& params
) override
;
130 std::string
AddRulesImpl(
131 const std::string
& extension_id
,
132 const std::vector
<linked_ptr
<api::events::Rule
>>& rules
) override
;
133 std::string
RemoveRulesImpl(
134 const std::string
& extension_id
,
135 const std::vector
<std::string
>& rule_identifiers
) override
;
136 std::string
RemoveAllRulesImpl(const std::string
& extension_id
) override
;
138 // content::NotificationObserver:
139 void Observe(int type
,
140 const content::NotificationSource
& source
,
141 const content::NotificationDetails
& details
) override
;
143 // DeclarativeContentConditionTrackerDelegate:
144 void RequestEvaluation(content::WebContents
* contents
) override
;
145 bool ShouldManageConditionsForBrowserContext(
146 content::BrowserContext
* context
) override
;
148 // Returns true if this object retains no allocated data. Only for debugging.
149 bool IsEmpty() const;
151 // TODO(wittman): Remove once DeclarativeChromeContentRulesRegistry no longer
152 // depends on concrete condition implementations. At that point
153 // DeclarativeChromeContentRulesRegistryTest.ActiveRulesDoesntGrow will be
154 // able to use a test condition object and not need to depend on force setting
155 // matching CSS seleectors.
156 void UpdateMatchingCssSelectorsForTesting(
157 content::WebContents
* contents
,
158 const std::vector
<std::string
>& matching_css_selectors
);
160 // Returns the number of active rules.
161 size_t GetActiveRulesCountForTesting();
164 ~ChromeContentRulesRegistry() override
;
167 // The internal declarative rule representation. Corresponds to a declarative
168 // API rule: https://developer.chrome.com/extensions/events.html#declarative.
171 ContentRule(const Extension
* extension
,
172 ScopedVector
<const ContentCondition
> conditions
,
173 ScopedVector
<const ContentAction
> actions
,
177 const Extension
* extension
;
178 ScopedVector
<const ContentCondition
> conditions
;
179 ScopedVector
<const ContentAction
> actions
;
183 DISALLOW_COPY_AND_ASSIGN(ContentRule
);
186 // Specifies what to do with evaluation requests.
187 // TODO(wittman): Try to eliminate the need for IGNORE after refactoring to
188 // treat all condition evaluation consistently. Currently RemoveRulesImpl only
189 // updates the CSS selectors after the rules are removed, which is too late
191 enum EvaluationDisposition
{
192 EVALUATE_REQUESTS
, // Evaluate immediately.
193 DEFER_REQUESTS
, // Defer for later evaluation.
194 IGNORE_REQUESTS
// Ignore.
197 class EvaluationScope
;
199 // Creates a ContentRule for |extension| given a json definition. The format
200 // of each condition and action's json is up to the specific ContentCondition
201 // and ContentAction. |extension| may be NULL in tests. If |error| is empty,
202 // the translation was successful and the returned rule is internally
204 scoped_ptr
<const ContentRule
> CreateRule(
205 const Extension
* extension
,
206 const PredicateFactory
<DeclarativeContentCssPredicate
>&
207 css_predicate_factory
,
208 const PredicateFactory
<DeclarativeContentIsBookmarkedPredicate
>&
209 is_bookmarked_predicate_factory
,
210 const PredicateFactory
<DeclarativeContentPageUrlPredicate
>&
211 page_url_predicate_factory
,
212 const api::events::Rule
& api_rule
,
215 // True if this object is managing the rules for |context|.
216 bool ManagingRulesForBrowserContext(content::BrowserContext
* context
);
218 std::set
<const ContentRule
*> GetMatchingRules(
219 content::WebContents
* tab
) const;
221 // Updates the condition evaluator with the current watched CSS selectors.
222 void UpdateCssSelectorsFromRules();
224 // Evaluates the conditions for |tab| based on the tab state and matching CSS
226 void EvaluateConditionsForTab(content::WebContents
* tab
);
228 // Returns true if a rule created by |extension| should be evaluated for an
229 // incognito renderer.
230 bool ShouldEvaluateExtensionRulesForIncognitoRenderer(
231 const Extension
* extension
) const;
233 using ExtensionIdRuleIdPair
= std::pair
<extensions::ExtensionId
, std::string
>;
234 using RuleAndConditionForURLMatcherId
=
235 std::map
<url_matcher::URLMatcherConditionSet::ID
,
236 std::pair
<const ContentRule
*, const ContentCondition
*>>;
237 using RulesMap
= std::map
<ExtensionIdRuleIdPair
,
238 linked_ptr
<const ContentRule
>>;
240 RulesMap content_rules_
;
242 // Maps a WebContents to the set of rules that match on that WebContents.
243 // This lets us call Revert as appropriate. Note that this is expected to have
244 // a key-value pair for every WebContents the registry is tracking, even if
245 // the value is the empty set.
246 std::map
<content::WebContents
*, std::set
<const ContentRule
*>> active_rules_
;
248 // Responsible for tracking declarative content page URL condition state.
249 DeclarativeContentPageUrlConditionTracker page_url_condition_tracker_
;
251 // Responsible for tracking declarative content CSS condition state.
252 DeclarativeContentCssConditionTracker css_condition_tracker_
;
254 // Responsible for tracking declarative content bookmarked condition state.
255 DeclarativeContentIsBookmarkedConditionTracker
256 is_bookmarked_condition_tracker_
;
258 // Specifies what to do with evaluation requests.
259 EvaluationDisposition evaluation_disposition_
;
261 // Contains WebContents which require rule evaluation. Only used while
262 // |evaluation_disposition_| is DEFER.
263 std::set
<content::WebContents
*> evaluation_pending_
;
265 // Manages our notification registrations.
266 content::NotificationRegistrar registrar_
;
268 DISALLOW_COPY_AND_ASSIGN(ChromeContentRulesRegistry
);
271 } // namespace extensions
273 #endif // CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_CONTENT_CHROME_CONTENT_RULES_REGISTRY_H_