blob: eb8664a5e2248cd8800d498d85c1ecec68f6fa06 [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 EXTENSIONS_BROWSER_API_DECLARATIVE_RULES_REGISTRY_SERVICE_H__
#define EXTENSIONS_BROWSER_API_DECLARATIVE_RULES_REGISTRY_SERVICE_H__
#include <map>
#include <string>
#include <tuple>
#include <vector>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/scoped_observer.h"
#include "extensions/browser/api/declarative/rules_cache_delegate.h"
#include "extensions/browser/api/declarative/rules_registry.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/extension_registry_observer.h"
namespace content {
class BrowserContext;
}
namespace extensions {
class ContentRulesRegistry;
class ExtensionRegistry;
}
namespace extensions {
// This class owns all RulesRegistries implementations of an ExtensionService.
// This class lives on the UI thread.
class RulesRegistryService : public BrowserContextKeyedAPI,
public ExtensionRegistryObserver,
public RulesCacheDelegate::Observer {
public:
static const int kDefaultRulesRegistryID;
static const int kInvalidRulesRegistryID;
struct RulesRegistryKey {
std::string event_name;
int rules_registry_id;
RulesRegistryKey(const std::string& event_name, int rules_registry_id)
: event_name(event_name), rules_registry_id(rules_registry_id) {}
bool operator<(const RulesRegistryKey& other) const {
return std::tie(event_name, rules_registry_id) <
std::tie(other.event_name, other.rules_registry_id);
}
};
class Observer {
public:
// Called when any of the |cache_delegates_| have rule updates.
virtual void OnUpdateRules() = 0;
protected:
virtual ~Observer() {}
};
explicit RulesRegistryService(content::BrowserContext* context);
~RulesRegistryService() override;
// Unregisters refptrs to concrete RulesRegistries at other objects that were
// created by us so that the RulesRegistries can be released.
void Shutdown() override;
// BrowserContextKeyedAPI implementation.
static BrowserContextKeyedAPIFactory<RulesRegistryService>*
GetFactoryInstance();
// Convenience method to get the RulesRegistryService for a context. If a
// RulesRegistryService does not already exist for |context|, one will be
// created and returned.
static RulesRegistryService* Get(content::BrowserContext* context);
// The same as Get(), except that if a RulesRegistryService does not already
// exist for |context|, nullptr is returned.
static RulesRegistryService* GetIfExists(content::BrowserContext* context);
int GetNextRulesRegistryID();
// Registers a RulesRegistry and wraps it in an InitializingRulesRegistry.
void RegisterRulesRegistry(scoped_refptr<RulesRegistry> rule_registry);
// Returns the RulesRegistry for |event_name| and |rules_registry_id|.
// Attempts to create and register the rules registry if necessary. Might
// return null if no corresponding rules registry was registered.
scoped_refptr<RulesRegistry> GetRulesRegistry(int rules_registry_id,
const std::string& event_name);
// Remove all rules registries of the given rules_registry_id.
void RemoveRulesRegistriesByID(int rules_registry_id);
// Accessors for each type of rules registry.
ContentRulesRegistry* content_rules_registry() const {
CHECK(content_rules_registry_);
return content_rules_registry_;
}
// Indicates whether any registry has rules registered.
bool HasAnyRegisteredRules() const;
// Adds or removes an observer.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// For testing.
void SimulateExtensionUninstalled(const Extension* extension);
private:
friend class BrowserContextKeyedAPIFactory<RulesRegistryService>;
scoped_refptr<RulesRegistry> RegisterWebRequestRulesRegistry(
int rules_registry_id,
RulesCacheDelegate::Type cache_delegate_type);
// Registers the default RulesRegistries used in Chromium.
void EnsureDefaultRulesRegistriesRegistered();
// Maps <event name, rules registry ID> to RuleRegistries that handle these
// events.
typedef std::map<RulesRegistryKey, scoped_refptr<RulesRegistry> >
RulesRegistryMap;
// ExtensionRegistryObserver implementation.
void OnExtensionLoaded(content::BrowserContext* browser_context,
const Extension* extension) override;
void OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason reason) override;
void OnExtensionUninstalled(content::BrowserContext* browser_context,
const Extension* extension,
extensions::UninstallReason reason) override;
// RulesCacheDelegate::Observer implementation.
void OnUpdateRules() override;
// Iterates over all registries, and calls |notification_callback| on them
// with |extension| as the argument. If a registry lives on a different
// thread, the call is posted to that thread, so no guarantee of synchronous
// processing.
void NotifyRegistriesHelper(
void (RulesRegistry::*notification_callback)(const Extension*),
const Extension* extension);
// BrowserContextKeyedAPI implementation.
static const char* service_name() {
return "RulesRegistryService";
}
static const bool kServiceHasOwnInstanceInIncognito = true;
static const bool kServiceIsNULLWhileTesting = true;
int current_rules_registry_id_;
RulesRegistryMap rule_registries_;
// We own the parts of the registries which need to run on the UI thread.
std::vector<std::unique_ptr<RulesCacheDelegate>> cache_delegates_;
// Weak pointer into rule_registries_ to make it easier to handle content rule
// conditions.
ContentRulesRegistry* content_rules_registry_;
// Listen to extension load, unloaded notification.
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observer_;
content::BrowserContext* browser_context_;
base::ObserverList<Observer> observers_;
DISALLOW_COPY_AND_ASSIGN(RulesRegistryService);
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_API_DECLARATIVE_RULES_REGISTRY_SERVICE_H__