blob: 192c228ecd4b34c00ece26bea0283dbe57281d79 [file] [log] [blame]
// 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 "base/memory/linked_ptr.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_