1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/preference/chrome_direct_setting_api.h"
8 #include "base/containers/hash_tables.h"
9 #include "base/lazy_instance.h"
10 #include "base/prefs/pref_change_registrar.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/stringprintf.h"
13 #include "chrome/browser/extensions/api/preference/preference_api_constants.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "extensions/browser/extension_registry.h"
17 namespace extensions
{
18 namespace chromedirectsetting
{
20 const char kOnPrefChangeFormat
[] =
21 "types.private.ChromeDirectSetting.%s.onChange";
23 class PreferenceWhitelist
{
25 PreferenceWhitelist() {
26 // Note: DO NOT add any setting here that does not have a UI element in
27 // chrome://settings unless you write a component extension that is always
28 // installed. Otherwise, users may install your extension, the extension may
29 // toggle settings, and after the extension has been disabled/uninstalled
30 // the toggled setting remains in place. See http://crbug.com/164227#c157 .
31 whitelist_
.insert("googlegeolocationaccess.enabled");
32 // The following settings need to be checked and probably removed. See
33 // http://crbug.com/164227#c157 .
34 whitelist_
.insert("spdy_proxy.enabled");
35 whitelist_
.insert("data_reduction.daily_original_length");
36 whitelist_
.insert("data_reduction.daily_received_length");
37 whitelist_
.insert("data_reduction.update_daily_lengths");
38 whitelist_
.insert("easy_unlock.proximity_required");
41 ~PreferenceWhitelist() {}
43 bool IsPreferenceOnWhitelist(const std::string
& pref_key
){
44 return whitelist_
.find(pref_key
) != whitelist_
.end();
47 void RegisterEventListeners(
49 EventRouter::Observer
* observer
) {
50 for (base::hash_set
<std::string
>::iterator iter
= whitelist_
.begin();
51 iter
!= whitelist_
.end();
53 std::string event_name
= base::StringPrintf(
56 EventRouter::Get(profile
)->RegisterObserver(observer
, event_name
);
60 void RegisterPropertyListeners(
62 PrefChangeRegistrar
* registrar
,
63 const base::Callback
<void(const std::string
&)>& callback
) {
64 for (base::hash_set
<std::string
>::iterator iter
= whitelist_
.begin();
65 iter
!= whitelist_
.end();
67 const char* pref_key
= (*iter
).c_str();
68 std::string event_name
= base::StringPrintf(
71 registrar
->Add(pref_key
, callback
);
76 base::hash_set
<std::string
> whitelist_
;
78 DISALLOW_COPY_AND_ASSIGN(PreferenceWhitelist
);
81 base::LazyInstance
<PreferenceWhitelist
> preference_whitelist
=
82 LAZY_INSTANCE_INITIALIZER
;
84 static base::LazyInstance
<
85 BrowserContextKeyedAPIFactory
<ChromeDirectSettingAPI
> > g_factory
=
86 LAZY_INSTANCE_INITIALIZER
;
88 ChromeDirectSettingAPI::ChromeDirectSettingAPI(content::BrowserContext
* context
)
89 : profile_(Profile::FromBrowserContext(context
)) {
90 preference_whitelist
.Get().RegisterEventListeners(profile_
, this);
93 ChromeDirectSettingAPI::~ChromeDirectSettingAPI() {}
95 // KeyedService implementation.
96 void ChromeDirectSettingAPI::Shutdown() {}
98 // BrowserContextKeyedAPI implementation.
99 BrowserContextKeyedAPIFactory
<ChromeDirectSettingAPI
>*
100 ChromeDirectSettingAPI::GetFactoryInstance() {
101 return g_factory
.Pointer();
104 // EventRouter::Observer implementation.
105 void ChromeDirectSettingAPI::OnListenerAdded(const EventListenerInfo
& details
) {
106 EventRouter::Get(profile_
)->UnregisterObserver(this);
107 registrar_
.Init(profile_
->GetPrefs());
108 preference_whitelist
.Get().RegisterPropertyListeners(
111 base::Bind(&ChromeDirectSettingAPI::OnPrefChanged
,
112 base::Unretained(this),
113 registrar_
.prefs()));
116 bool ChromeDirectSettingAPI::IsPreferenceOnWhitelist(
117 const std::string
& pref_key
) {
118 return preference_whitelist
.Get().IsPreferenceOnWhitelist(pref_key
);
121 ChromeDirectSettingAPI
* ChromeDirectSettingAPI::Get(
122 content::BrowserContext
* context
) {
123 return BrowserContextKeyedAPIFactory
<ChromeDirectSettingAPI
>::Get(context
);
126 // BrowserContextKeyedAPI implementation.
127 const char* ChromeDirectSettingAPI::service_name() {
128 return "ChromeDirectSettingAPI";
131 void ChromeDirectSettingAPI::OnPrefChanged(
132 PrefService
* pref_service
, const std::string
& pref_key
) {
133 std::string event_name
= base::StringPrintf(kOnPrefChangeFormat
,
135 EventRouter
* router
= EventRouter::Get(profile_
);
136 if (router
&& router
->HasEventListener(event_name
)) {
137 const PrefService::Preference
* preference
=
138 profile_
->GetPrefs()->FindPreference(pref_key
.c_str());
139 const base::Value
* value
= preference
->GetValue();
141 scoped_ptr
<base::DictionaryValue
> result(new base::DictionaryValue
);
142 result
->Set(preference_api_constants::kValue
, value
->DeepCopy());
143 base::ListValue args
;
144 args
.Append(result
.release());
146 for (const scoped_refptr
<const extensions::Extension
>& extension
:
147 ExtensionRegistry::Get(profile_
)->enabled_extensions()) {
148 const std::string
& extension_id
= extension
->id();
149 if (router
->ExtensionHasEventListener(extension_id
, event_name
)) {
150 scoped_ptr
<base::ListValue
> args_copy(args
.DeepCopy());
151 scoped_ptr
<Event
> event(new Event(event_name
, args_copy
.Pass()));
152 router
->DispatchEventToExtension(extension_id
, event
.Pass());
158 } // namespace chromedirectsetting
159 } // namespace extensions