When extension is blacklisted by admin policy, it should be removed if already running.
(Attempt 2 at landing this, this time with changes to fix Enabledness unit test)

BUG=51689
TEST=ExtensionsServiceTest.BlacklistedByPolicyRemovedIfRunning


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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56987 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index e9d635c..58ead19 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -204,6 +204,8 @@
                  NotificationService::AllSources());
   registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED,
                  Source<Profile>(profile_));
+  prefs->AddPrefObserver(prefs::kExtensionInstallAllowList, this);
+  prefs->AddPrefObserver(prefs::kExtensionInstallDenyList, this);
 
   // Set up the ExtensionUpdater
   if (autoupdate_enabled) {
@@ -218,7 +220,7 @@
 
   backend_ = new ExtensionsServiceBackend(install_directory_);
 
-  // Use monochrome icons for omnibox icons.
+  // Use monochrome icons for Omnibox icons.
   omnibox_icon_manager_.set_monochrome(true);
 }
 
@@ -794,6 +796,31 @@
   }
 }
 
+void ExtensionsService::DestroyingProfile() {
+  profile_->GetPrefs()->RemovePrefObserver(
+      prefs::kExtensionInstallAllowList, this);
+  profile_->GetPrefs()->RemovePrefObserver(
+      prefs::kExtensionInstallDenyList, this);
+
+  profile_ = NULL;
+}
+
+void ExtensionsService::CheckAdminBlacklist() {
+  std::vector<std::string> to_be_removed;
+  // Loop through extensions list, unload installed extensions.
+  for (ExtensionList::const_iterator iter = extensions_.begin();
+       iter != extensions_.end(); ++iter) {
+    Extension* extension = (*iter);
+    if (!extension_prefs_->IsExtensionAllowedByPolicy(extension->id()))
+      to_be_removed.push_back(extension->id());
+  }
+
+  // UnloadExtension will change the extensions_ list. So, we should
+  // call it outside the iterator loop.
+  for (unsigned int i = 0; i < to_be_removed.size(); ++i)
+    UnloadExtension(to_be_removed[i]);
+}
+
 bool ExtensionsService::IsIncognitoEnabled(const Extension* extension) {
   // If this is a component extension we always allow it to work in incognito
   // mode.
@@ -1337,6 +1364,14 @@
       break;
     }
 
+    case NotificationType::PREF_CHANGED: {
+      std::string* pref_name = Details<std::string>(details).ptr();
+      DCHECK(*pref_name == prefs::kExtensionInstallAllowList ||
+             *pref_name == prefs::kExtensionInstallDenyList);
+      CheckAdminBlacklist();
+      break;
+    }
+
     default:
       NOTREACHED() << "Unexpected notification type.";
   }