Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(383)

Side by Side Diff: chrome/browser/extensions/extension_preference_api.cc

Issue 6596044: Add onChange event to preference extension APIs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/extension_preference_api.h" 5 #include "chrome/browser/extensions/extension_preference_api.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/singleton.h" 10 #include "base/singleton.h"
11 #include "base/stl_util-inl.h" 11 #include "base/stl_util-inl.h"
12 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "chrome/browser/extensions/extension_event_router.h"
14 #include "chrome/browser/extensions/extension_prefs.h" 15 #include "chrome/browser/extensions/extension_prefs.h"
15 #include "chrome/browser/extensions/extension_proxy_api.h" 16 #include "chrome/browser/extensions/extension_proxy_api.h"
16 #include "chrome/browser/extensions/extension_service.h" 17 #include "chrome/browser/extensions/extension_service.h"
17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/common/pref_names.h" 19 #include "chrome/common/pref_names.h"
20 #include "content/common/notification_type.h"
21 #include "content/common/notification_service.h"
19 22
20 namespace { 23 namespace {
21 24
22 struct PrefMappingEntry { 25 struct PrefMappingEntry {
23 const char* extension_pref; 26 const char* extension_pref;
24 const char* browser_pref; 27 const char* browser_pref;
25 const char* permission; 28 const char* permission;
26 }; 29 };
27 30
28 const char kNotControllable[] = "NotControllable"; 31 const char kNotControllable[] = "NotControllable";
29 const char kControlledByOtherExtensions[] = "ControlledByOtherExtensions"; 32 const char kControlledByOtherExtensions[] = "ControlledByOtherExtensions";
30 const char kControllableByThisExtension[] = "ControllableByThisExtension"; 33 const char kControllableByThisExtension[] = "ControllableByThisExtension";
31 const char kControlledByThisExtension[] = "ControlledByThisExtension"; 34 const char kControlledByThisExtension[] = "ControlledByThisExtension";
32 35
33 const char kIncognito[] = "incognito"; 36 const char kIncognito[] = "incognito";
34 const char kIncognitoSpecific[] = "incognitoSpecific"; 37 const char kIncognitoSpecific[] = "incognitoSpecific";
35 const char kLevelOfControl[] = "levelOfControl"; 38 const char kLevelOfControl[] = "levelOfControl";
36 const char kValue[] = "value"; 39 const char kValue[] = "value";
37 40
41 const char kOnPrefChangeFormat[] = "experimental.preferences.%s.onChange";
42
38 const char kIncognitoErrorMessage[] = 43 const char kIncognitoErrorMessage[] =
39 "You do not have permission to access incognito preferences."; 44 "You do not have permission to access incognito preferences.";
40 45
41 const char kPermissionErrorMessage[] = 46 const char kPermissionErrorMessage[] =
42 "You do not have permission to access the preference '%s'. " 47 "You do not have permission to access the preference '%s'. "
43 "Be sure to declare in your manifest what permissions you need."; 48 "Be sure to declare in your manifest what permissions you need.";
44 49
45 PrefMappingEntry kPrefMapping[] = { 50 PrefMappingEntry kPrefMapping[] = {
46 { "blockThirdPartyCookies", 51 { "blockThirdPartyCookies",
47 prefs::kBlockThirdPartyCookies, 52 prefs::kBlockThirdPartyCookies,
(...skipping 13 matching lines...) Expand all
61 virtual Value* ExtensionToBrowserPref(const Value* extension_pref, 66 virtual Value* ExtensionToBrowserPref(const Value* extension_pref,
62 std::string* error) { 67 std::string* error) {
63 return extension_pref->DeepCopy(); 68 return extension_pref->DeepCopy();
64 } 69 }
65 70
66 virtual Value* BrowserToExtensionPref(const Value* browser_pref) { 71 virtual Value* BrowserToExtensionPref(const Value* browser_pref) {
67 return browser_pref->DeepCopy(); 72 return browser_pref->DeepCopy();
68 } 73 }
69 }; 74 };
70 75
76 // Returns a string constant (defined in the API) indicating the level of
77 // control this extension has over the specified preference.
78 const char* GetLevelOfControl(
79 Profile* profile,
80 const std::string& extension_id,
81 const std::string& browser_pref,
82 bool incognito) {
83 PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs()
84 : profile->GetPrefs();
85 const PrefService::Preference* pref =
86 prefs->FindPreference(browser_pref.c_str());
87 CHECK(pref);
88 ExtensionPrefs* ep = profile->GetExtensionService()->extension_prefs();
89
90 if (!pref->IsExtensionModifiable())
91 return kNotControllable;
92
93 if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito))
94 return kControlledByThisExtension;
95
96 if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito))
97 return kControllableByThisExtension;
98
99 return kControlledByOtherExtensions;
100 }
101
71 class PrefMapping { 102 class PrefMapping {
72 public: 103 public:
73 static PrefMapping* GetInstance() { 104 static PrefMapping* GetInstance() {
74 return Singleton<PrefMapping>::get(); 105 return Singleton<PrefMapping>::get();
75 } 106 }
76 107
77 bool FindBrowserPrefForExtensionPref(const std::string& extension_pref, 108 bool FindBrowserPrefForExtensionPref(const std::string& extension_pref,
78 std::string* browser_pref, 109 std::string* browser_pref,
79 std::string* permission) { 110 std::string* permission) {
80 std::map<std::string, std::pair<std::string, std::string> >::iterator it = 111 std::map<std::string, std::pair<std::string, std::string> >::iterator it =
81 mapping_.find(extension_pref); 112 mapping_.find(extension_pref);
82 if (it != mapping_.end()) { 113 if (it != mapping_.end()) {
83 *browser_pref = it->second.first; 114 *browser_pref = it->second.first;
84 *permission = it->second.second; 115 *permission = it->second.second;
85 return true; 116 return true;
86 } 117 }
87 return false; 118 return false;
88 } 119 }
89 120
121 bool FindEventForBrowserPref(const std::string& browser_pref,
122 std::string* event_name,
123 std::string* permission) {
124 std::map<std::string, std::pair<std::string, std::string> >::iterator it =
125 event_mapping_.find(browser_pref);
126 if (it != event_mapping_.end()) {
127 *event_name = it->second.first;
128 *permission = it->second.second;
129 return true;
130 }
131 return false;
132 }
133
90 PrefTransformerInterface* FindTransformerForBrowserPref( 134 PrefTransformerInterface* FindTransformerForBrowserPref(
91 const std::string& browser_pref) { 135 const std::string& browser_pref) {
92 std::map<std::string, PrefTransformerInterface*>::iterator it = 136 std::map<std::string, PrefTransformerInterface*>::iterator it =
93 transformers_.find(browser_pref); 137 transformers_.find(browser_pref);
94 if (it != transformers_.end()) 138 if (it != transformers_.end())
95 return it->second; 139 return it->second;
96 else 140 else
97 return identity_transformer_.get(); 141 return identity_transformer_.get();
98 } 142 }
99 143
100 private: 144 private:
101 friend struct DefaultSingletonTraits<PrefMapping>; 145 friend struct DefaultSingletonTraits<PrefMapping>;
102 146
103 PrefMapping() { 147 PrefMapping() {
104 identity_transformer_.reset(new IdentityPrefTransformer()); 148 identity_transformer_.reset(new IdentityPrefTransformer());
105 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) { 149 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
106 mapping_[kPrefMapping[i].extension_pref] = 150 mapping_[kPrefMapping[i].extension_pref] =
107 std::make_pair(kPrefMapping[i].browser_pref, 151 std::make_pair(kPrefMapping[i].browser_pref,
108 kPrefMapping[i].permission); 152 kPrefMapping[i].permission);
153 std::string event_name =
154 base::StringPrintf(kOnPrefChangeFormat,
155 kPrefMapping[i].extension_pref);
156 event_mapping_[kPrefMapping[i].browser_pref] =
157 std::make_pair(event_name, kPrefMapping[i].permission);
109 } 158 }
110 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size()); 159 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size());
160 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size());
111 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer()); 161 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer());
112 } 162 }
113 163
114 ~PrefMapping() { 164 ~PrefMapping() {
115 STLDeleteContainerPairSecondPointers(transformers_.begin(), 165 STLDeleteContainerPairSecondPointers(transformers_.begin(),
116 transformers_.end()); 166 transformers_.end());
117 } 167 }
118 168
119 void RegisterPrefTransformer(const std::string& browser_pref, 169 void RegisterPrefTransformer(const std::string& browser_pref,
120 PrefTransformerInterface* transformer) { 170 PrefTransformerInterface* transformer) {
121 DCHECK_EQ(0u, transformers_.count(browser_pref)) << 171 DCHECK_EQ(0u, transformers_.count(browser_pref)) <<
122 "Trying to register pref transformer for " << browser_pref << " twice"; 172 "Trying to register pref transformer for " << browser_pref << " twice";
123 transformers_[browser_pref] = transformer; 173 transformers_[browser_pref] = transformer;
124 } 174 }
125 175
126 // Mapping from extension pref keys to browser pref keys. 176 // Mapping from extension pref keys to browser pref keys.
127 std::map<std::string, std::pair<std::string, std::string> > mapping_; 177 std::map<std::string, std::pair<std::string, std::string> > mapping_;
128 178
179 // Mapping from browser pref keys to extension event names.
battre 2011/03/16 13:07:35 "to extension event names" is not quite correct, i
180 std::map<std::string, std::pair<std::string, std::string> > event_mapping_;
129 181
130 // Mapping from browser pref keys to transformers. 182 // Mapping from browser pref keys to transformers.
131 std::map<std::string, PrefTransformerInterface*> transformers_; 183 std::map<std::string, PrefTransformerInterface*> transformers_;
132 184
133 scoped_ptr<PrefTransformerInterface> identity_transformer_; 185 scoped_ptr<PrefTransformerInterface> identity_transformer_;
186
187 DISALLOW_COPY_AND_ASSIGN(PrefMapping);
134 }; 188 };
135 189
136 } // namespace 190 } // namespace
137 191
192 ExtensionPreferenceEventRouter::ExtensionPreferenceEventRouter(
193 Profile* profile) : profile_(profile) {
194 registrar_.Init(profile_->GetPrefs());
195 incognito_registrar_.Init(profile_->GetOffTheRecordPrefs());
196 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
197 registrar_.Add(kPrefMapping[i].browser_pref, this);
198 incognito_registrar_.Add(kPrefMapping[i].browser_pref, this);
199 }
200 }
201
202 ExtensionPreferenceEventRouter::~ExtensionPreferenceEventRouter() { }
203
204 void ExtensionPreferenceEventRouter::Observe(
205 NotificationType type,
206 const NotificationSource& source,
207 const NotificationDetails& details) {
208 if (type == NotificationType::PREF_CHANGED) {
209 const std::string* pref_key =
210 Details<const std::string>(details).ptr();
211 OnPrefChanged(Source<PrefService>(source).ptr(), *pref_key);
212 } else {
213 NOTREACHED();
214 }
215 }
216
217 void ExtensionPreferenceEventRouter::OnPrefChanged(
218 PrefService* pref_service,
219 const std::string& browser_pref) {
220 bool incognito = (pref_service != profile_->GetPrefs());
221
222 std::string event_name;
223 std::string permission;
224 bool rv = PrefMapping::GetInstance()->FindEventForBrowserPref(
225 browser_pref, &event_name, &permission);
226 DCHECK(rv);
227
228 ListValue args;
229 DictionaryValue* dict = new DictionaryValue();
230 args.Append(dict);
231 const PrefService::Preference* pref =
232 pref_service->FindPreference(browser_pref.c_str());
233 CHECK(pref);
234 ExtensionService* extension_service = profile_->GetExtensionService();
235 PrefTransformerInterface* transformer =
236 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
237 dict->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue()));
238 if (incognito) {
239 ExtensionPrefs* ep = extension_service->extension_prefs();
240 dict->Set(
241 kIncognitoSpecific,
242 Value::CreateBooleanValue(ep->HasIncognitoPrefValue(browser_pref)));
243 }
244
245 ExtensionEventRouter* router = profile_->GetExtensionEventRouter();
246 if (!router || !router->HasEventListener(event_name))
247 return;
248 const ExtensionList* extensions = extension_service->extensions();
249 for (ExtensionList::const_iterator it = extensions->begin();
250 it != extensions->end(); ++it) {
251 std::string extension_id = (*it)->id();
252 // TODO(bauerb): Only iterate over registered event listeners.
253 if (router->ExtensionHasEventListener(extension_id, event_name) &&
254 (*it)->HasApiPermission(permission) &&
255 (!incognito || extension_service->CanCrossIncognito(*it))) {
256 std::string level_of_control =
257 GetLevelOfControl(profile_, extension_id, browser_pref, incognito);
258 dict->Set(kLevelOfControl, Value::CreateStringValue(level_of_control));
259
260 std::string json_args;
261 base::JSONWriter::Write(&args, false, &json_args);
262
263 DispatchEvent(extension_id, event_name, json_args);
264 }
265 }
266 }
267
268 void ExtensionPreferenceEventRouter::DispatchEvent(
269 const std::string& extension_id,
270 const std::string& event_name,
271 const std::string& json_args) {
272 profile_->GetExtensionEventRouter()->DispatchEventToExtension(
273 extension_id, event_name, json_args, NULL, GURL());
274 }
275
138 // TODO(battre): Factor out common parts once this is stable. 276 // TODO(battre): Factor out common parts once this is stable.
139 277
140 GetPreferenceFunction::~GetPreferenceFunction() { } 278 GetPreferenceFunction::~GetPreferenceFunction() { }
141 279
142 const char* GetPreferenceFunction::GetLevelOfControl(
143 const std::string& browser_pref,
144 bool incognito) const {
145 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs()
146 : profile_->GetPrefs();
147 const PrefService::Preference* pref =
148 prefs->FindPreference(browser_pref.c_str());
149 CHECK(pref);
150 ExtensionPrefs* ep = profile_->GetExtensionService()->extension_prefs();
151
152 if (!pref->IsExtensionModifiable())
153 return kNotControllable;
154
155 if (ep->DoesExtensionControlPref(extension_id(), browser_pref, incognito))
156 return kControlledByThisExtension;
157
158 if (ep->CanExtensionControlPref(extension_id(), browser_pref, incognito))
159 return kControllableByThisExtension;
160
161 return kControlledByOtherExtensions;
162 }
163
164 bool GetPreferenceFunction::RunImpl() { 280 bool GetPreferenceFunction::RunImpl() {
165 std::string pref_key; 281 std::string pref_key;
166 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key)); 282 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
167 DictionaryValue* details = NULL; 283 DictionaryValue* details = NULL;
168 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details)); 284 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
169 285
170 bool incognito = false; 286 bool incognito = false;
171 if (details->HasKey(kIncognito)) 287 if (details->HasKey(kIncognito))
172 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(kIncognito, &incognito)); 288 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(kIncognito, &incognito));
173 289
(...skipping 10 matching lines...) Expand all
184 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( 300 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
185 pref_key, &browser_pref, &permission)); 301 pref_key, &browser_pref, &permission));
186 if (!GetExtension()->HasApiPermission(permission)) { 302 if (!GetExtension()->HasApiPermission(permission)) {
187 error_ = base::StringPrintf(kPermissionErrorMessage, pref_key.c_str()); 303 error_ = base::StringPrintf(kPermissionErrorMessage, pref_key.c_str());
188 return false; 304 return false;
189 } 305 }
190 306
191 const PrefService::Preference* pref = 307 const PrefService::Preference* pref =
192 prefs->FindPreference(browser_pref.c_str()); 308 prefs->FindPreference(browser_pref.c_str());
193 CHECK(pref); 309 CHECK(pref);
194 std::string level_of_control = GetLevelOfControl(browser_pref, incognito); 310 std::string level_of_control =
311 GetLevelOfControl(profile_, extension_id(), browser_pref, incognito);
195 312
196 scoped_ptr<DictionaryValue> result(new DictionaryValue); 313 scoped_ptr<DictionaryValue> result(new DictionaryValue);
197 PrefTransformerInterface* transformer = 314 PrefTransformerInterface* transformer =
198 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); 315 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
199 result->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue())); 316 result->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue()));
200 result->Set(kLevelOfControl, Value::CreateStringValue(level_of_control)); 317 result->Set(kLevelOfControl, Value::CreateStringValue(level_of_control));
201 if (incognito) { 318 if (incognito) {
202 ExtensionPrefs* ep = profile_->GetExtensionService()->extension_prefs(); 319 ExtensionPrefs* ep = profile_->GetExtensionService()->extension_prefs();
203 result->Set( 320 result->Set(
204 kIncognitoSpecific, 321 kIncognitoSpecific,
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( 395 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
279 pref_key, &browser_pref, &permission)); 396 pref_key, &browser_pref, &permission));
280 if (!GetExtension()->HasApiPermission(permission)) { 397 if (!GetExtension()->HasApiPermission(permission)) {
281 error_ = base::StringPrintf(kPermissionErrorMessage, pref_key.c_str()); 398 error_ = base::StringPrintf(kPermissionErrorMessage, pref_key.c_str());
282 return false; 399 return false;
283 } 400 }
284 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); 401 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs();
285 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, incognito); 402 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, incognito);
286 return true; 403 return true;
287 } 404 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_preference_api.h ('k') | chrome/browser/extensions/extension_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698