Finish refactoring of DomCodeToUsLayoutKeyboardCode().
[chromium-blink-merge.git] / extensions / browser / api / declarative / rules_registry_service.cc
blob939b01eab2ae33b92bdf779c059582e6ae5ee6ab
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 #include "extensions/browser/api/declarative/rules_registry_service.h"
7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/render_process_host.h"
13 #include "extensions/browser/api/declarative/rules_cache_delegate.h"
14 #include "extensions/browser/api/declarative_content/content_rules_registry.h"
15 #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
16 #include "extensions/browser/api/declarative_webrequest/webrequest_rules_registry.h"
17 #include "extensions/browser/api/extensions_api_client.h"
18 #include "extensions/browser/api/web_request/web_request_api.h"
19 #include "extensions/browser/extension_registry.h"
20 #include "extensions/common/extension.h"
22 namespace extensions {
24 namespace {
26 // Registers |web_request_rules_registry| on the IO thread.
27 void RegisterToExtensionWebRequestEventRouterOnIO(
28 content::BrowserContext* browser_context,
29 int rules_registry_id,
30 scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry) {
31 ExtensionWebRequestEventRouter::GetInstance()->RegisterRulesRegistry(
32 browser_context, rules_registry_id, web_request_rules_registry);
35 void NotifyWithExtensionSafe(
36 scoped_refptr<const Extension> extension,
37 void (RulesRegistry::*notification_callback)(const Extension*),
38 scoped_refptr<RulesRegistry> registry) {
39 (registry.get()->*notification_callback)(extension.get());
42 } // namespace
44 const int RulesRegistryService::kDefaultRulesRegistryID = 0;
45 const int RulesRegistryService::kInvalidRulesRegistryID = -1;
47 RulesRegistryService::RulesRegistryService(content::BrowserContext* context)
48 : current_rules_registry_id_(kDefaultRulesRegistryID),
49 content_rules_registry_(NULL),
50 extension_registry_observer_(this),
51 browser_context_(context) {
52 if (browser_context_) {
53 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
54 EnsureDefaultRulesRegistriesRegistered(kDefaultRulesRegistryID);
58 RulesRegistryService::~RulesRegistryService() {}
60 int RulesRegistryService::GetNextRulesRegistryID() {
61 return ++current_rules_registry_id_;
64 void RulesRegistryService::EnsureDefaultRulesRegistriesRegistered(
65 int rules_registry_id) {
66 if (!browser_context_)
67 return;
68 RulesRegistryKey key(declarative_webrequest_constants::kOnRequest,
69 rules_registry_id);
70 // If we can find the key in the |rule_registries_| then we have already
71 // installed the default registries.
72 if (ContainsKey(rule_registries_, key))
73 return;
75 // Only cache rules for regular pages.
76 RulesCacheDelegate* web_request_cache_delegate = NULL;
77 if (rules_registry_id == kDefaultRulesRegistryID) {
78 // Create a RulesCacheDelegate.
79 web_request_cache_delegate =
80 new RulesCacheDelegate(true /*log_storage_init_delay*/);
81 cache_delegates_.push_back(web_request_cache_delegate);
83 scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry(
84 new WebRequestRulesRegistry(browser_context_, web_request_cache_delegate,
85 rules_registry_id));
87 RegisterRulesRegistry(web_request_rules_registry);
88 content::BrowserThread::PostTask(
89 content::BrowserThread::IO, FROM_HERE,
90 base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO,
91 browser_context_, rules_registry_id,
92 web_request_rules_registry));
94 // Only create a ContentRulesRegistry for regular pages.
95 if (rules_registry_id == kDefaultRulesRegistryID) {
96 RulesCacheDelegate* content_rules_cache_delegate =
97 new RulesCacheDelegate(false /*log_storage_init_delay*/);
98 cache_delegates_.push_back(content_rules_cache_delegate);
99 scoped_refptr<ContentRulesRegistry> content_rules_registry =
100 ExtensionsAPIClient::Get()->CreateContentRulesRegistry(
101 browser_context_, content_rules_cache_delegate);
102 if (content_rules_registry.get() != nullptr) {
103 RegisterRulesRegistry(content_rules_registry);
104 content_rules_registry_ = content_rules_registry.get();
109 void RulesRegistryService::Shutdown() {
110 // Release the references to all registries. This would happen soon during
111 // destruction of |*this|, but we need the ExtensionWebRequestEventRouter to
112 // be the last to reference the WebRequestRulesRegistry objects, so that
113 // the posted task below causes their destruction on the IO thread, not on UI
114 // where the destruction of |*this| takes place.
115 // TODO(vabr): Remove once http://crbug.com/218451#c6 gets addressed.
116 rule_registries_.clear();
117 content::BrowserThread::PostTask(
118 content::BrowserThread::IO, FROM_HERE,
119 base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO,
120 browser_context_,
121 RulesRegistryService::kDefaultRulesRegistryID,
122 scoped_refptr<WebRequestRulesRegistry>(NULL)));
125 static base::LazyInstance<BrowserContextKeyedAPIFactory<RulesRegistryService> >
126 g_factory = LAZY_INSTANCE_INITIALIZER;
128 // static
129 BrowserContextKeyedAPIFactory<RulesRegistryService>*
130 RulesRegistryService::GetFactoryInstance() {
131 return g_factory.Pointer();
134 // static
135 RulesRegistryService* RulesRegistryService::Get(
136 content::BrowserContext* context) {
137 return BrowserContextKeyedAPIFactory<RulesRegistryService>::Get(context);
140 void RulesRegistryService::RegisterRulesRegistry(
141 scoped_refptr<RulesRegistry> rule_registry) {
142 const std::string event_name(rule_registry->event_name());
143 RulesRegistryKey key(event_name, rule_registry->id());
144 DCHECK(rule_registries_.find(key) == rule_registries_.end());
145 rule_registries_[key] = rule_registry;
148 scoped_refptr<RulesRegistry> RulesRegistryService::GetRulesRegistry(
149 int rules_registry_id,
150 const std::string& event_name) {
151 EnsureDefaultRulesRegistriesRegistered(rules_registry_id);
153 RulesRegistryKey key(event_name, rules_registry_id);
154 RulesRegistryMap::const_iterator i = rule_registries_.find(key);
155 if (i == rule_registries_.end())
156 return scoped_refptr<RulesRegistry>();
157 return i->second;
160 void RulesRegistryService::RemoveRulesRegistriesByID(int rules_registry_id) {
161 std::set<RulesRegistryKey> registries_to_delete;
162 for (RulesRegistryMap::iterator it = rule_registries_.begin();
163 it != rule_registries_.end(); ++it) {
164 const RulesRegistryKey& key = it->first;
165 if (key.rules_registry_id != rules_registry_id)
166 continue;
167 // Modifying a container while iterating over it can lead to badness. So we
168 // save the keys in another container and delete them in another loop.
169 registries_to_delete.insert(key);
172 for (std::set<RulesRegistryKey>::iterator it = registries_to_delete.begin();
173 it != registries_to_delete.end(); ++it) {
174 rule_registries_.erase(*it);
178 void RulesRegistryService::SimulateExtensionUninstalled(
179 const Extension* extension) {
180 NotifyRegistriesHelper(&RulesRegistry::OnExtensionUninstalled, extension);
183 void RulesRegistryService::NotifyRegistriesHelper(
184 void (RulesRegistry::*notification_callback)(const Extension*),
185 const Extension* extension) {
186 RulesRegistryMap::iterator i;
187 for (i = rule_registries_.begin(); i != rule_registries_.end(); ++i) {
188 scoped_refptr<RulesRegistry> registry = i->second;
189 if (content::BrowserThread::CurrentlyOn(registry->owner_thread())) {
190 (registry.get()->*notification_callback)(extension);
191 } else {
192 content::BrowserThread::PostTask(
193 registry->owner_thread(), FROM_HERE,
194 base::Bind(&NotifyWithExtensionSafe, make_scoped_refptr(extension),
195 notification_callback, registry));
200 void RulesRegistryService::OnExtensionLoaded(
201 content::BrowserContext* browser_context,
202 const Extension* extension) {
203 NotifyRegistriesHelper(&RulesRegistry::OnExtensionLoaded, extension);
206 void RulesRegistryService::OnExtensionUnloaded(
207 content::BrowserContext* browser_context,
208 const Extension* extension,
209 UnloadedExtensionInfo::Reason reason) {
210 NotifyRegistriesHelper(&RulesRegistry::OnExtensionUnloaded, extension);
213 void RulesRegistryService::OnExtensionUninstalled(
214 content::BrowserContext* browser_context,
215 const Extension* extension,
216 extensions::UninstallReason reason) {
217 NotifyRegistriesHelper(&RulesRegistry::OnExtensionUninstalled, extension);
220 } // namespace extensions