15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/declarative/rules_registry_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/lazy_instance.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/declarative/initializing_rules_registry.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/declarative_content/content_rules_registry.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/web_request/web_request_api.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Registers |web_request_rules_registry| on the IO thread.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RegisterToExtensionWebRequestEventRouterOnIO(
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionWebRequestEventRouter::GetInstance()->RegisterRulesRegistry(
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile, web_request_rules_registry);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RulesRegistryService::RulesRegistryService(Profile* profile)
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : content_rules_registry_(NULL),
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      profile_(profile) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (profile) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        content::Source<Profile>(profile->GetOriginalProfile()));
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RegisterDefaultRulesRegistries();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)RulesRegistryService::~RulesRegistryService() {}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RulesRegistryService::RegisterDefaultRulesRegistries() {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<RulesRegistryWithCache::RuleStorageOnUI> ui_part;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry(
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new WebRequestRulesRegistry(profile_, &ui_part));
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ui_parts_of_registries_.push_back(ui_part.release());
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RegisterRulesRegistry(web_request_rules_registry);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::BrowserThread::PostTask(
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::BrowserThread::IO, FROM_HERE,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          profile_, web_request_rules_registry));
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(ENABLE_EXTENSIONS)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<ContentRulesRegistry> content_rules_registry(
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new ContentRulesRegistry(profile_, &ui_part));
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ui_parts_of_registries_.push_back(ui_part.release());
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RegisterRulesRegistry(content_rules_registry);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content_rules_registry_ = content_rules_registry.get();
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(ENABLE_EXTENSIONS)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RulesRegistryService::Shutdown() {
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Release the references to all registries. This would happen soon during
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // destruction of |*this|, but we need the ExtensionWebRequestEventRouter to
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // be the last to reference the WebRequestRulesRegistry objects, so that
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // the posted task below causes their destruction on the IO thread, not on UI
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // where the destruction of |*this| takes place.
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(vabr): Remove once http://crbug.com/218451#c6 gets addressed.
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  rule_registries_.clear();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::BrowserThread::PostTask(
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::BrowserThread::IO, FROM_HERE,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          profile_, scoped_refptr<WebRequestRulesRegistry>(NULL)));
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static base::LazyInstance<ProfileKeyedAPIFactory<RulesRegistryService> >
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)g_factory = LAZY_INSTANCE_INITIALIZER;
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ProfileKeyedAPIFactory<RulesRegistryService>*
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)RulesRegistryService::GetFactoryInstance() {
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return &g_factory.Get();
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)RulesRegistryService* RulesRegistryService::Get(Profile* profile) {
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return ProfileKeyedAPIFactory<RulesRegistryService>::GetForProfile(profile);
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RulesRegistryService::RegisterRulesRegistry(
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<RulesRegistry> rule_registry) {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string event_name(rule_registry->event_name());
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(rule_registries_.find(event_name) == rule_registries_.end());
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rule_registries_[event_name] =
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      make_scoped_refptr(new InitializingRulesRegistry(rule_registry));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<RulesRegistry> RulesRegistryService::GetRulesRegistry(
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name) const {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RulesRegistryMap::const_iterator i = rule_registries_.find(event_name);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == rule_registries_.end())
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return scoped_refptr<RulesRegistry>();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return i->second;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RulesRegistryService::SimulateExtensionUnloaded(
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnExtensionUnloaded(extension_id);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RulesRegistryService::OnExtensionUnloaded(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RulesRegistryMap::iterator i;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = rule_registries_.begin(); i != rule_registries_.end(); ++i) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<RulesRegistry> registry = i->second;
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (content::BrowserThread::CurrentlyOn(registry->owner_thread())) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      registry->OnExtensionUnloaded(extension_id);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::BrowserThread::PostTask(
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          registry->owner_thread(),
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          FROM_HERE,
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              &RulesRegistry::OnExtensionUnloaded, registry, extension_id));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RulesRegistryService::Observe(
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int type,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationSource& source,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::NotificationDetails& details) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Extension* extension =
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Details<UnloadedExtensionInfo>(details)->extension;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnExtensionUnloaded(extension->id());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
153