Convert ExtensionRegistry to a BrowserContextKeyedService

This removes dependencies on ExtensionService, which does not exist for
app_shell.

* Convert all of src/extensions to use ExtensionRegistry's extension sets.
* Remove ExtensionService::blacklisted_extensions() and convert all callers
  to use ExtensionRegistry.

BUG=none
TEST=existing unit_tests, browser_tests
[email protected]
[email protected] for adding dependency on components/browser_context_keyed_service

Review URL: https://codereview.chromium.org/120863003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@242624 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index ee9f6c3..fdfde83 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -329,7 +329,7 @@
       blacklist_(blacklist),
       settings_frontend_(extensions::SettingsFrontend::Create(profile)),
       extension_sync_service_(NULL),
-      registry_(new extensions::ExtensionRegistry),
+      registry_(extensions::ExtensionRegistry::Get(profile)),
       pending_extension_manager_(*this),
       install_directory_(install_directory),
       extensions_enabled_(extensions_enabled),
@@ -422,10 +422,6 @@
   return &registry_->terminated_extensions();
 }
 
-const ExtensionSet* ExtensionService::blacklisted_extensions() const {
-  return &registry_->blacklisted_extensions();
-}
-
 const ExtensionSet* ExtensionService::delayed_installs() const {
   return &delayed_installs_;
 }
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 8545283..f8a7bba4 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -161,8 +161,10 @@
   // Gets the list of currently installed extensions.
   virtual const extensions::ExtensionSet* extensions() const OVERRIDE;
   virtual const extensions::ExtensionSet* disabled_extensions() const OVERRIDE;
+
+  // DEPRECATED: Use extensions::ExtensionRegistry::terminated_extensions().
   const extensions::ExtensionSet* terminated_extensions() const;
-  const extensions::ExtensionSet* blacklisted_extensions() const;
+
   const extensions::ExtensionSet* delayed_installs() const;
 
   // Returns a set of all installed, disabled, blacklisted, and terminated
@@ -739,8 +741,8 @@
   // The ExtensionSyncService that is used by this ExtensionService.
   ExtensionSyncService* extension_sync_service_;
 
-  // TODO(jamescook): Convert this to a BrowserContextKeyedService.
-  scoped_ptr<extensions::ExtensionRegistry> registry_;
+  // Sets of enabled/disabled/terminated/blacklisted extensions. Not owned.
+  extensions::ExtensionRegistry* registry_;
 
   // The list of extension installs delayed for various reasons.  The reason
   // for delayed install is stored in ExtensionPrefs. These are not part of
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index bf5bed9..6dae5fc 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -87,6 +87,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_constants.h"
 #include "content/public/test/test_utils.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/external_provider_interface.h"
 #include "extensions/browser/management_policy.h"
 #include "extensions/browser/pending_extension_info.h"
@@ -151,6 +152,7 @@
 using extensions::Extension;
 using extensions::ExtensionCreator;
 using extensions::ExtensionPrefs;
+using extensions::ExtensionRegistry;
 using extensions::ExtensionResource;
 using extensions::ExtensionSystem;
 using extensions::FakeSafeBrowsingDatabaseManager;
@@ -3369,16 +3371,18 @@
   InitializeGoodInstalledExtensionService();
   service_->Init();
 
-  const extensions::ExtensionSet* extensions = service_->extensions();
-  const extensions::ExtensionSet* blacklisted_extensions =
-      service_->blacklisted_extensions();
+  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_.get());
+  const extensions::ExtensionSet& enabled_extensions =
+      registry->enabled_extensions();
+  const extensions::ExtensionSet& blacklisted_extensions =
+      registry->blacklisted_extensions();
 
-  EXPECT_TRUE( extensions->Contains(good0) &&
-              !blacklisted_extensions->Contains(good0));
-  EXPECT_TRUE( extensions->Contains(good1) &&
-              !blacklisted_extensions->Contains(good1));
-  EXPECT_TRUE( extensions->Contains(good2) &&
-              !blacklisted_extensions->Contains(good2));
+  EXPECT_TRUE(enabled_extensions.Contains(good0) &&
+              !blacklisted_extensions.Contains(good0));
+  EXPECT_TRUE(enabled_extensions.Contains(good1) &&
+              !blacklisted_extensions.Contains(good1));
+  EXPECT_TRUE(enabled_extensions.Contains(good2) &&
+              !blacklisted_extensions.Contains(good2));
 
   EXPECT_FALSE(IsPrefExist(good0, "blacklist"));
   EXPECT_FALSE(IsPrefExist(good1, "blacklist"));
@@ -3389,12 +3393,12 @@
   blacklist_db->SetUnsafe(good0, good1, "invalid_id").NotifyUpdate();
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_TRUE(!extensions->Contains(good0) &&
-               blacklisted_extensions->Contains(good0));
-  EXPECT_TRUE(!extensions->Contains(good1) &&
-               blacklisted_extensions->Contains(good1));
-  EXPECT_TRUE( extensions->Contains(good2) &&
-              !blacklisted_extensions->Contains(good2));
+  EXPECT_TRUE(!enabled_extensions.Contains(good0) &&
+              blacklisted_extensions.Contains(good0));
+  EXPECT_TRUE(!enabled_extensions.Contains(good1) &&
+              blacklisted_extensions.Contains(good1));
+  EXPECT_TRUE(enabled_extensions.Contains(good2) &&
+              !blacklisted_extensions.Contains(good2));
 
   EXPECT_TRUE(ValidateBooleanPref(good0, "blacklist", true));
   EXPECT_TRUE(ValidateBooleanPref(good1, "blacklist", true));
@@ -3405,12 +3409,12 @@
   blacklist_db->SetUnsafe(good0, good2, "invalid_id").NotifyUpdate();
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_TRUE(!extensions->Contains(good0) &&
-               blacklisted_extensions->Contains(good0));
-  EXPECT_TRUE( extensions->Contains(good1) &&
-              !blacklisted_extensions->Contains(good1));
-  EXPECT_TRUE(!extensions->Contains(good2) &&
-               blacklisted_extensions->Contains(good2));
+  EXPECT_TRUE(!enabled_extensions.Contains(good0) &&
+              blacklisted_extensions.Contains(good0));
+  EXPECT_TRUE(enabled_extensions.Contains(good1) &&
+              !blacklisted_extensions.Contains(good1));
+  EXPECT_TRUE(!enabled_extensions.Contains(good2) &&
+              blacklisted_extensions.Contains(good2));
 
   EXPECT_TRUE(ValidateBooleanPref(good0, "blacklist", true));
   EXPECT_FALSE(IsPrefExist(good1, "blacklist"));
@@ -3492,12 +3496,14 @@
   ASSERT_EQ(3u, loaded_.size());  // hasn't had time to blacklist yet
 
   base::RunLoop().RunUntilIdle();
-  ASSERT_EQ(1u, service_->blacklisted_extensions()->size());
-  ASSERT_EQ(2u, service_->extensions()->size());
 
-  ASSERT_TRUE(service_->extensions()->Contains(good0));
-  ASSERT_TRUE(service_->blacklisted_extensions()->Contains(good1));
-  ASSERT_TRUE(service_->extensions()->Contains(good2));
+  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_.get());
+  ASSERT_EQ(1u, registry->blacklisted_extensions().size());
+  ASSERT_EQ(2u, registry->enabled_extensions().size());
+
+  ASSERT_TRUE(registry->enabled_extensions().Contains(good0));
+  ASSERT_TRUE(registry->blacklisted_extensions().Contains(good1));
+  ASSERT_TRUE(registry->enabled_extensions().Contains(good2));
 }
 #endif  // defined(ENABLE_BLACKLIST_TESTS)
 
@@ -3517,22 +3523,23 @@
 
   service_->Init();
 
-  ASSERT_EQ(2u, service_->blacklisted_extensions()->size());
-  ASSERT_EQ(1u, service_->extensions()->size());
+  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_.get());
+  ASSERT_EQ(2u, registry->blacklisted_extensions().size());
+  ASSERT_EQ(1u, registry->enabled_extensions().size());
 
-  ASSERT_TRUE(service_->blacklisted_extensions()->Contains(good0));
-  ASSERT_TRUE(service_->blacklisted_extensions()->Contains(good1));
-  ASSERT_TRUE(service_->extensions()->Contains(good2));
+  ASSERT_TRUE(registry->blacklisted_extensions().Contains(good0));
+  ASSERT_TRUE(registry->blacklisted_extensions().Contains(good1));
+  ASSERT_TRUE(registry->enabled_extensions().Contains(good2));
 
   // Give time for the blacklist to update.
   base::RunLoop().RunUntilIdle();
 
-  ASSERT_EQ(1u, service_->blacklisted_extensions()->size());
-  ASSERT_EQ(2u, service_->extensions()->size());
+  ASSERT_EQ(1u, registry->blacklisted_extensions().size());
+  ASSERT_EQ(2u, registry->enabled_extensions().size());
 
-  ASSERT_TRUE(service_->extensions()->Contains(good0));
-  ASSERT_TRUE(service_->blacklisted_extensions()->Contains(good1));
-  ASSERT_TRUE(service_->extensions()->Contains(good2));
+  ASSERT_TRUE(registry->enabled_extensions().Contains(good0));
+  ASSERT_TRUE(registry->blacklisted_extensions().Contains(good1));
+  ASSERT_TRUE(registry->enabled_extensions().Contains(good2));
 }
 #endif  // defined(ENABLE_BLACKLIST_TESTS)
 
@@ -3915,37 +3922,40 @@
   InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
   EXPECT_TRUE(service_->GetExtensionById(good_crx, true));
   EXPECT_TRUE(service_->GetExtensionById(good_crx, false));
-  EXPECT_EQ(1u, service_->extensions()->size());
-  EXPECT_EQ(0u, service_->disabled_extensions()->size());
-  EXPECT_EQ(0u, service_->terminated_extensions()->size());
-  EXPECT_EQ(0u, service_->blacklisted_extensions()->size());
+
+  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_.get());
+  EXPECT_EQ(1u, registry->enabled_extensions().size());
+  EXPECT_EQ(0u, registry->disabled_extensions().size());
+  EXPECT_EQ(0u, registry->terminated_extensions().size());
+  EXPECT_EQ(0u, registry->blacklisted_extensions().size());
 
   // Disable it.
   service_->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
 
   EXPECT_TRUE(service_->GetExtensionById(good_crx, true));
   EXPECT_FALSE(service_->GetExtensionById(good_crx, false));
-  EXPECT_EQ(0u, service_->extensions()->size());
-  EXPECT_EQ(1u, service_->disabled_extensions()->size());
-  EXPECT_EQ(0u, service_->terminated_extensions()->size());
-  EXPECT_EQ(0u, service_->blacklisted_extensions()->size());
+  EXPECT_EQ(0u, registry->enabled_extensions().size());
+  EXPECT_EQ(1u, registry->disabled_extensions().size());
+  EXPECT_EQ(0u, registry->terminated_extensions().size());
+  EXPECT_EQ(0u, registry->blacklisted_extensions().size());
 }
 
 TEST_F(ExtensionServiceTest, TerminateExtension) {
   InitializeEmptyExtensionService();
 
   InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
-  EXPECT_EQ(1u, service_->extensions()->size());
-  EXPECT_EQ(0u, service_->disabled_extensions()->size());
-  EXPECT_EQ(0u, service_->terminated_extensions()->size());
-  EXPECT_EQ(0u, service_->blacklisted_extensions()->size());
+  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_.get());
+  EXPECT_EQ(1u, registry->enabled_extensions().size());
+  EXPECT_EQ(0u, registry->disabled_extensions().size());
+  EXPECT_EQ(0u, registry->terminated_extensions().size());
+  EXPECT_EQ(0u, registry->blacklisted_extensions().size());
 
   TerminateExtension(good_crx);
 
-  EXPECT_EQ(0u, service_->extensions()->size());
-  EXPECT_EQ(0u, service_->disabled_extensions()->size());
-  EXPECT_EQ(1u, service_->terminated_extensions()->size());
-  EXPECT_EQ(0u, service_->blacklisted_extensions()->size());
+  EXPECT_EQ(0u, registry->enabled_extensions().size());
+  EXPECT_EQ(0u, registry->disabled_extensions().size());
+  EXPECT_EQ(1u, registry->terminated_extensions().size());
+  EXPECT_EQ(0u, registry->blacklisted_extensions().size());
 }
 
 TEST_F(ExtensionServiceTest, DisableTerminatedExtension) {
@@ -3961,10 +3971,11 @@
   EXPECT_FALSE(service_->GetTerminatedExtension(good_crx));
   EXPECT_TRUE(service_->GetExtensionById(good_crx, true));
 
-  EXPECT_EQ(0u, service_->extensions()->size());
-  EXPECT_EQ(1u, service_->disabled_extensions()->size());
-  EXPECT_EQ(0u, service_->terminated_extensions()->size());
-  EXPECT_EQ(0u, service_->blacklisted_extensions()->size());
+  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_.get());
+  EXPECT_EQ(0u, registry->enabled_extensions().size());
+  EXPECT_EQ(1u, registry->disabled_extensions().size());
+  EXPECT_EQ(0u, registry->terminated_extensions().size());
+  EXPECT_EQ(0u, registry->blacklisted_extensions().size());
 }
 
 // Tests disabling all extensions (simulating --disable-extensions flag).
@@ -6703,10 +6714,12 @@
   // Extension was installed but not loaded.
   EXPECT_TRUE(notifications.CheckNotifications(
       chrome::NOTIFICATION_EXTENSION_INSTALLED));
-
   EXPECT_TRUE(service_->GetInstalledExtension(id));
-  EXPECT_FALSE(service_->extensions()->Contains(id));
-  EXPECT_TRUE(service_->blacklisted_extensions()->Contains(id));
+
+  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_.get());
+  EXPECT_FALSE(registry->enabled_extensions().Contains(id));
+  EXPECT_TRUE(registry->blacklisted_extensions().Contains(id));
+
   EXPECT_TRUE(service_->extension_prefs()->IsExtensionBlacklisted(id));
   EXPECT_TRUE(
       service_->extension_prefs()->IsBlacklistedExtensionAcknowledged(id));
diff --git a/chrome/browser/extensions/extension_system_factory.cc b/chrome/browser/extensions/extension_system_factory.cc
index 228d1969..3289e796 100644
--- a/chrome/browser/extensions/extension_system_factory.cc
+++ b/chrome/browser/extensions/extension_system_factory.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
 #include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+#include "extensions/browser/extension_registry_factory.h"
 #include "extensions/browser/extensions_browser_client.h"
 
 namespace extensions {
@@ -33,6 +34,8 @@
         "ExtensionSystemShared",
         BrowserContextDependencyManager::GetInstance()) {
   DependsOn(ExtensionPrefsFactory::GetInstance());
+  // This depends on ExtensionService which depends on ExtensionRegistry.
+  DependsOn(ExtensionRegistryFactory::GetInstance());
   DependsOn(GlobalErrorServiceFactory::GetInstance());
   DependsOn(policy::ProfilePolicyConnectorFactory::GetInstance());
 }
diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS
index 8bd19ef..a2c9650 100644
--- a/extensions/browser/DEPS
+++ b/extensions/browser/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+components/browser_context_keyed_service",
   "+content/public/browser",
   "+sync",
 
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc
index 5daabf0f..3c85b8b0 100644
--- a/extensions/browser/event_router.cc
+++ b/extensions/browser/event_router.cc
@@ -20,6 +20,7 @@
 #include "chrome/common/extensions/extension_messages.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_process_host.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extensions_browser_client.h"
 #include "extensions/browser/lazy_background_task_queue.h"
 #include "extensions/browser/process_manager.h"
@@ -482,12 +483,12 @@
     const std::string& extension_id,
     const linked_ptr<Event>& event,
     std::set<EventDispatchIdentifier>* already_dispatched) {
-  ExtensionService* service = ExtensionSystem::GetForBrowserContext(
-      browser_context_)->extension_service();
   // Check both the original and the incognito browser context to see if we
   // should load a lazy bg page to handle the event. The latter case
   // occurs in the case of split-mode extensions.
-  const Extension* extension = service->extensions()->GetByID(extension_id);
+  const Extension* extension =
+      ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
+          extension_id);
   if (!extension)
     return;
 
@@ -512,9 +513,9 @@
 void EventRouter::DispatchEventToProcess(const std::string& extension_id,
                                          content::RenderProcessHost* process,
                                          const linked_ptr<Event>& event) {
-  ExtensionService* service = ExtensionSystem::GetForBrowserContext(
-      browser_context_)->extension_service();
-  const Extension* extension = service->extensions()->GetByID(extension_id);
+  const Extension* extension =
+      ExtensionRegistry::Get(browser_context_)->enabled_extensions().GetByID(
+          extension_id);
 
   // The extension could have been removed, but we do not unregister it until
   // the extension process is unloaded.
@@ -617,9 +618,9 @@
   EventRouter* event_router = extension_system->event_router();
   if (!event_router)
     return;
-  ExtensionService* extension_service = extension_system->extension_service();
   const Extension* extension =
-      extension_service->extensions()->GetByID(extension_id);
+      ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
+          extension_id);
   if (!extension)
     return;
   event_router->IncrementInFlightEvents(browser_context, extension);
diff --git a/extensions/browser/extension_registry.cc b/extensions/browser/extension_registry.cc
index 9391b40..f4bd91e1 100644
--- a/extensions/browser/extension_registry.cc
+++ b/extensions/browser/extension_registry.cc
@@ -4,11 +4,18 @@
 
 #include "extensions/browser/extension_registry.h"
 
+#include "extensions/browser/extension_registry_factory.h"
+
 namespace extensions {
 
 ExtensionRegistry::ExtensionRegistry() {}
 ExtensionRegistry::~ExtensionRegistry() {}
 
+// static
+ExtensionRegistry* ExtensionRegistry::Get(content::BrowserContext* context) {
+  return ExtensionRegistryFactory::GetForBrowserContext(context);
+}
+
 bool ExtensionRegistry::AddEnabled(
     const scoped_refptr<const Extension>& extension) {
   return enabled_extensions_.Insert(extension);
@@ -57,4 +64,9 @@
   disabled_extensions_.set_modification_callback(callback);
 }
 
+void ExtensionRegistry::Shutdown() {
+  // Release references to all Extension objects in the sets.
+  ClearAll();
+}
+
 }  // namespace extensions
diff --git a/extensions/browser/extension_registry.h b/extensions/browser/extension_registry.h
index c051fbb6..aedd11a 100644
--- a/extensions/browser/extension_registry.h
+++ b/extensions/browser/extension_registry.h
@@ -7,19 +7,28 @@
 
 #include <string>
 
+#include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
 #include "extensions/common/extension_set.h"
 
+namespace content {
+class BrowserContext;
+}
+
 namespace extensions {
 class Extension;
 
 // ExtensionRegistry holds sets of the installed extensions for a given
-// BrowserContext.
-// TODO(jamescook): Convert this to a BrowserContextKeyedService.
-class ExtensionRegistry {
+// BrowserContext. An incognito browser context and its master browser context
+// share a single registry.
+class ExtensionRegistry : public BrowserContextKeyedService {
  public:
   ExtensionRegistry();
-  ~ExtensionRegistry();
+  virtual ~ExtensionRegistry();
+
+  // Returns the instance for the given |browser_context|.
+  static ExtensionRegistry* Get(content::BrowserContext* browser_context);
 
   // NOTE: These sets are *eventually* mututally exclusive, but an extension can
   // appear in two sets for short periods of time.
@@ -70,6 +79,9 @@
   void SetDisabledModificationCallback(
       const ExtensionSet::ModificationCallback& callback);
 
+  // BrowserContextKeyedService implementation:
+  virtual void Shutdown() OVERRIDE;
+
  private:
   // Extensions that are installed, enabled and not terminated.
   ExtensionSet enabled_extensions_;
diff --git a/extensions/browser/extension_registry_factory.cc b/extensions/browser/extension_registry_factory.cc
new file mode 100644
index 0000000..6451bd5
--- /dev/null
+++ b/extensions/browser/extension_registry_factory.cc
@@ -0,0 +1,47 @@
+// Copyright 2013 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.
+
+#include "extensions/browser/extension_registry_factory.h"
+
+#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extensions_browser_client.h"
+
+using content::BrowserContext;
+
+namespace extensions {
+
+// static
+ExtensionRegistry* ExtensionRegistryFactory::GetForBrowserContext(
+      BrowserContext* context) {
+  return static_cast<ExtensionRegistry*>(
+      GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+// static
+ExtensionRegistryFactory* ExtensionRegistryFactory::GetInstance() {
+  return Singleton<ExtensionRegistryFactory>::get();
+}
+
+ExtensionRegistryFactory::ExtensionRegistryFactory()
+    : BrowserContextKeyedServiceFactory(
+          "ExtensionRegistry",
+          BrowserContextDependencyManager::GetInstance()) {
+  // No dependencies on other services.
+}
+
+ExtensionRegistryFactory::~ExtensionRegistryFactory() {}
+
+BrowserContextKeyedService* ExtensionRegistryFactory::BuildServiceInstanceFor(
+      content::BrowserContext* profile) const {
+  return new ExtensionRegistry;
+}
+
+BrowserContext* ExtensionRegistryFactory::GetBrowserContextToUse(
+      BrowserContext* context) const {
+  // Redirected in incognito.
+  return ExtensionsBrowserClient::Get()->GetOriginalContext(context);
+}
+
+}  // namespace extensions
diff --git a/extensions/browser/extension_registry_factory.h b/extensions/browser/extension_registry_factory.h
new file mode 100644
index 0000000..e99c4d87
--- /dev/null
+++ b/extensions/browser/extension_registry_factory.h
@@ -0,0 +1,43 @@
+// Copyright 2013 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_EXTENSION_REGISTRY_FACTORY_H_
+#define EXTENSIONS_BROWSER_EXTENSION_REGISTRY_FACTORY_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/singleton.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
+
+namespace extensions {
+
+class ExtensionRegistry;
+
+// Factory for ExtensionRegistry objects. ExtensionRegistry objects are shared
+// between an incognito browser context and its master browser context.
+class ExtensionRegistryFactory : public BrowserContextKeyedServiceFactory {
+ public:
+  static ExtensionRegistry* GetForBrowserContext(
+      content::BrowserContext* context);
+
+  static ExtensionRegistryFactory* GetInstance();
+
+ private:
+  friend struct DefaultSingletonTraits<ExtensionRegistryFactory>;
+
+  ExtensionRegistryFactory();
+  virtual ~ExtensionRegistryFactory();
+
+  // BrowserContextKeyedServiceFactory implementation:
+  virtual BrowserContextKeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* profile) const OVERRIDE;
+  virtual content::BrowserContext* GetBrowserContextToUse(
+      content::BrowserContext* context) const OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ExtensionRegistryFactory);
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_BROWSER_EXTENSION_REGISTRY_FACTORY_H_
diff --git a/extensions/browser/lazy_background_task_queue.cc b/extensions/browser/lazy_background_task_queue.cc
index f53cdd3..2a525031 100644
--- a/extensions/browser/lazy_background_task_queue.cc
+++ b/extensions/browser/lazy_background_task_queue.cc
@@ -7,7 +7,6 @@
 #include "base/callback.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_host.h"
-#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_system.h"
 #include "chrome/common/extensions/extension_messages.h"
 #include "content/public/browser/browser_context.h"
@@ -16,6 +15,7 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extensions_browser_client.h"
 #include "extensions/browser/process_manager.h"
 #include "extensions/browser/process_map.h"
@@ -73,11 +73,9 @@
     tasks_list = new PendingTasksList();
     pending_tasks_[key] = linked_ptr<PendingTasksList>(tasks_list);
 
-    ExtensionService* extension_service = ExtensionSystem::GetForBrowserContext(
-        browser_context)->extension_service();
-    DCHECK(extension_service);
     const Extension* extension =
-        extension_service->extensions()->GetByID(extension_id);
+        ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
+            extension_id);
     if (extension && BackgroundInfo::HasLazyBackgroundPage(extension)) {
       // If this is the first enqueued task, and we're not waiting for the
       // background page to unload, ensure the background page is loaded.
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc
index 0ffba2ac..1162b81 100644
--- a/extensions/browser/process_manager.cc
+++ b/extensions/browser/process_manager.cc
@@ -33,6 +33,7 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 #include "content/public/common/renderer_preferences.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extensions_browser_client.h"
 #include "extensions/browser/view_type_utils.h"
 #include "extensions/common/extension.h"
@@ -301,12 +302,12 @@
   if (!render_view_host->GetSiteInstance())
     return NULL;
 
-  ExtensionService* service = ExtensionSystem::GetForBrowserContext(
-      GetBrowserContext())->extension_service();
-  if (!service)
+  ExtensionRegistry* registry = ExtensionRegistry::Get(GetBrowserContext());
+  if (!registry)
     return NULL;
 
-  return service->extensions()->GetByID(GetExtensionID(render_view_host));
+  return registry->enabled_extensions().GetByID(
+      GetExtensionID(render_view_host));
 }
 
 void ProcessManager::UnregisterRenderViewHost(
@@ -702,11 +703,11 @@
     return;
   }
 
-  ExtensionService* service = ExtensionSystem::GetForBrowserContext(
-      GetBrowserContext())->extension_service();
-  DCHECK(service);
-  for (ExtensionSet::const_iterator extension = service->extensions()->begin();
-       extension != service->extensions()->end(); ++extension) {
+  const ExtensionSet& enabled_extensions =
+      ExtensionRegistry::Get(GetBrowserContext())->enabled_extensions();
+  for (ExtensionSet::const_iterator extension = enabled_extensions.begin();
+       extension != enabled_extensions.end();
+       ++extension) {
     CreateBackgroundHostForExtensionLoad(this, extension->get());
 
     RuntimeEventRouter::DispatchOnStartupEvent(GetBrowserContext(),
@@ -841,11 +842,10 @@
 }
 
 SiteInstance* IncognitoProcessManager::GetSiteInstanceForURL(const GURL& url) {
-  ExtensionService* service = ExtensionSystem::GetForBrowserContext(
-      GetBrowserContext())->extension_service();
-  if (service) {
+  ExtensionRegistry* registry = ExtensionRegistry::Get(GetBrowserContext());
+  if (registry) {
     const Extension* extension =
-        service->extensions()->GetExtensionOrAppByURL(url);
+        registry->enabled_extensions().GetExtensionOrAppByURL(url);
     if (extension && !IncognitoInfo::IsSplitMode(extension)) {
       return original_manager_->GetSiteInstanceForURL(url);
     }
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp
index fa07292..0ca42f8 100644
--- a/extensions/extensions.gyp
+++ b/extensions/extensions.gyp
@@ -171,6 +171,8 @@
         'browser/extension_function.h',
         'browser/extension_registry.cc',
         'browser/extension_registry.h',
+        'browser/extension_registry_factory.cc',
+        'browser/extension_registry_factory.h',
         'browser/extensions_browser_client.cc',
         'browser/extensions_browser_client.h',
         'browser/external_provider_interface.h',