summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authordanno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-10 13:55:18 +0000
committerdanno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-10 13:55:18 +0000
commit492d214950b16d229ced62021486e9e0ec859e40 (patch)
treeac098e0dc234b894433b13d409ddb198cd9d24b1 /chrome
parent0ef5163fe4f9a76f516f09f7aa9d19c322e79691 (diff)
downloadchromium_src-492d214950b16d229ced62021486e9e0ec859e40.zip
chromium_src-492d214950b16d229ced62021486e9e0ec859e40.tar.gz
chromium_src-492d214950b16d229ced62021486e9e0ec859e40.tar.bz2
Policy: plugins disabled by policy should honor policy changes without Chrome relaunch.
BUG=54620 TEST=PrefChangeRegistrarTest.* Review URL: http://codereview.chromium.org/3316007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@59094 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/browser_process_impl.cc8
-rw-r--r--chrome/browser/browser_process_impl.h5
-rw-r--r--chrome/browser/dom_ui/plugins_ui.cc41
-rw-r--r--chrome/browser/plugin_service.cc4
-rw-r--r--chrome/browser/plugin_updater.cc137
-rw-r--r--chrome/browser/plugin_updater.h69
-rw-r--r--chrome/browser/prefs/pref_change_registrar.cc53
-rw-r--r--chrome/browser/prefs/pref_change_registrar.h50
-rw-r--r--chrome/browser/prefs/pref_change_registrar_unittest.cc90
-rw-r--r--chrome/browser/prefs/pref_service.h2
-rw-r--r--chrome/browser/resources/plugins.html1
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/notification_type.h4
-rw-r--r--chrome/common/plugin_group.cc2
-rw-r--r--chrome/common/plugin_group.h3
16 files changed, 401 insertions, 71 deletions
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 472464f..539bf57 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -37,6 +37,7 @@
#include "chrome/browser/net/sqlite_persistent_cookie_store.h"
#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/browser/plugin_service.h"
+#include "chrome/browser/plugin_updater.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/profile_manager.h"
@@ -605,6 +606,13 @@ void BrowserProcessImpl::CreateLocalState() {
FilePath local_state_path;
PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
local_state_.reset(PrefService::CreatePrefService(local_state_path, NULL));
+
+ // Make sure the the plugin updater gets notifications of changes
+ // in the plugin blacklist.
+ local_state_->RegisterListPref(prefs::kPluginsPluginsBlacklist);
+ plugin_state_change_registrar_.Init(local_state_.get());
+ plugin_state_change_registrar_.Add(prefs::kPluginsPluginsBlacklist,
+ PluginUpdater::GetPluginUpdater());
}
void BrowserProcessImpl::CreateIconManager() {
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index 0ae2de6..a5bbca0 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -19,6 +19,7 @@
#include "base/timer.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/pref_change_registrar.h"
#include "chrome/browser/tab_contents/thumbnail_generator.h"
#include "ipc/ipc_message.h"
@@ -194,6 +195,10 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe {
// Our best estimate about the existence of the inspector directory.
bool have_inspector_files_;
+ // Ensures that the observer of plugin disable/enable state
+ // notifications are properly added and removed.
+ PrefChangeRegistrar plugin_state_change_registrar_;
+
#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
base::RepeatingTimer<BrowserProcessImpl> autoupdate_timer_;
diff --git a/chrome/browser/dom_ui/plugins_ui.cc b/chrome/browser/dom_ui/plugins_ui.cc
index a52fc88..1d2d347 100644
--- a/chrome/browser/dom_ui/plugins_ui.cc
+++ b/chrome/browser/dom_ui/plugins_ui.cc
@@ -21,8 +21,10 @@
#include "chrome/browser/plugin_updater.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/jstemplate_builder.h"
+#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "grit/browser_resources.h"
@@ -127,9 +129,10 @@ void PluginsUIHTMLSource::StartDataRequest(const std::string& path,
// TODO(viettrungluu): Make plugin list updates notify, and then observe
// changes; maybe replumb plugin list through plugin service?
// <http://crbug.com/39101>
-class PluginsDOMHandler : public DOMMessageHandler {
+class PluginsDOMHandler : public DOMMessageHandler,
+ public NotificationObserver {
public:
- PluginsDOMHandler() {}
+ explicit PluginsDOMHandler();
virtual ~PluginsDOMHandler() {}
// DOMMessageHandler implementation.
@@ -146,10 +149,23 @@ class PluginsDOMHandler : public DOMMessageHandler {
// the security model.
void HandleShowTermsOfServiceMessage(const ListValue* args);
+ // NotificationObserver method overrides
+ void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
private:
+ NotificationRegistrar registrar_;
+
DISALLOW_COPY_AND_ASSIGN(PluginsDOMHandler);
};
+PluginsDOMHandler::PluginsDOMHandler() {
+ registrar_.Add(this,
+ NotificationType::PLUGIN_ENABLE_STATUS_CHANGED,
+ NotificationService::AllSources());
+}
+
void PluginsDOMHandler::RegisterMessages() {
dom_ui_->RegisterMessageCallback("requestPluginsData",
NewCallback(this, &PluginsDOMHandler::HandleRequestPluginsData));
@@ -161,7 +177,8 @@ void PluginsDOMHandler::RegisterMessages() {
void PluginsDOMHandler::HandleRequestPluginsData(const ListValue* args) {
DictionaryValue results;
- results.Set("plugins", plugin_updater::GetPluginGroupsData());
+ results.Set("plugins",
+ PluginUpdater::GetPluginUpdater()->GetPluginGroupsData());
dom_ui_->CallJavascriptFunction(L"returnPluginsData", results);
}
@@ -181,19 +198,21 @@ void PluginsDOMHandler::HandleEnablePluginMessage(const ListValue* args) {
if (!args->GetString(0, &group_name))
return;
- plugin_updater::EnablePluginGroup(enable_str == "true", group_name);
+ PluginUpdater::GetPluginUpdater()->EnablePluginGroup(
+ enable_str == "true", group_name);
} else {
FilePath::StringType file_path;
if (!args->GetString(0, &file_path))
return;
- plugin_updater::EnablePluginFile(enable_str == "true", file_path);
+ PluginUpdater::GetPluginUpdater()->EnablePluginFile(
+ enable_str == "true", file_path);
}
// TODO(viettrungluu): We might also want to ensure that the plugins
// list is always written to prefs even when the user hasn't disabled a
// plugin. <http://crbug.com/39101>
- plugin_updater::UpdatePreferences(dom_ui_->GetProfile());
+ PluginUpdater::GetPluginUpdater()->UpdatePreferences(dom_ui_->GetProfile());
}
void PluginsDOMHandler::HandleShowTermsOfServiceMessage(const ListValue* args) {
@@ -204,6 +223,16 @@ void PluginsDOMHandler::HandleShowTermsOfServiceMessage(const ListValue* args) {
browser->window()->Show();
}
+void PluginsDOMHandler::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK_EQ(NotificationType::PLUGIN_ENABLE_STATUS_CHANGED, type.value);
+ DictionaryValue results;
+ results.Set("plugins",
+ PluginUpdater::GetPluginUpdater()->GetPluginGroupsData());
+ dom_ui_->CallJavascriptFunction(L"returnPluginsData", results);
+}
+
} // namespace
///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc
index 5ab9368..c1d7e02 100644
--- a/chrome/browser/plugin_service.cc
+++ b/chrome/browser/plugin_service.cc
@@ -61,11 +61,11 @@ void PluginService::InitGlobalInstance(Profile* profile) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
// We first group the plugins and then figure out which groups to disable.
- plugin_updater::DisablePluginGroupsFromPrefs(profile);
+ PluginUpdater::GetPluginUpdater()->DisablePluginGroupsFromPrefs(profile);
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableOutdatedPlugins)) {
- plugin_updater::DisableOutdatedPluginGroups();
+ PluginUpdater::GetPluginUpdater()->DisableOutdatedPluginGroups();
}
// Have Chrome plugins write their data to the profile directory.
diff --git a/chrome/browser/plugin_updater.cc b/chrome/browser/plugin_updater.cc
index ab303ba..280db00 100644
--- a/chrome/browser/plugin_updater.cc
+++ b/chrome/browser/plugin_updater.cc
@@ -16,15 +16,17 @@
#include "chrome/browser/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/notification_service.h"
#include "chrome/common/plugin_group.h"
#include "chrome/common/pref_names.h"
#include "webkit/glue/plugins/plugin_list.h"
#include "webkit/glue/plugins/webplugininfo.h"
-namespace plugin_updater {
+PluginUpdater::PluginUpdater() : enable_internal_pdf_(true) {
+}
// Convert to a List of Groups
-static void GetPluginGroups(
+void PluginUpdater::GetPluginGroups(
std::vector<linked_ptr<PluginGroup> >* plugin_groups) {
// Read all plugins and convert them to plugin groups
std::vector<WebPluginInfo> web_plugins;
@@ -44,7 +46,7 @@ static void GetPluginGroups(
}
}
-static DictionaryValue* CreatePluginFileSummary(
+DictionaryValue* PluginUpdater::CreatePluginFileSummary(
const WebPluginInfo& plugin) {
DictionaryValue* data = new DictionaryValue();
data->SetString("path", plugin.path.value());
@@ -54,7 +56,7 @@ static DictionaryValue* CreatePluginFileSummary(
return data;
}
-ListValue* GetPluginGroupsData() {
+ListValue* PluginUpdater::GetPluginGroupsData() {
std::vector<linked_ptr<PluginGroup> > plugin_groups;
GetPluginGroups(&plugin_groups);
@@ -69,7 +71,7 @@ ListValue* GetPluginGroupsData() {
return plugin_groups_data;
}
-void EnablePluginGroup(bool enable, const string16& group_name) {
+void PluginUpdater::EnablePluginGroup(bool enable, const string16& group_name) {
std::vector<linked_ptr<PluginGroup> > plugin_groups;
GetPluginGroups(&plugin_groups);
@@ -78,24 +80,96 @@ void EnablePluginGroup(bool enable, const string16& group_name) {
it != plugin_groups.end();
++it) {
if ((*it)->GetGroupName() == group_name) {
- (*it)->Enable(enable);
+ if (PluginGroup::IsPluginNameDisabledByPolicy(group_name))
+ enable = false;
+ if ((*it)->Enabled() != enable) {
+ (*it)->Enable(enable);
+ NotificationService::current()->Notify(
+ NotificationType::PLUGIN_ENABLE_STATUS_CHANGED,
+ Source<PluginUpdater>(this),
+ NotificationService::NoDetails());
+ }
+ return;
}
}
}
-void EnablePluginFile(bool enable, const FilePath::StringType& path) {
+void PluginUpdater::EnablePluginFile(bool enable,
+ const FilePath::StringType& path) {
FilePath file_path(path);
if (enable && !PluginGroup::IsPluginPathDisabledByPolicy(file_path))
NPAPI::PluginList::Singleton()->EnablePlugin(file_path);
else
NPAPI::PluginList::Singleton()->DisablePlugin(file_path);
+
+ NotificationService::current()->Notify(
+ NotificationType::PLUGIN_ENABLE_STATUS_CHANGED,
+ Source<PluginUpdater>(this),
+ NotificationService::NoDetails());
+}
+
+void PluginUpdater::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK_EQ(NotificationType::PREF_CHANGED, type.value);
+ const std::string* pref_name = Details<std::string>(details).ptr();
+ if (!pref_name) {
+ NOTREACHED();
+ return;
+ }
+ if (*pref_name == prefs::kPluginsPluginsBlacklist) {
+ PrefService* pref_service = Source<PrefService>(source).ptr();
+ const ListValue* list =
+ pref_service->GetList(prefs::kPluginsPluginsBlacklist);
+ DisablePluginsFromPolicy(list);
+ }
}
-// Note: if you change this to false from true, you must update
-// kPluginsEnabledInternalPDF to be a new name (i.e. add 2, 3, 4...) at end.
-static bool enable_internal_pdf_ = true;
+void PluginUpdater::DisablePluginsFromPolicy(const ListValue* plugin_names) {
+ // Generate the set of unique disabled plugins from the disabled
+ // plugins list.
+ std::set<string16> policy_disabled_plugins;
+ if (plugin_names) {
+ ListValue::const_iterator end(plugin_names->end());
+ for (ListValue::const_iterator current(plugin_names->begin());
+ current != end; ++current) {
+ string16 plugin_name;
+ if ((*current)->GetAsString(&plugin_name)) {
+ policy_disabled_plugins.insert(plugin_name);
+ }
+ }
+ }
+ PluginGroup::SetPolicyDisabledPluginSet(policy_disabled_plugins);
+
+ // Disable all of the plugins and plugin groups that are disabled by policy.
+ // There's currenly a bug that makes it impossible to correctly re-enable
+ // plugins or plugin-groups to their original, "pre-policy" state, so
+ // plugins and grousp are only changed to a more "safe" state after a policy
+ // change, i.e. from enabled to disabled. See bug 54681.
+ std::vector<WebPluginInfo> plugins;
+ NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
+ for (std::vector<WebPluginInfo>::const_iterator plugin_iter = plugins.begin();
+ plugin_iter != plugins.end(); ++plugin_iter) {
+ if (PluginGroup::IsPluginNameDisabledByPolicy(plugin_iter->name))
+ NPAPI::PluginList::Singleton()->DisablePlugin(plugin_iter->path);
+ }
+
+ std::vector<linked_ptr<PluginGroup> > plugin_groups;
+ GetPluginGroups(&plugin_groups);
+ std::vector<linked_ptr<PluginGroup> >::iterator it;
+ for (it = plugin_groups.begin(); it != plugin_groups.end(); ++it) {
+ string16 current_group_name = (*it)->GetGroupName();
+ if (PluginGroup::IsPluginNameDisabledByPolicy(current_group_name))
+ (*it)->Enable(false);
+ }
-void DisablePluginGroupsFromPrefs(Profile* profile) {
+ NotificationService::current()->Notify(
+ NotificationType::PLUGIN_ENABLE_STATUS_CHANGED,
+ Source<PluginUpdater>(this),
+ NotificationService::NoDetails());
+}
+
+void PluginUpdater::DisablePluginGroupsFromPrefs(Profile* profile) {
bool update_internal_dir = false;
bool update_preferences = false;
FilePath last_internal_dir =
@@ -187,39 +261,9 @@ void DisablePluginGroupsFromPrefs(Profile* profile) {
// Build the set of policy-disabled plugins once and cache it.
// Don't do this in the constructor, there's no profile available there.
- std::set<string16> policy_disabled_plugins;
const ListValue* plugin_blacklist =
profile->GetPrefs()->GetList(prefs::kPluginsPluginsBlacklist);
- if (plugin_blacklist) {
- ListValue::const_iterator end(plugin_blacklist->end());
- for (ListValue::const_iterator current(plugin_blacklist->begin());
- current != end; ++current) {
- string16 plugin_name;
- if ((*current)->GetAsString(&plugin_name)) {
- policy_disabled_plugins.insert(plugin_name);
- }
- }
- }
- PluginGroup::SetPolicyDisabledPluginSet(policy_disabled_plugins);
-
- // Disable all of the plugins and plugin groups that are disabled by policy.
- std::vector<WebPluginInfo> plugins;
- NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
- for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin();
- it != plugins.end();
- ++it) {
- if (PluginGroup::IsPluginNameDisabledByPolicy(it->name))
- NPAPI::PluginList::Singleton()->DisablePlugin(it->path);
- }
-
- std::vector<linked_ptr<PluginGroup> > plugin_groups;
- GetPluginGroups(&plugin_groups);
- std::vector<linked_ptr<PluginGroup> >::const_iterator it;
- for (it = plugin_groups.begin(); it != plugin_groups.end(); ++it) {
- string16 current_group_name = (*it)->GetGroupName();
- if (PluginGroup::IsPluginNameDisabledByPolicy(current_group_name))
- EnablePluginGroup(false, current_group_name);
- }
+ DisablePluginsFromPolicy(plugin_blacklist);
if (!enable_internal_pdf_ && !found_internal_pdf) {
// The internal PDF plugin is disabled by default, and the user hasn't
@@ -231,7 +275,7 @@ void DisablePluginGroupsFromPrefs(Profile* profile) {
UpdatePreferences(profile);
}
-void DisableOutdatedPluginGroups() {
+void PluginUpdater::DisableOutdatedPluginGroups() {
std::vector<linked_ptr<PluginGroup> > groups;
GetPluginGroups(&groups);
for (std::vector<linked_ptr<PluginGroup> >::iterator it =
@@ -242,7 +286,7 @@ void DisableOutdatedPluginGroups() {
}
}
-void UpdatePreferences(Profile* profile) {
+void PluginUpdater::UpdatePreferences(Profile* profile) {
ListValue* plugins_list = profile->GetPrefs()->GetMutableList(
prefs::kPluginsPluginsList);
plugins_list->Clear();
@@ -277,4 +321,7 @@ void UpdatePreferences(Profile* profile) {
}
}
-} // namespace plugin_updater
+/*static*/
+PluginUpdater* PluginUpdater::GetPluginUpdater() {
+ return Singleton<PluginUpdater>::get();
+}
diff --git a/chrome/browser/plugin_updater.h b/chrome/browser/plugin_updater.h
index b847162..d046d46 100644
--- a/chrome/browser/plugin_updater.h
+++ b/chrome/browser/plugin_updater.h
@@ -6,36 +6,73 @@
#define CHROME_BROWSER_PLUGIN_UPDATER_H_
#pragma once
+#include <vector>
+
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/linked_ptr.h"
#include "base/singleton.h"
+#include "chrome/common/notification_observer.h"
+class DictionaryValue;
class ListValue;
+class NotificationDetails;
+class NotificationSource;
+class PluginGroup;
class Profile;
+struct WebPluginInfo;
+
+class PluginUpdater : public NotificationObserver {
+ public:
+ // Get a list of all the Plugin groups.
+ ListValue* GetPluginGroupsData();
+
+ // Enable or disable a plugin group.
+ void EnablePluginGroup(bool enable, const string16& group_name);
+
+ // Enable or disable a specific plugin file.
+ void EnablePluginFile(bool enable, const FilePath::StringType& file_path);
+
+ // Disable all plugin groups as defined by the user's preference file.
+ void DisablePluginGroupsFromPrefs(Profile* profile);
+
+ // Disable all plugins groups that are known to be outdated, according to
+ // the information hardcoded in PluginGroup, to make sure that they can't
+ // be loaded on a web page and instead show a UI to update to the latest
+ // version.
+ void DisableOutdatedPluginGroups();
+
+ // Write the enable/disable status to the user's preference file.
+ void UpdatePreferences(Profile* profile);
+
+ // NotificationObserver method overrides
+ void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
-namespace plugin_updater {
+ static PluginUpdater* GetPluginUpdater();
-// Get a list of all the Plugin groups.
-ListValue* GetPluginGroupsData();
+ private:
+ PluginUpdater();
+ virtual ~PluginUpdater() {}
-// Enable or disable a plugin group.
-void EnablePluginGroup(bool enable, const string16& group_name);
+ // Note: if you change this to false from true, you must update
+ // kPluginsEnabledInternalPDF to be a new name (i.e. add 2, 3, 4...) at end.
+ bool enable_internal_pdf_;
-// Enable or disable a specific plugin file.
-void EnablePluginFile(bool enable, const FilePath::StringType& file_path);
+ DictionaryValue* CreatePluginFileSummary(const WebPluginInfo& plugin);
-// Disable all plugin groups as defined by the user's preference file.
-void DisablePluginGroupsFromPrefs(Profile* profile);
+ // Convert to a List of Groups
+ void GetPluginGroups(std::vector<linked_ptr<PluginGroup> >* plugin_groups);
-// Disable all plugins groups that are known to be outdated, according to the
-// information hardcoded in PluginGroup, to make sure that they can't be loaded
-// on a web page and instead show a UI to update to the latest version.
-void DisableOutdatedPluginGroups();
+ // Force plugins to be disabled due to policy. |plugins| contains
+ // the list of StringValues of the names of the policy-disabled plugins.
+ void DisablePluginsFromPolicy(const ListValue* plugin_names);
-// Write the enable/disable status to the user's preference file.
-void UpdatePreferences(Profile* profile);
+ // Needed to allow singleton instantiation using private constructor.
+ friend struct DefaultSingletonTraits<PluginUpdater>;
-} // namespace plugin_updater
+ DISALLOW_COPY_AND_ASSIGN(PluginUpdater);
+};
#endif // CHROME_BROWSER_PLUGIN_UPDATER_H_
diff --git a/chrome/browser/prefs/pref_change_registrar.cc b/chrome/browser/prefs/pref_change_registrar.cc
new file mode 100644
index 0000000..dc8bb97
--- /dev/null
+++ b/chrome/browser/prefs/pref_change_registrar.cc
@@ -0,0 +1,53 @@
+// Copyright (c) 2010 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 "chrome/browser/prefs/pref_change_registrar.h"
+
+#include "chrome/browser/prefs/pref_service.h"
+
+PrefChangeRegistrar::PrefChangeRegistrar() : service_(NULL) {}
+
+PrefChangeRegistrar::~PrefChangeRegistrar() {
+ if (service_) {
+ for (std::set<ObserverRegistration>::const_iterator it = observers_.begin();
+ it != observers_.end(); ++it) {
+ service_->RemovePrefObserver(it->first.c_str(), it->second);
+ }
+ }
+}
+
+void PrefChangeRegistrar::Init(PrefService* service) {
+ DCHECK(!service_);
+ service_ = service;
+}
+
+void PrefChangeRegistrar::Add(const char* path, NotificationObserver* obs) {
+ if (!service_) {
+ NOTREACHED();
+ return;
+ }
+ ObserverRegistration registration(path, obs);
+ if (observers_.find(registration) != observers_.end()) {
+ NOTREACHED();
+ return;
+ }
+ observers_.insert(registration);
+ service_->AddPrefObserver(path, obs);
+}
+
+void PrefChangeRegistrar::Remove(const char* path, NotificationObserver* obs) {
+ if (!service_) {
+ NOTREACHED();
+ return;
+ }
+ ObserverRegistration registration(path, obs);
+ std::set<ObserverRegistration>::iterator it =
+ observers_.find(registration);
+ if (it == observers_.end()) {
+ NOTREACHED();
+ return;
+ }
+ service_->RemovePrefObserver(it->first.c_str(), it->second);
+ observers_.erase(it);
+}
diff --git a/chrome/browser/prefs/pref_change_registrar.h b/chrome/browser/prefs/pref_change_registrar.h
new file mode 100644
index 0000000..cd8f5eb
--- /dev/null
+++ b/chrome/browser/prefs/pref_change_registrar.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2010 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 CHROME_BROWSER_PREFS_PREF_CHANGE_REGISTRAR_H_
+#define CHROME_BROWSER_PREFS_PREF_CHANGE_REGISTRAR_H_
+#pragma once
+
+#include <set>
+#include <string>
+
+#include "base/basictypes.h"
+
+class PrefService;
+class NotificationObserver;
+
+// Automatically manages the registration of one or more pref change observers
+// with a PrefStore. Functions much like NotificationRegistrar, but specifically
+// manages observers of preference changes. When the Registrar is destroyed,
+// all registered observers are automatically unregistered with the PrefStore.
+class PrefChangeRegistrar {
+ public:
+ PrefChangeRegistrar();
+ virtual ~PrefChangeRegistrar();
+
+ // Must be called before adding or removing observers.
+ void Init(PrefService* service);
+
+ // Adds an pref observer for the specified pref |path| and |obs| observer
+ // object. All registered observers will be automatically unregistered
+ // when the registrar's destructor is called unless the observer has been
+ // explicitly removed by a call to Remove beforehand.
+ void Add(const char* path,
+ NotificationObserver* obs);
+
+ // Removes a preference observer that has previously been added with a call to
+ // Add.
+ void Remove(const char* path,
+ NotificationObserver* obs);
+
+ private:
+ typedef std::pair<std::string, NotificationObserver*> ObserverRegistration;
+
+ std::set<ObserverRegistration> observers_;
+ PrefService* service_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrefChangeRegistrar);
+};
+
+#endif // CHROME_BROWSER_PREFS_PREF_CHANGE_REGISTRAR_H_
diff --git a/chrome/browser/prefs/pref_change_registrar_unittest.cc b/chrome/browser/prefs/pref_change_registrar_unittest.cc
new file mode 100644
index 0000000..4d7f747
--- /dev/null
+++ b/chrome/browser/prefs/pref_change_registrar_unittest.cc
@@ -0,0 +1,90 @@
+// Copyright (c) 2010 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 "chrome/browser/prefs/pref_change_registrar.h"
+#include "chrome/common/notification_details.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/testing_pref_service.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::Mock;
+using testing::Eq;
+
+// A mock provider that allows us to capture pref observer changes.
+class MockPrefService : public TestingPrefService {
+ public:
+ MockPrefService() {}
+ virtual ~MockPrefService() {};
+
+ MOCK_METHOD2(AddPrefObserver, void(const char*, NotificationObserver*));
+ MOCK_METHOD2(RemovePrefObserver, void(const char*, NotificationObserver*));
+};
+
+// A mock observer used as a pref observer
+class MockObserver : public NotificationObserver {
+ public:
+ MOCK_METHOD3(Observe, void(NotificationType, const NotificationSource& source,
+ const NotificationDetails& details));
+};
+
+class PrefChangeRegistrarTest : public testing::Test {
+ public:
+ PrefChangeRegistrarTest() {}
+ virtual ~PrefChangeRegistrarTest() {}
+
+ protected:
+ virtual void SetUp();
+
+ NotificationObserver* observer() const { return observer_.get(); }
+ MockPrefService* service() const { return service_.get(); }
+
+ private:
+ scoped_ptr<MockPrefService> service_;
+ scoped_ptr<MockObserver> observer_;
+};
+
+void PrefChangeRegistrarTest::SetUp() {
+ service_.reset(new MockPrefService());
+ observer_.reset(new MockObserver());
+}
+
+TEST_F(PrefChangeRegistrarTest, AddAndRemove) {
+ PrefChangeRegistrar registrar;
+ registrar.Init(service());
+
+ // Test adding.
+ EXPECT_CALL(*service(),
+ AddPrefObserver(Eq(std::string("test.pref.1")), observer()));
+ EXPECT_CALL(*service(),
+ AddPrefObserver(Eq(std::string("test.pref.2")), observer()));
+ registrar.Add("test.pref.1", observer());
+ registrar.Add("test.pref.2", observer());
+
+ // Test removing.
+ Mock::VerifyAndClearExpectations(service());
+ EXPECT_CALL(*service(),
+ RemovePrefObserver(Eq(std::string("test.pref.1")), observer()));
+ EXPECT_CALL(*service(),
+ RemovePrefObserver(Eq(std::string("test.pref.2")), observer()));
+ registrar.Remove("test.pref.1", observer());
+ registrar.Remove("test.pref.2", observer());
+}
+
+TEST_F(PrefChangeRegistrarTest, AutoRemove) {
+ PrefChangeRegistrar registrar;
+ registrar.Init(service());
+
+ // Setup of auto-remove.
+ EXPECT_CALL(*service(),
+ AddPrefObserver(Eq(std::string("test.pref.1")), observer()));
+ registrar.Add("test.pref.1", observer());
+ Mock::VerifyAndClearExpectations(service());
+
+ // Test auto-removing.
+ EXPECT_CALL(*service(),
+ RemovePrefObserver(Eq(std::string("test.pref.1")), observer()));
+}
diff --git a/chrome/browser/prefs/pref_service.h b/chrome/browser/prefs/pref_service.h
index 07fa5e5..5a94542 100644
--- a/chrome/browser/prefs/pref_service.h
+++ b/chrome/browser/prefs/pref_service.h
@@ -165,7 +165,7 @@ class PrefService : public NonThreadSafe {
// If the pref at the given path changes, we call the observer's Observe
// method with NOTIFY_PREF_CHANGED.
virtual void AddPrefObserver(const char* path, NotificationObserver* obs);
- void RemovePrefObserver(const char* path, NotificationObserver* obs);
+ virtual void RemovePrefObserver(const char* path, NotificationObserver* obs);
// Removes a user pref and restores the pref to its default value.
void ClearPref(const char* path);
diff --git a/chrome/browser/resources/plugins.html b/chrome/browser/resources/plugins.html
index 58c34de..7cee567 100644
--- a/chrome/browser/resources/plugins.html
+++ b/chrome/browser/resources/plugins.html
@@ -423,7 +423,6 @@ function handleEnablePlugin(node, enable, isGroup) {
// Tell the C++ PluginsDOMHandler to enable/disable the plugin.
chrome.send('enablePlugin', [String(node.path), String(enable),
String(isGroup)]);
- requestPluginsData();
}
// Keeps track of whether details have been made visible (expanded) or not.
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 5616bc2..195316a 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2241,6 +2241,8 @@
'browser/prefs/pref_member.h',
'browser/prefs/pref_notifier.cc',
'browser/prefs/pref_notifier.h',
+ 'browser/prefs/pref_change_registrar.cc',
+ 'browser/prefs/pref_change_registrar.h',
'browser/prefs/pref_service.cc',
'browser/prefs/pref_service.h',
'browser/prefs/pref_set_observer.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index bdfbfc0..43f1b77 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1175,6 +1175,7 @@
'browser/preferences_mock_mac.cc',
'browser/preferences_mock_mac.h',
'browser/prefs/command_line_pref_store_unittest.cc',
+ 'browser/prefs/pref_change_registrar_unittest.cc',
'browser/prefs/pref_member_unittest.cc',
'browser/prefs/pref_notifier_unittest.cc',
'browser/prefs/pref_service_unittest.cc',
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index 834b9e5..10bef67 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -552,6 +552,10 @@ class NotificationType {
// should be loaded. The source is the RenderView. No details are expected.
SHOULD_LOAD_PLUGINS,
+ // Sent by the PluginUpdater when there is a change of plugin
+ // enable/disable status.
+ PLUGIN_ENABLE_STATUS_CHANGED,
+
// This is sent when a login prompt is shown. The source is the
// Source<NavigationController> for the tab in which the prompt is shown.
// Details are a LoginNotificationDetails which provide the LoginHandler
diff --git a/chrome/common/plugin_group.cc b/chrome/common/plugin_group.cc
index 2061956..f426803 100644
--- a/chrome/common/plugin_group.cc
+++ b/chrome/common/plugin_group.cc
@@ -88,6 +88,8 @@ size_t PluginGroup::GetPluginGroupDefinitionsSize() {
void PluginGroup::SetPolicyDisabledPluginSet(const std::set<string16>& set) {
if (!policy_disabled_plugins_)
policy_disabled_plugins_ = new std::set<string16>(set);
+ else
+ *policy_disabled_plugins_ = set;
}
/*static*/
diff --git a/chrome/common/plugin_group.h b/chrome/common/plugin_group.h
index 22acb88..a7ba852 100644
--- a/chrome/common/plugin_group.h
+++ b/chrome/common/plugin_group.h
@@ -90,6 +90,9 @@ class PluginGroup {
// group.
void Enable(bool enable);
+ // Returns whether the plugin group is enabled or not.
+ bool Enabled() const { return enabled_; }
+
// Returns this group's name
const string16& GetGroupName() const { return group_name_; }