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

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

Issue 10952021: Moving preference API into api/preferences (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 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
(Empty)
1 // Copyright (c) 2012 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.
4
5 #include "chrome/browser/extensions/extension_preference_api.h"
6
7 #include <map>
8 #include <utility>
9
10 #include "base/memory/singleton.h"
11 #include "base/stl_util.h"
12 #include "base/stringprintf.h"
13 #include "base/values.h"
14 #include "chrome/browser/extensions/api/proxy/proxy_api.h"
15 #include "chrome/browser/extensions/extension_preference_api_constants.h"
16 #include "chrome/browser/extensions/extension_preference_helpers.h"
17 #include "chrome/browser/extensions/extension_prefs.h"
18 #include "chrome/browser/extensions/extension_prefs_scope.h"
19 #include "chrome/browser/extensions/extension_service.h"
20 #include "chrome/browser/prefs/pref_service.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/common/chrome_notification_types.h"
23 #include "chrome/common/extensions/extension_error_utils.h"
24 #include "chrome/common/extensions/permissions/api_permission.h"
25 #include "chrome/common/pref_names.h"
26 #include "content/public/browser/notification_details.h"
27 #include "content/public/browser/notification_source.h"
28
29 namespace keys = extension_preference_api_constants;
30 namespace helpers = extension_preference_helpers;
31
32 using extensions::APIPermission;
33
34 namespace {
35
36 struct PrefMappingEntry {
37 // Name of the preference referenced by the extension API JSON.
38 const char* extension_pref;
39
40 // Name of the preference in the PrefStores.
41 const char* browser_pref;
42
43 // Permission required to access this preference.
44 // Use APIPermission::kInvalid for |permission| to express that no
45 // permission is necessary.
46 APIPermission::ID permission;
47 };
48
49 const char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange";
50
51 PrefMappingEntry kPrefMapping[] = {
52 #if defined(OS_CHROMEOS)
53 { "protectedContentEnabled",
54 prefs::kEnableCrosDRM,
55 APIPermission::kPrivacy
56 },
57 #endif // defined(OS_CHROMEOS)
58 { "alternateErrorPagesEnabled",
59 prefs::kAlternateErrorPagesEnabled,
60 APIPermission::kPrivacy
61 },
62 { "autofillEnabled",
63 prefs::kAutofillEnabled,
64 APIPermission::kPrivacy
65 },
66 { "hyperlinkAuditingEnabled",
67 prefs::kEnableHyperlinkAuditing,
68 APIPermission::kPrivacy
69 },
70 { "instantEnabled",
71 prefs::kInstantEnabled,
72 APIPermission::kPrivacy
73 },
74 { "managedModeEnabled",
75 prefs::kInManagedMode,
76 APIPermission::kManagedModePrivate
77 },
78 { "networkPredictionEnabled",
79 prefs::kNetworkPredictionEnabled,
80 APIPermission::kPrivacy
81 },
82 { "proxy",
83 prefs::kProxy,
84 APIPermission::kProxy
85 },
86 { "referrersEnabled",
87 prefs::kEnableReferrers,
88 APIPermission::kPrivacy
89 },
90 { "safeBrowsingEnabled",
91 prefs::kSafeBrowsingEnabled,
92 APIPermission::kPrivacy
93 },
94 { "searchSuggestEnabled",
95 prefs::kSearchSuggestEnabled,
96 APIPermission::kPrivacy
97 },
98 { "spellingServiceEnabled",
99 prefs::kSpellCheckUseSpellingService,
100 APIPermission::kPrivacy
101 },
102 { "thirdPartyCookiesAllowed",
103 prefs::kBlockThirdPartyCookies,
104 APIPermission::kPrivacy
105 },
106 { "translationServiceEnabled",
107 prefs::kEnableTranslate,
108 APIPermission::kPrivacy
109 }
110 };
111
112 class IdentityPrefTransformer : public PrefTransformerInterface {
113 public:
114 virtual Value* ExtensionToBrowserPref(const Value* extension_pref,
115 std::string* error,
116 bool* bad_message) {
117 return extension_pref->DeepCopy();
118 }
119
120 virtual Value* BrowserToExtensionPref(const Value* browser_pref) {
121 return browser_pref->DeepCopy();
122 }
123 };
124
125 class InvertBooleanTransformer : public PrefTransformerInterface {
126 public:
127 virtual Value* ExtensionToBrowserPref(const Value* extension_pref,
128 std::string* error,
129 bool* bad_message) {
130 return InvertBooleanValue(extension_pref);
131 }
132
133 virtual Value* BrowserToExtensionPref(const Value* browser_pref) {
134 return InvertBooleanValue(browser_pref);
135 }
136
137 private:
138 static Value* InvertBooleanValue(const Value* value) {
139 bool bool_value = false;
140 bool result = value->GetAsBoolean(&bool_value);
141 DCHECK(result);
142 return Value::CreateBooleanValue(!bool_value);
143 }
144 };
145
146 class PrefMapping {
147 public:
148 static PrefMapping* GetInstance() {
149 return Singleton<PrefMapping>::get();
150 }
151
152 bool FindBrowserPrefForExtensionPref(const std::string& extension_pref,
153 std::string* browser_pref,
154 APIPermission::ID* permission) {
155 PrefMap::iterator it = mapping_.find(extension_pref);
156 if (it != mapping_.end()) {
157 *browser_pref = it->second.first;
158 *permission = it->second.second;
159 return true;
160 }
161 return false;
162 }
163
164 bool FindEventForBrowserPref(const std::string& browser_pref,
165 std::string* event_name,
166 APIPermission::ID* permission) {
167 PrefMap::iterator it = event_mapping_.find(browser_pref);
168 if (it != event_mapping_.end()) {
169 *event_name = it->second.first;
170 *permission = it->second.second;
171 return true;
172 }
173 return false;
174 }
175
176 PrefTransformerInterface* FindTransformerForBrowserPref(
177 const std::string& browser_pref) {
178 std::map<std::string, PrefTransformerInterface*>::iterator it =
179 transformers_.find(browser_pref);
180 if (it != transformers_.end())
181 return it->second;
182 else
183 return identity_transformer_.get();
184 }
185
186 private:
187 friend struct DefaultSingletonTraits<PrefMapping>;
188
189 PrefMapping() {
190 identity_transformer_.reset(new IdentityPrefTransformer());
191 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
192 mapping_[kPrefMapping[i].extension_pref] =
193 std::make_pair(kPrefMapping[i].browser_pref,
194 kPrefMapping[i].permission);
195 std::string event_name =
196 base::StringPrintf(kOnPrefChangeFormat,
197 kPrefMapping[i].extension_pref);
198 event_mapping_[kPrefMapping[i].browser_pref] =
199 std::make_pair(event_name, kPrefMapping[i].permission);
200 }
201 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size());
202 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size());
203 RegisterPrefTransformer(prefs::kProxy,
204 new extensions::ProxyPrefTransformer());
205 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies,
206 new InvertBooleanTransformer());
207 }
208
209 ~PrefMapping() {
210 STLDeleteContainerPairSecondPointers(transformers_.begin(),
211 transformers_.end());
212 }
213
214 void RegisterPrefTransformer(const std::string& browser_pref,
215 PrefTransformerInterface* transformer) {
216 DCHECK_EQ(0u, transformers_.count(browser_pref)) <<
217 "Trying to register pref transformer for " << browser_pref << " twice";
218 transformers_[browser_pref] = transformer;
219 }
220
221 typedef std::map<std::string,
222 std::pair<std::string, APIPermission::ID> >
223 PrefMap;
224
225 // Mapping from extension pref keys to browser pref keys and permissions.
226 PrefMap mapping_;
227
228 // Mapping from browser pref keys to extension event names and permissions.
229 PrefMap event_mapping_;
230
231 // Mapping from browser pref keys to transformers.
232 std::map<std::string, PrefTransformerInterface*> transformers_;
233
234 scoped_ptr<PrefTransformerInterface> identity_transformer_;
235
236 DISALLOW_COPY_AND_ASSIGN(PrefMapping);
237 };
238
239 } // namespace
240
241 ExtensionPreferenceEventRouter::ExtensionPreferenceEventRouter(
242 Profile* profile) : profile_(profile) {
243 registrar_.Init(profile_->GetPrefs());
244 incognito_registrar_.Init(profile_->GetOffTheRecordPrefs());
245 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
246 registrar_.Add(kPrefMapping[i].browser_pref, this);
247 incognito_registrar_.Add(kPrefMapping[i].browser_pref, this);
248 }
249 }
250
251 ExtensionPreferenceEventRouter::~ExtensionPreferenceEventRouter() { }
252
253 void ExtensionPreferenceEventRouter::Observe(
254 int type,
255 const content::NotificationSource& source,
256 const content::NotificationDetails& details) {
257 if (type == chrome::NOTIFICATION_PREF_CHANGED) {
258 const std::string* pref_key =
259 content::Details<const std::string>(details).ptr();
260 OnPrefChanged(content::Source<PrefService>(source).ptr(), *pref_key);
261 } else {
262 NOTREACHED();
263 }
264 }
265
266 void ExtensionPreferenceEventRouter::OnPrefChanged(
267 PrefService* pref_service,
268 const std::string& browser_pref) {
269 bool incognito = (pref_service != profile_->GetPrefs());
270
271 std::string event_name;
272 APIPermission::ID permission = APIPermission::kInvalid;
273 bool rv = PrefMapping::GetInstance()->FindEventForBrowserPref(
274 browser_pref, &event_name, &permission);
275 DCHECK(rv);
276
277 ListValue args;
278 DictionaryValue* dict = new DictionaryValue();
279 args.Append(dict);
280 const PrefService::Preference* pref =
281 pref_service->FindPreference(browser_pref.c_str());
282 CHECK(pref);
283 ExtensionService* extension_service = profile_->GetExtensionService();
284 PrefTransformerInterface* transformer =
285 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
286 dict->Set(keys::kValue,
287 transformer->BrowserToExtensionPref(pref->GetValue()));
288 if (incognito) {
289 extensions::ExtensionPrefs* ep = extension_service->extension_prefs();
290 dict->SetBoolean(keys::kIncognitoSpecific,
291 ep->HasIncognitoPrefValue(browser_pref));
292 }
293
294 helpers::DispatchEventToExtensions(profile_,
295 event_name,
296 &args,
297 permission,
298 incognito,
299 browser_pref);
300 }
301
302 PreferenceFunction::~PreferenceFunction() { }
303
304 bool PreferenceFunction::ValidateBrowserPref(
305 const std::string& extension_pref_key,
306 std::string* browser_pref_key) {
307 APIPermission::ID permission = APIPermission::kInvalid;
308 EXTENSION_FUNCTION_VALIDATE(
309 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
310 extension_pref_key, browser_pref_key, &permission));
311 if (!GetExtension()->HasAPIPermission(permission)) {
312 error_ = ExtensionErrorUtils::FormatErrorMessage(
313 keys::kPermissionErrorMessage, extension_pref_key);
314 return false;
315 }
316 return true;
317 }
318
319 GetPreferenceFunction::~GetPreferenceFunction() { }
320
321 bool GetPreferenceFunction::RunImpl() {
322 std::string pref_key;
323 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
324 DictionaryValue* details = NULL;
325 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
326
327 bool incognito = false;
328 if (details->HasKey(keys::kIncognitoKey))
329 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(keys::kIncognitoKey,
330 &incognito));
331
332 // Check incognito access.
333 if (incognito && !include_incognito()) {
334 error_ = keys::kIncognitoErrorMessage;
335 return false;
336 }
337
338 // Obtain pref.
339 std::string browser_pref;
340 if (!ValidateBrowserPref(pref_key, &browser_pref))
341 return false;
342 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs()
343 : profile_->GetPrefs();
344 const PrefService::Preference* pref =
345 prefs->FindPreference(browser_pref.c_str());
346 CHECK(pref);
347
348 scoped_ptr<DictionaryValue> result(new DictionaryValue);
349
350 // Retrieve level of control.
351 std::string level_of_control =
352 helpers::GetLevelOfControl(profile_, extension_id(), browser_pref,
353 incognito);
354 result->SetString(keys::kLevelOfControl, level_of_control);
355
356 // Retrieve pref value.
357 PrefTransformerInterface* transformer =
358 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
359 result->Set(keys::kValue,
360 transformer->BrowserToExtensionPref(pref->GetValue()));
361
362 // Retrieve incognito status.
363 if (incognito) {
364 extensions::ExtensionPrefs* ep =
365 profile_->GetExtensionService()->extension_prefs();
366 result->SetBoolean(keys::kIncognitoSpecific,
367 ep->HasIncognitoPrefValue(browser_pref));
368 }
369
370 SetResult(result.release());
371 return true;
372 }
373
374 SetPreferenceFunction::~SetPreferenceFunction() { }
375
376 bool SetPreferenceFunction::RunImpl() {
377 std::string pref_key;
378 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
379 DictionaryValue* details = NULL;
380 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
381
382 Value* value = NULL;
383 EXTENSION_FUNCTION_VALIDATE(details->Get(keys::kValue, &value));
384
385 extensions::ExtensionPrefsScope scope =
386 extensions::kExtensionPrefsScopeRegular;
387 if (details->HasKey(keys::kScopeKey)) {
388 std::string scope_str;
389 EXTENSION_FUNCTION_VALIDATE(
390 details->GetString(keys::kScopeKey, &scope_str));
391
392 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope));
393 }
394
395 // Check incognito scope.
396 bool incognito =
397 (scope == extensions::kExtensionPrefsScopeIncognitoPersistent ||
398 scope == extensions::kExtensionPrefsScopeIncognitoSessionOnly);
399 if (incognito) {
400 // Regular profiles can't access incognito unless include_incognito is true.
401 if (!profile()->IsOffTheRecord() && !include_incognito()) {
402 error_ = keys::kIncognitoErrorMessage;
403 return false;
404 }
405 } else {
406 // Incognito profiles can't access regular mode ever, they only exist in
407 // split mode.
408 if (profile()->IsOffTheRecord()) {
409 error_ = "Can't modify regular settings from an incognito context.";
410 return false;
411 }
412 }
413
414 if (scope == extensions::kExtensionPrefsScopeIncognitoSessionOnly &&
415 !profile_->HasOffTheRecordProfile()) {
416 error_ = keys::kIncognitoSessionOnlyErrorMessage;
417 return false;
418 }
419
420 // Obtain pref.
421 std::string browser_pref;
422 if (!ValidateBrowserPref(pref_key, &browser_pref))
423 return false;
424 extensions::ExtensionPrefs* prefs =
425 profile_->GetExtensionService()->extension_prefs();
426 const PrefService::Preference* pref =
427 prefs->pref_service()->FindPreference(browser_pref.c_str());
428 CHECK(pref);
429
430 // Validate new value.
431 EXTENSION_FUNCTION_VALIDATE(value->GetType() == pref->GetType());
432 PrefTransformerInterface* transformer =
433 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
434 std::string error;
435 bool bad_message = false;
436 Value* browserPrefValue =
437 transformer->ExtensionToBrowserPref(value, &error, &bad_message);
438 if (!browserPrefValue) {
439 error_ = error;
440 bad_message_ = bad_message;
441 return false;
442 }
443
444 prefs->SetExtensionControlledPref(extension_id(),
445 browser_pref,
446 scope,
447 browserPrefValue);
448 return true;
449 }
450
451 ClearPreferenceFunction::~ClearPreferenceFunction() { }
452
453 bool ClearPreferenceFunction::RunImpl() {
454 std::string pref_key;
455 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
456 DictionaryValue* details = NULL;
457 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
458
459 extensions::ExtensionPrefsScope scope =
460 extensions::kExtensionPrefsScopeRegular;
461 if (details->HasKey(keys::kScopeKey)) {
462 std::string scope_str;
463 EXTENSION_FUNCTION_VALIDATE(
464 details->GetString(keys::kScopeKey, &scope_str));
465
466 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope));
467 }
468
469 // Check incognito scope.
470 bool incognito =
471 (scope == extensions::kExtensionPrefsScopeIncognitoPersistent ||
472 scope == extensions::kExtensionPrefsScopeIncognitoSessionOnly);
473 if (incognito) {
474 // We don't check incognito permissions here, as an extension should be
475 // always allowed to clear its own settings.
476 } else {
477 // Incognito profiles can't access regular mode ever, they only exist in
478 // split mode.
479 if (profile()->IsOffTheRecord()) {
480 error_ = "Can't modify regular settings from an incognito context.";
481 return false;
482 }
483 }
484
485 std::string browser_pref;
486 if (!ValidateBrowserPref(pref_key, &browser_pref))
487 return false;
488
489 extensions::ExtensionPrefs* prefs =
490 profile_->GetExtensionService()->extension_prefs();
491 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, scope);
492 return true;
493 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_preference_api.h ('k') | chrome/browser/extensions/extension_preference_api_constants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698