External extensions should be uninstalled when removed from external source.

This was broken for external_extensions.json key "update_url".

BUG=57044
TEST=ExtensionsServiceTest.ExternalInstallPrefUpdateUrl

Review URL: http://codereview.chromium.org/3471022

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60944 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 017890f..737f6894 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -272,7 +272,9 @@
   // Whether errors result in noisy alerts.
   bool alert_on_error_;
 
-  // A map of all external extension providers.
+  // A map from external extension type to the external extension provider
+  // for that type.  Because a single provider may handle more than one
+  // external extension type, more than one key may map to the same object.
   typedef std::map<Extension::Location,
                    linked_ptr<ExternalExtensionProvider> > ProviderMap;
   ProviderMap external_extension_providers_;
@@ -301,6 +303,10 @@
   external_extension_providers_[Extension::EXTERNAL_PREF] =
       linked_ptr<ExternalExtensionProvider>(
           new ExternalPrefExtensionProvider());
+  // EXTERNAL_PREF_DOWNLOAD and EXTERNAL_PREF extensions are handled by the
+  // same object.
+  external_extension_providers_[Extension::EXTERNAL_PREF_DOWNLOAD] =
+      external_extension_providers_[Extension::EXTERNAL_PREF];
 #if defined(OS_WIN)
   external_extension_providers_[Extension::EXTERNAL_REGISTRY] =
       linked_ptr<ExternalExtensionProvider>(
@@ -1024,8 +1030,7 @@
 
   OnExtensionLoaded(extension, true);
 
-  if (info.extension_location == Extension::EXTERNAL_PREF ||
-      info.extension_location == Extension::EXTERNAL_REGISTRY) {
+  if (Extension::IsExternalLocation(info.extension_location)) {
     ChromeThread::PostTask(
         ChromeThread::FILE, FROM_HERE,
         NewRunnableMethod(
diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc
index 7781945..9fddb71 100644
--- a/chrome/browser/extensions/extensions_service_unittest.cc
+++ b/chrome/browser/extensions/extensions_service_unittest.cc
@@ -2321,6 +2321,18 @@
   TestExternalProvider(pref_provider, Extension::EXTERNAL_PREF);
 }
 
+TEST_F(ExtensionsServiceTest, ExternalInstallPrefUpdateUrl) {
+  // This should all work, even when normal extension installation is disabled.
+  InitializeEmptyExtensionsService();
+  set_extensions_enabled(false);
+
+  // Now add providers. Extension system takes ownership of the objects.
+  MockExtensionProvider* pref_provider =
+      new MockExtensionProvider(Extension::EXTERNAL_PREF_DOWNLOAD);
+  SetMockExternalProvider(Extension::EXTERNAL_PREF_DOWNLOAD, pref_provider);
+  TestExternalProvider(pref_provider, Extension::EXTERNAL_PREF_DOWNLOAD);
+}
+
 TEST_F(ExtensionsServiceTest, ExternalPrefProvider) {
   InitializeEmptyExtensionsService();
   std::string json_data =