diff options
author | danno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-10 13:55:18 +0000 |
---|---|---|
committer | danno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-10 13:55:18 +0000 |
commit | 492d214950b16d229ced62021486e9e0ec859e40 (patch) | |
tree | ac098e0dc234b894433b13d409ddb198cd9d24b1 /chrome | |
parent | 0ef5163fe4f9a76f516f09f7aa9d19c322e79691 (diff) | |
download | chromium_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.cc | 8 | ||||
-rw-r--r-- | chrome/browser/browser_process_impl.h | 5 | ||||
-rw-r--r-- | chrome/browser/dom_ui/plugins_ui.cc | 41 | ||||
-rw-r--r-- | chrome/browser/plugin_service.cc | 4 | ||||
-rw-r--r-- | chrome/browser/plugin_updater.cc | 137 | ||||
-rw-r--r-- | chrome/browser/plugin_updater.h | 69 | ||||
-rw-r--r-- | chrome/browser/prefs/pref_change_registrar.cc | 53 | ||||
-rw-r--r-- | chrome/browser/prefs/pref_change_registrar.h | 50 | ||||
-rw-r--r-- | chrome/browser/prefs/pref_change_registrar_unittest.cc | 90 | ||||
-rw-r--r-- | chrome/browser/prefs/pref_service.h | 2 | ||||
-rw-r--r-- | chrome/browser/resources/plugins.html | 1 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/common/notification_type.h | 4 | ||||
-rw-r--r-- | chrome/common/plugin_group.cc | 2 | ||||
-rw-r--r-- | chrome/common/plugin_group.h | 3 |
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_; } |