diff options
author | robliao@chromium.org <robliao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-18 09:40:47 +0000 |
---|---|---|
committer | robliao@chromium.org <robliao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-18 09:40:47 +0000 |
commit | 4ad4ce089223e144fb240751ba7a48f7c9064d27 (patch) | |
tree | 1c9cb30afd770376443e67c97a79a968ba7531f5 /chrome/browser/extensions/api/preference | |
parent | e631a5f7df3aceff6307e04d36073f01412fbb3c (diff) | |
download | chromium_src-4ad4ce089223e144fb240751ba7a48f7c9064d27.zip chromium_src-4ad4ce089223e144fb240751ba7a48f7c9064d27.tar.gz chromium_src-4ad4ce089223e144fb240751ba7a48f7c9064d27.tar.bz2 |
Implemented types.private.ChromeDirectSetting.onChange
This delta links up the onChange event machinery to the property
change notification machinery.
It follows a pattern established in PreferencesAPI and the
PreferenceEventRouter.
* Given a list of preferences, register event listener added
observers to each preference.
* On the first added event listener, unregister all observers
and register all property change listeners.
* On property changes, forward an event to each component
extension that has a property listener added.
BUG=164227
Review URL: https://chromiumcodereview.appspot.com/18100007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@212307 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions/api/preference')
4 files changed, 222 insertions, 36 deletions
diff --git a/chrome/browser/extensions/api/preference/chrome_direct_setting.cc b/chrome/browser/extensions/api/preference/chrome_direct_setting.cc index 161ef9b..6d1bd76 100644 --- a/chrome/browser/extensions/api/preference/chrome_direct_setting.cc +++ b/chrome/browser/extensions/api/preference/chrome_direct_setting.cc @@ -5,39 +5,16 @@ #include "chrome/browser/extensions/api/preference/chrome_direct_setting.h" #include "base/containers/hash_tables.h" +#include "base/lazy_instance.h" #include "base/prefs/pref_service.h" #include "base/values.h" +#include "chrome/browser/extensions/api/preference/chrome_direct_setting_api.h" #include "chrome/browser/extensions/api/preference/preference_api_constants.h" #include "chrome/browser/profiles/profile.h" namespace extensions { namespace chromedirectsetting { -namespace { - -class PreferenceWhitelist { - public: - PreferenceWhitelist() { - whitelist_.insert("googlegeolocationaccess.enabled"); - } - - ~PreferenceWhitelist() {} - - bool IsPreferenceOnWhitelist(const std::string& pref_key){ - return whitelist_.find(pref_key) != whitelist_.end(); - } - - private: - base::hash_set<std::string> whitelist_; - - DISALLOW_COPY_AND_ASSIGN(PreferenceWhitelist); -}; - -static base::LazyInstance<PreferenceWhitelist> preference_whitelist_ = - LAZY_INSTANCE_INITIALIZER; - -} // namespace - DirectSettingFunctionBase::DirectSettingFunctionBase() {} DirectSettingFunctionBase::~DirectSettingFunctionBase() {} @@ -50,11 +27,6 @@ bool DirectSettingFunctionBase::IsCalledFromComponentExtension() { return GetExtension()->location() == Manifest::COMPONENT; } -bool DirectSettingFunctionBase::IsPreferenceOnWhitelist( - const std::string& pref_key) { - return preference_whitelist_.Get().IsPreferenceOnWhitelist(pref_key); -} - GetDirectSettingFunction::GetDirectSettingFunction() {} bool GetDirectSettingFunction::RunImpl() { @@ -62,7 +34,8 @@ bool GetDirectSettingFunction::RunImpl() { std::string pref_key; EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key)); - EXTENSION_FUNCTION_VALIDATE(IsPreferenceOnWhitelist(pref_key)); + EXTENSION_FUNCTION_VALIDATE( + ChromeDirectSettingAPI::Get(profile())->IsPreferenceOnWhitelist(pref_key)); const PrefService::Preference* preference = GetPrefService()->FindPreference(pref_key.c_str()); @@ -85,7 +58,8 @@ bool SetDirectSettingFunction::RunImpl() { std::string pref_key; EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key)); - EXTENSION_FUNCTION_VALIDATE(IsPreferenceOnWhitelist(pref_key)); + EXTENSION_FUNCTION_VALIDATE( + ChromeDirectSettingAPI::Get(profile())->IsPreferenceOnWhitelist(pref_key)); DictionaryValue* details = NULL; EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details)); @@ -115,7 +89,8 @@ bool ClearDirectSettingFunction::RunImpl() { std::string pref_key; EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key)); - EXTENSION_FUNCTION_VALIDATE(IsPreferenceOnWhitelist(pref_key)); + EXTENSION_FUNCTION_VALIDATE( + ChromeDirectSettingAPI::Get(profile())->IsPreferenceOnWhitelist(pref_key)); GetPrefService()->ClearPref(pref_key.c_str()); return true; diff --git a/chrome/browser/extensions/api/preference/chrome_direct_setting.h b/chrome/browser/extensions/api/preference/chrome_direct_setting.h index 1a8164b..7e36344 100644 --- a/chrome/browser/extensions/api/preference/chrome_direct_setting.h +++ b/chrome/browser/extensions/api/preference/chrome_direct_setting.h @@ -25,9 +25,6 @@ class DirectSettingFunctionBase : public SyncExtensionFunction { // Returns true if the caller is a component extension. bool IsCalledFromComponentExtension(); - // Returns true if the preference is on the whitelist. - bool IsPreferenceOnWhitelist(const std::string& pref_key); - private: DISALLOW_COPY_AND_ASSIGN(DirectSettingFunctionBase); }; diff --git a/chrome/browser/extensions/api/preference/chrome_direct_setting_api.cc b/chrome/browser/extensions/api/preference/chrome_direct_setting_api.cc new file mode 100644 index 0000000..04b4307 --- /dev/null +++ b/chrome/browser/extensions/api/preference/chrome_direct_setting_api.cc @@ -0,0 +1,154 @@ +// 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 "chrome/browser/extensions/api/preference/chrome_direct_setting_api.h" + +#include "base/bind.h" +#include "base/containers/hash_tables.h" +#include "base/lazy_instance.h" +#include "base/prefs/pref_change_registrar.h" +#include "base/prefs/pref_service.h" +#include "base/strings/stringprintf.h" +#include "chrome/browser/extensions/api/preference/preference_api_constants.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/profiles/profile.h" + +namespace extensions { +namespace chromedirectsetting { + +const char kOnPrefChangeFormat[] = + "types.private.ChromeDirectSetting.%s.onChange"; + +class PreferenceWhitelist { + public: + PreferenceWhitelist() { + whitelist_.insert("googlegeolocationaccess.enabled"); + } + + ~PreferenceWhitelist() {} + + bool IsPreferenceOnWhitelist(const std::string& pref_key){ + return whitelist_.find(pref_key) != whitelist_.end(); + } + + void RegisterEventListeners( + Profile* profile, + EventRouter::Observer* observer) { + for (base::hash_set<std::string>::iterator iter = whitelist_.begin(); + iter != whitelist_.end(); + iter++) { + std::string event_name = base::StringPrintf( + kOnPrefChangeFormat, + (*iter).c_str()); + ExtensionSystem::Get(profile)->event_router()->RegisterObserver( + observer, + event_name); + } + } + + void RegisterPropertyListeners( + Profile* profile, + PrefChangeRegistrar* registrar, + const base::Callback<void(const std::string&)>& callback) { + for (base::hash_set<std::string>::iterator iter = whitelist_.begin(); + iter != whitelist_.end(); + iter++) { + const char* pref_key = (*iter).c_str(); + std::string event_name = base::StringPrintf( + kOnPrefChangeFormat, + pref_key); + registrar->Add(pref_key, callback); + } + } + + private: + base::hash_set<std::string> whitelist_; + + DISALLOW_COPY_AND_ASSIGN(PreferenceWhitelist); +}; + +base::LazyInstance<PreferenceWhitelist> preference_whitelist = + LAZY_INSTANCE_INITIALIZER; + +static base::LazyInstance<ProfileKeyedAPIFactory<ChromeDirectSettingAPI> > + g_factory = LAZY_INSTANCE_INITIALIZER; + +ChromeDirectSettingAPI::ChromeDirectSettingAPI(Profile* profile) + : profile_(profile) { + preference_whitelist.Get().RegisterEventListeners(profile, this); +} + +ChromeDirectSettingAPI::~ChromeDirectSettingAPI() {} + +// BrowserContextKeyedService implementation. +void ChromeDirectSettingAPI::Shutdown() {} + +// ProfileKeyedAPI implementation. +ProfileKeyedAPIFactory<ChromeDirectSettingAPI>* + ChromeDirectSettingAPI::GetFactoryInstance() { + return &g_factory.Get(); +} + +// EventRouter::Observer implementation. +void ChromeDirectSettingAPI::OnListenerAdded(const EventListenerInfo& details) { + ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this); + registrar_.Init(profile_->GetPrefs()); + preference_whitelist.Get().RegisterPropertyListeners( + profile_, + ®istrar_, + base::Bind(&ChromeDirectSettingAPI::OnPrefChanged, + base::Unretained(this), + registrar_.prefs())); +} + +bool ChromeDirectSettingAPI::IsPreferenceOnWhitelist( + const std::string& pref_key) { + return preference_whitelist.Get().IsPreferenceOnWhitelist(pref_key); +} + +ChromeDirectSettingAPI* ChromeDirectSettingAPI::Get(Profile* profile) { + return + ProfileKeyedAPIFactory<ChromeDirectSettingAPI>::GetForProfile(profile); +} + +// ProfileKeyedAPI implementation. +const char* ChromeDirectSettingAPI::service_name() { + return "ChromeDirectSettingAPI"; +} + +void ChromeDirectSettingAPI::OnPrefChanged( + PrefService* pref_service, const std::string& pref_key) { + std::string event_name = base::StringPrintf(kOnPrefChangeFormat, + pref_key.c_str()); + EventRouter* router = ExtensionSystem::Get(profile_)->event_router(); + if (router && router->HasEventListener(event_name)) { + const PrefService::Preference* preference = + profile_->GetPrefs()->FindPreference(pref_key.c_str()); + const base::Value* value = preference->GetValue(); + + scoped_ptr<DictionaryValue> result(new DictionaryValue); + result->Set(preference_api_constants::kValue, value->DeepCopy()); + base::ListValue args; + args.Append(result.release()); + + ExtensionService* extension_service = + ExtensionSystem::Get(profile_)->extension_service(); + const ExtensionSet* extensions = extension_service->extensions(); + for (ExtensionSet::const_iterator it = extensions->begin(); + it != extensions->end(); ++it) { + if ((*it)->location() == Manifest::COMPONENT) { + std::string extension_id = (*it)->id(); + if (router->ExtensionHasEventListener(extension_id, event_name)) { + scoped_ptr<base::ListValue> args_copy(args.DeepCopy()); + scoped_ptr<Event> event(new Event(event_name, args_copy.Pass())); + router->DispatchEventToExtension(extension_id, event.Pass()); + } + } + } + } +} + +} // namespace chromedirectsetting +} // namespace extensions + diff --git a/chrome/browser/extensions/api/preference/chrome_direct_setting_api.h b/chrome/browser/extensions/api/preference/chrome_direct_setting_api.h new file mode 100644 index 0000000..0fd6207 --- /dev/null +++ b/chrome/browser/extensions/api/preference/chrome_direct_setting_api.h @@ -0,0 +1,60 @@ +// 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 CHROME_BROWSER_EXTENSIONS_API_PREFERENCE_CHROME_DIRECT_SETTING_API_H__ +#define CHROME_BROWSER_EXTENSIONS_API_PREFERENCE_CHROME_DIRECT_SETTING_API_H__ + +#include "chrome/browser/extensions/api/profile_keyed_api_factory.h" +#include "chrome/browser/extensions/event_router.h" + +class PrefChangeRegistrar; +class Profile; + +namespace extensions { +namespace chromedirectsetting { + +class ChromeDirectSettingAPI : public ProfileKeyedAPI, + public EventRouter::Observer { + public: + explicit ChromeDirectSettingAPI(Profile* profile); + + virtual ~ChromeDirectSettingAPI(); + + // BrowserContextKeyedService implementation. + virtual void Shutdown() OVERRIDE; + + // ProfileKeyedAPI implementation. + static ProfileKeyedAPIFactory<ChromeDirectSettingAPI>* GetFactoryInstance(); + + // EventRouter::Observer implementation. + virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE; + + // Returns true if the preference is on the whitelist. + bool IsPreferenceOnWhitelist(const std::string& pref_key); + + // Convenience method to get the ChromeDirectSettingAPI for a profile. + static ChromeDirectSettingAPI* Get(Profile* profile); + + private: + friend class ProfileKeyedAPIFactory<ChromeDirectSettingAPI>; + + // ProfileKeyedAPI implementation. + static const char* service_name(); + + void OnPrefChanged(PrefService* pref_service, const std::string& pref_key); + + static const bool kServiceIsNULLWhileTesting = true; + static const bool kServiceRedirectedInIncognito = false; + + PrefChangeRegistrar registrar_; + Profile* profile_; + + DISALLOW_COPY_AND_ASSIGN(ChromeDirectSettingAPI); +}; + +} // namespace chromedirectsetting +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_PREFERENCE_CHROME_DIRECT_SETTING_API_H__ + |