| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_CONTENT_CHROME_CONTENT_RULES_REGISTRY_H_ |
| #define CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_CONTENT_CHROME_CONTENT_RULES_REGISTRY_H_ |
| |
| #include <stddef.h> |
| |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/callback.h" |
| #include "base/macros.h" |
| #include "chrome/browser/extensions/api/declarative_content/content_action.h" |
| #include "chrome/browser/extensions/api/declarative_content/content_condition.h" |
| #include "chrome/browser/extensions/api/declarative_content/content_predicate_evaluator.h" |
| #include "content/public/browser/notification_observer.h" |
| #include "content/public/browser/notification_registrar.h" |
| #include "extensions/browser/api/declarative_content/content_rules_registry.h" |
| #include "extensions/common/extension_id.h" |
| |
| namespace content { |
| class BrowserContext; |
| class WebContents; |
| } |
| |
| namespace extensions { |
| |
| class Extension; |
| |
| // The ChromeContentRulesRegistry is responsible for managing |
| // the internal representation of rules for the Declarative Content API. |
| // |
| // Here is the high level overview of this functionality: |
| // |
| // api::events::Rule consists of conditions and actions, these are |
| // represented as a ContentRule with ContentConditions and ContentActions. |
| // |
| // A note on incognito support: separate instances of ChromeContentRulesRegistry |
| // are created for incognito and non-incognito contexts. The incognito instance, |
| // however, is only responsible for applying rules registered by the incognito |
| // side of split-mode extensions to incognito tabs. The non-incognito instance |
| // handles incognito tabs for spanning-mode extensions, plus all non-incognito |
| // tabs. |
| class ChromeContentRulesRegistry |
| : public ContentRulesRegistry, |
| public content::NotificationObserver, |
| public ContentPredicateEvaluator::Delegate { |
| public: |
| using PredicateEvaluatorsFactory = |
| base::Callback<std::vector<std::unique_ptr<ContentPredicateEvaluator>>( |
| ContentPredicateEvaluator::Delegate*)>; |
| |
| // For testing, |cache_delegate| can be NULL. In that case it constructs the |
| // registry with storage functionality suspended. |
| ChromeContentRulesRegistry( |
| content::BrowserContext* browser_context, |
| RulesCacheDelegate* cache_delegate, |
| const PredicateEvaluatorsFactory& evaluators_factory); |
| |
| // ContentRulesRegistry: |
| void MonitorWebContentsForRuleEvaluation( |
| content::WebContents* contents) override; |
| void DidFinishNavigation( |
| content::WebContents* tab, |
| content::NavigationHandle* navigation_handle) override; |
| |
| // RulesRegistry: |
| std::string AddRulesImpl( |
| const std::string& extension_id, |
| const std::vector<const api::events::Rule*>& rules) override; |
| std::string RemoveRulesImpl( |
| const std::string& extension_id, |
| const std::vector<std::string>& rule_identifiers) override; |
| std::string RemoveAllRulesImpl(const std::string& extension_id) override; |
| |
| // content::NotificationObserver: |
| void Observe(int type, |
| const content::NotificationSource& source, |
| const content::NotificationDetails& details) override; |
| |
| // DeclarativeContentConditionTrackerDelegate: |
| void RequestEvaluation(content::WebContents* contents) override; |
| bool ShouldManageConditionsForBrowserContext( |
| content::BrowserContext* context) override; |
| |
| // Returns the number of active rules. |
| size_t GetActiveRulesCountForTesting(); |
| |
| protected: |
| ~ChromeContentRulesRegistry() override; |
| |
| private: |
| // The internal declarative rule representation. Corresponds to a declarative |
| // API rule: https://developer.chrome.com/extensions/events.html#declarative. |
| struct ContentRule { |
| public: |
| ContentRule(const Extension* extension, |
| std::vector<std::unique_ptr<const ContentCondition>> conditions, |
| std::vector<std::unique_ptr<const ContentAction>> actions, |
| int priority); |
| ~ContentRule(); |
| |
| const Extension* extension; |
| std::vector<std::unique_ptr<const ContentCondition>> conditions; |
| std::vector<std::unique_ptr<const ContentAction>> actions; |
| int priority; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(ContentRule); |
| }; |
| |
| // Specifies what to do with evaluation requests. |
| // TODO(wittman): Try to eliminate the need for IGNORE after refactoring to |
| // treat all condition evaluation consistently. |
| enum EvaluationDisposition { |
| EVALUATE_REQUESTS, // Evaluate immediately. |
| DEFER_REQUESTS, // Defer for later evaluation. |
| IGNORE_REQUESTS // Ignore. |
| }; |
| |
| class EvaluationScope; |
| |
| // Creates a ContentRule for |extension| given a json definition. The format |
| // of each condition and action's json is up to the specific ContentCondition |
| // and ContentAction. |extension| may be NULL in tests. If |error| is empty, |
| // the translation was successful and the returned rule is internally |
| // consistent. |
| std::unique_ptr<const ContentRule> CreateRule( |
| const Extension* extension, |
| const std::map<std::string, ContentPredicateFactory*>& |
| predicate_factories, |
| const api::events::Rule& api_rule, |
| std::string* error); |
| |
| // True if this object is managing the rules for |context|. |
| bool ManagingRulesForBrowserContext(content::BrowserContext* context); |
| |
| // True if |condition| matches on |tab|. |
| static bool EvaluateConditionForTab(const ContentCondition* condition, |
| content::WebContents* tab); |
| |
| std::set<const ContentRule*> GetMatchingRules( |
| content::WebContents* tab) const; |
| |
| // Evaluates the conditions for |tab| based on the tab state and matching CSS |
| // selectors. |
| void EvaluateConditionsForTab(content::WebContents* tab); |
| |
| // Returns true if a rule created by |extension| should be evaluated for an |
| // incognito renderer. |
| bool ShouldEvaluateExtensionRulesForIncognitoRenderer( |
| const Extension* extension) const; |
| |
| using ExtensionIdRuleIdPair = std::pair<extensions::ExtensionId, std::string>; |
| using RulesMap = |
| std::map<ExtensionIdRuleIdPair, std::unique_ptr<const ContentRule>>; |
| |
| RulesMap content_rules_; |
| |
| // Maps a WebContents to the set of rules that match on that WebContents. |
| // This lets us call Revert as appropriate. Note that this is expected to have |
| // a key-value pair for every WebContents the registry is tracking, even if |
| // the value is the empty set. |
| std::map<content::WebContents*, std::set<const ContentRule*>> active_rules_; |
| |
| // The evaluators responsible for creating predicates and tracking |
| // predicate-related state. |
| std::vector<std::unique_ptr<ContentPredicateEvaluator>> evaluators_; |
| |
| // Specifies what to do with evaluation requests. |
| EvaluationDisposition evaluation_disposition_; |
| |
| // Contains WebContents which require rule evaluation. Only used while |
| // |evaluation_disposition_| is DEFER. |
| std::set<content::WebContents*> evaluation_pending_; |
| |
| // Manages our notification registrations. |
| content::NotificationRegistrar registrar_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ChromeContentRulesRegistry); |
| }; |
| |
| } // namespace extensions |
| |
| #endif // CHROME_BROWSER_EXTENSIONS_API_DECLARATIVE_CONTENT_CHROME_CONTENT_RULES_REGISTRY_H_ |