Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / preference / preference_api.cc
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/api/preference/preference_api.h"
6
7 #include <map>
8 #include <utility>
9
10 #include "base/lazy_instance.h"
11 #include "base/memory/singleton.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/stl_util.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/values.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/extensions/api/content_settings/content_settings_service.h"
18 #include "chrome/browser/extensions/api/preference/preference_api_constants.h"
19 #include "chrome/browser/extensions/api/preference/preference_helpers.h"
20 #include "chrome/browser/extensions/api/proxy/proxy_api.h"
21 #include "chrome/browser/extensions/extension_service.h"
22 #include "chrome/browser/net/prediction_options.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/common/pref_names.h"
25 #include "components/translate/core/common/translate_pref_names.h"
26 #include "content/public/browser/notification_details.h"
27 #include "content/public/browser/notification_source.h"
28 #include "extensions/browser/extension_pref_value_map.h"
29 #include "extensions/browser/extension_pref_value_map_factory.h"
30 #include "extensions/browser/extension_prefs.h"
31 #include "extensions/browser/extension_prefs_factory.h"
32 #include "extensions/browser/extension_system_provider.h"
33 #include "extensions/browser/extensions_browser_client.h"
34 #include "extensions/browser/pref_names.h"
35 #include "extensions/common/error_utils.h"
36 #include "extensions/common/permissions/api_permission.h"
37 #include "extensions/common/permissions/permissions_data.h"
38
39 namespace keys = extensions::preference_api_constants;
40 namespace helpers = extensions::preference_helpers;
41
42 using base::DictionaryValue;
43
44 namespace extensions {
45
46 namespace {
47
48 struct PrefMappingEntry {
49   // Name of the preference referenced by the extension API JSON.
50   const char* extension_pref;
51
52   // Name of the preference in the PrefStores.
53   const char* browser_pref;
54
55   // Permission required to read and observe this preference.
56   // Use APIPermission::kInvalid for |read_permission| to express that the read
57   // permission should not be granted.
58   APIPermission::ID read_permission;
59
60   // Permission required to write this preference.
61   // Use APIPermission::kInvalid for |write_permission| to express that the
62   // write permission should not be granted.
63   APIPermission::ID write_permission;
64 };
65
66 const char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange";
67 const char kConversionErrorMessage[] =
68     "Internal error: Stored value for preference '*' cannot be converted "
69     "properly.";
70
71 PrefMappingEntry kPrefMapping[] = {
72     {"alternateErrorPagesEnabled", prefs::kAlternateErrorPagesEnabled,
73      APIPermission::kPrivacy, APIPermission::kPrivacy},
74     {"autofillEnabled", autofill::prefs::kAutofillEnabled,
75      APIPermission::kPrivacy, APIPermission::kPrivacy},
76     {"hyperlinkAuditingEnabled", prefs::kEnableHyperlinkAuditing,
77      APIPermission::kPrivacy, APIPermission::kPrivacy},
78     {"networkPredictionEnabled", prefs::kNetworkPredictionOptions,
79      APIPermission::kPrivacy, APIPermission::kPrivacy},
80     {"passwordSavingEnabled",
81      password_manager::prefs::kPasswordManagerSavingEnabled,
82      APIPermission::kPrivacy, APIPermission::kPrivacy},
83     {"protectedContentEnabled", prefs::kEnableDRM, APIPermission::kPrivacy,
84      APIPermission::kPrivacy},
85     {"proxy", prefs::kProxy, APIPermission::kProxy, APIPermission::kProxy},
86     {"referrersEnabled", prefs::kEnableReferrers, APIPermission::kPrivacy,
87      APIPermission::kPrivacy},
88     {"safeBrowsingEnabled", prefs::kSafeBrowsingEnabled,
89      APIPermission::kPrivacy, APIPermission::kPrivacy},
90     {"searchSuggestEnabled", prefs::kSearchSuggestEnabled,
91      APIPermission::kPrivacy, APIPermission::kPrivacy},
92     {"spellingServiceEnabled", prefs::kSpellCheckUseSpellingService,
93      APIPermission::kPrivacy, APIPermission::kPrivacy},
94     {"thirdPartyCookiesAllowed", prefs::kBlockThirdPartyCookies,
95      APIPermission::kPrivacy, APIPermission::kPrivacy},
96     {"translationServiceEnabled", prefs::kEnableTranslate,
97      APIPermission::kPrivacy, APIPermission::kPrivacy},
98 #if defined(OS_CHROMEOS)
99     {"autoclick", prefs::kAccessibilityAutoclickEnabled,
100      APIPermission::kAccessibilityFeaturesRead,
101      APIPermission::kAccessibilityFeaturesModify},
102     {"highContrast", prefs::kAccessibilityHighContrastEnabled,
103      APIPermission::kAccessibilityFeaturesRead,
104      APIPermission::kAccessibilityFeaturesModify},
105     {"largeCursor", prefs::kAccessibilityLargeCursorEnabled,
106      APIPermission::kAccessibilityFeaturesRead,
107      APIPermission::kAccessibilityFeaturesModify},
108     {"screenMagnifier", prefs::kAccessibilityScreenMagnifierEnabled,
109      APIPermission::kAccessibilityFeaturesRead,
110      APIPermission::kAccessibilityFeaturesModify},
111     {"spokenFeedback", prefs::kAccessibilitySpokenFeedbackEnabled,
112      APIPermission::kAccessibilityFeaturesRead,
113      APIPermission::kAccessibilityFeaturesModify},
114     {"stickyKeys", prefs::kAccessibilityStickyKeysEnabled,
115      APIPermission::kAccessibilityFeaturesRead,
116      APIPermission::kAccessibilityFeaturesModify},
117     {"virtualKeyboard", prefs::kAccessibilityVirtualKeyboardEnabled,
118      APIPermission::kAccessibilityFeaturesRead,
119      APIPermission::kAccessibilityFeaturesModify},
120 #endif
121 };
122
123 class IdentityPrefTransformer : public PrefTransformerInterface {
124  public:
125   base::Value* ExtensionToBrowserPref(const base::Value* extension_pref,
126                                       std::string* error,
127                                       bool* bad_message) override {
128     return extension_pref->DeepCopy();
129   }
130
131   base::Value* BrowserToExtensionPref(
132       const base::Value* browser_pref) override {
133     return browser_pref->DeepCopy();
134   }
135 };
136
137 class InvertBooleanTransformer : public PrefTransformerInterface {
138  public:
139   base::Value* ExtensionToBrowserPref(const base::Value* extension_pref,
140                                       std::string* error,
141                                       bool* bad_message) override {
142     return InvertBooleanValue(extension_pref);
143   }
144
145   base::Value* BrowserToExtensionPref(
146       const base::Value* browser_pref) override {
147     return InvertBooleanValue(browser_pref);
148   }
149
150  private:
151   static base::Value* InvertBooleanValue(const base::Value* value) {
152     bool bool_value = false;
153     bool result = value->GetAsBoolean(&bool_value);
154     DCHECK(result);
155     return new base::FundamentalValue(!bool_value);
156   }
157 };
158
159 class NetworkPredictionTransformer : public PrefTransformerInterface {
160  public:
161   virtual base::Value* ExtensionToBrowserPref(const base::Value* extension_pref,
162                                               std::string* error,
163                                               bool* bad_message) override {
164     bool bool_value = false;
165     const bool pref_found = extension_pref->GetAsBoolean(&bool_value);
166     DCHECK(pref_found) << "Preference not found.";
167     if (bool_value) {
168       return new base::FundamentalValue(
169           chrome_browser_net::NETWORK_PREDICTION_DEFAULT);
170     } else {
171       return new base::FundamentalValue(
172           chrome_browser_net::NETWORK_PREDICTION_NEVER);
173     }
174   }
175
176   virtual base::Value* BrowserToExtensionPref(
177       const base::Value* browser_pref) override {
178     int int_value = chrome_browser_net::NETWORK_PREDICTION_DEFAULT;
179     const bool pref_found = browser_pref->GetAsInteger(&int_value);
180     DCHECK(pref_found) << "Preference not found.";
181     return new base::FundamentalValue(
182         int_value != chrome_browser_net::NETWORK_PREDICTION_NEVER);
183   }
184 };
185
186 class PrefMapping {
187  public:
188   static PrefMapping* GetInstance() {
189     return Singleton<PrefMapping>::get();
190   }
191
192   bool FindBrowserPrefForExtensionPref(const std::string& extension_pref,
193                                        std::string* browser_pref,
194                                        APIPermission::ID* read_permission,
195                                        APIPermission::ID* write_permission) {
196     PrefMap::iterator it = mapping_.find(extension_pref);
197     if (it != mapping_.end()) {
198       *browser_pref = it->second.pref_name;
199       *read_permission = it->second.read_permission;
200       *write_permission = it->second.write_permission;
201       return true;
202     }
203     return false;
204   }
205
206   bool FindEventForBrowserPref(const std::string& browser_pref,
207                                std::string* event_name,
208                                APIPermission::ID* permission) {
209     PrefMap::iterator it = event_mapping_.find(browser_pref);
210     if (it != event_mapping_.end()) {
211       *event_name = it->second.pref_name;
212       *permission = it->second.read_permission;
213       return true;
214     }
215     return false;
216   }
217
218   PrefTransformerInterface* FindTransformerForBrowserPref(
219       const std::string& browser_pref) {
220     std::map<std::string, PrefTransformerInterface*>::iterator it =
221         transformers_.find(browser_pref);
222     if (it != transformers_.end())
223       return it->second;
224     else
225       return identity_transformer_.get();
226   }
227
228  private:
229   friend struct DefaultSingletonTraits<PrefMapping>;
230
231   PrefMapping() {
232     identity_transformer_.reset(new IdentityPrefTransformer());
233     for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
234       mapping_[kPrefMapping[i].extension_pref] =
235           PrefMapData(kPrefMapping[i].browser_pref,
236                       kPrefMapping[i].read_permission,
237                       kPrefMapping[i].write_permission);
238       std::string event_name =
239           base::StringPrintf(kOnPrefChangeFormat,
240                              kPrefMapping[i].extension_pref);
241       event_mapping_[kPrefMapping[i].browser_pref] =
242           PrefMapData(event_name,
243                       kPrefMapping[i].read_permission,
244                       kPrefMapping[i].write_permission);
245     }
246     DCHECK_EQ(arraysize(kPrefMapping), mapping_.size());
247     DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size());
248     RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer());
249     RegisterPrefTransformer(prefs::kBlockThirdPartyCookies,
250                             new InvertBooleanTransformer());
251     RegisterPrefTransformer(prefs::kNetworkPredictionOptions,
252                             new NetworkPredictionTransformer());
253   }
254
255   ~PrefMapping() {
256     STLDeleteContainerPairSecondPointers(transformers_.begin(),
257                                          transformers_.end());
258   }
259
260   void RegisterPrefTransformer(const std::string& browser_pref,
261                                PrefTransformerInterface* transformer) {
262     DCHECK_EQ(0u, transformers_.count(browser_pref)) <<
263         "Trying to register pref transformer for " << browser_pref << " twice";
264     transformers_[browser_pref] = transformer;
265   }
266
267   struct PrefMapData {
268     PrefMapData()
269         : read_permission(APIPermission::kInvalid),
270           write_permission(APIPermission::kInvalid) {}
271
272     PrefMapData(const std::string& pref_name,
273                 APIPermission::ID read,
274                 APIPermission::ID write)
275         : pref_name(pref_name),
276           read_permission(read),
277           write_permission(write) {}
278
279     // Browser or extension preference to which the data maps.
280     std::string pref_name;
281
282     // Permission needed to read the preference.
283     APIPermission::ID read_permission;
284
285     // Permission needed to write the preference.
286     APIPermission::ID write_permission;
287   };
288
289   typedef std::map<std::string, PrefMapData> PrefMap;
290
291   // Mapping from extension pref keys to browser pref keys and permissions.
292   PrefMap mapping_;
293
294   // Mapping from browser pref keys to extension event names and permissions.
295   PrefMap event_mapping_;
296
297   // Mapping from browser pref keys to transformers.
298   std::map<std::string, PrefTransformerInterface*> transformers_;
299
300   scoped_ptr<PrefTransformerInterface> identity_transformer_;
301
302   DISALLOW_COPY_AND_ASSIGN(PrefMapping);
303 };
304
305 }  // namespace
306
307 PreferenceEventRouter::PreferenceEventRouter(Profile* profile)
308     : profile_(profile) {
309   registrar_.Init(profile_->GetPrefs());
310   incognito_registrar_.Init(profile_->GetOffTheRecordPrefs());
311   for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
312     registrar_.Add(kPrefMapping[i].browser_pref,
313                    base::Bind(&PreferenceEventRouter::OnPrefChanged,
314                               base::Unretained(this),
315                               registrar_.prefs()));
316     incognito_registrar_.Add(kPrefMapping[i].browser_pref,
317                              base::Bind(&PreferenceEventRouter::OnPrefChanged,
318                                         base::Unretained(this),
319                                         incognito_registrar_.prefs()));
320   }
321 }
322
323 PreferenceEventRouter::~PreferenceEventRouter() { }
324
325 void PreferenceEventRouter::OnPrefChanged(PrefService* pref_service,
326                                           const std::string& browser_pref) {
327   bool incognito = (pref_service != profile_->GetPrefs());
328
329   std::string event_name;
330   APIPermission::ID permission = APIPermission::kInvalid;
331   bool rv = PrefMapping::GetInstance()->FindEventForBrowserPref(
332       browser_pref, &event_name, &permission);
333   DCHECK(rv);
334
335   base::ListValue args;
336   base::DictionaryValue* dict = new base::DictionaryValue();
337   args.Append(dict);
338   const PrefService::Preference* pref =
339       pref_service->FindPreference(browser_pref.c_str());
340   CHECK(pref);
341   PrefTransformerInterface* transformer =
342       PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
343   base::Value* transformed_value =
344       transformer->BrowserToExtensionPref(pref->GetValue());
345   if (!transformed_value) {
346     LOG(ERROR) << ErrorUtils::FormatErrorMessage(kConversionErrorMessage,
347                                                  pref->name());
348     return;
349   }
350
351   dict->Set(keys::kValue, transformed_value);
352   if (incognito) {
353     ExtensionPrefs* ep = ExtensionPrefs::Get(profile_);
354     dict->SetBoolean(keys::kIncognitoSpecific,
355                      ep->HasIncognitoPrefValue(browser_pref));
356   }
357
358   helpers::DispatchEventToExtensions(profile_,
359                                      event_name,
360                                      &args,
361                                      permission,
362                                      incognito,
363                                      browser_pref);
364 }
365
366 void PreferenceAPIBase::SetExtensionControlledPref(
367     const std::string& extension_id,
368     const std::string& pref_key,
369     ExtensionPrefsScope scope,
370     base::Value* value) {
371 #ifndef NDEBUG
372   const PrefService::Preference* pref =
373       extension_prefs()->pref_service()->FindPreference(pref_key.c_str());
374   DCHECK(pref) << "Extension controlled preference key " << pref_key
375                << " not registered.";
376   DCHECK_EQ(pref->GetType(), value->GetType())
377       << "Extension controlled preference " << pref_key << " has wrong type.";
378 #endif
379
380   std::string scope_string;
381   // ScopeToPrefName() returns false if the scope is not persisted.
382   if (pref_names::ScopeToPrefName(scope, &scope_string)) {
383     // Also store in persisted Preferences file to recover after a
384     // browser restart.
385     ExtensionPrefs::ScopedDictionaryUpdate update(extension_prefs(),
386                                                   extension_id,
387                                                   scope_string);
388     base::DictionaryValue* preference = update.Get();
389     if (!preference)
390       preference = update.Create();
391     preference->SetWithoutPathExpansion(pref_key, value->DeepCopy());
392   }
393   extension_pref_value_map()->SetExtensionPref(
394       extension_id, pref_key, scope, value);
395 }
396
397 void PreferenceAPIBase::RemoveExtensionControlledPref(
398     const std::string& extension_id,
399     const std::string& pref_key,
400     ExtensionPrefsScope scope) {
401   DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key.c_str()))
402       << "Extension controlled preference key " << pref_key
403       << " not registered.";
404
405   std::string scope_string;
406   if (pref_names::ScopeToPrefName(scope, &scope_string)) {
407     ExtensionPrefs::ScopedDictionaryUpdate update(extension_prefs(),
408                                                   extension_id,
409                                                   scope_string);
410     base::DictionaryValue* preference = update.Get();
411     if (preference)
412       preference->RemoveWithoutPathExpansion(pref_key, NULL);
413   }
414   extension_pref_value_map()->RemoveExtensionPref(
415       extension_id, pref_key, scope);
416 }
417
418 bool PreferenceAPIBase::CanExtensionControlPref(
419      const std::string& extension_id,
420      const std::string& pref_key,
421      bool incognito) {
422   DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key.c_str()))
423       << "Extension controlled preference key " << pref_key
424       << " not registered.";
425
426   return extension_pref_value_map()->CanExtensionControlPref(
427        extension_id, pref_key, incognito);
428 }
429
430 bool PreferenceAPIBase::DoesExtensionControlPref(
431     const std::string& extension_id,
432     const std::string& pref_key,
433     bool* from_incognito) {
434   DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key.c_str()))
435       << "Extension controlled preference key " << pref_key
436       << " not registered.";
437
438   return extension_pref_value_map()->DoesExtensionControlPref(
439       extension_id, pref_key, from_incognito);
440 }
441
442 PreferenceAPI::PreferenceAPI(content::BrowserContext* context)
443     : profile_(Profile::FromBrowserContext(context)) {
444   for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
445     std::string event_name;
446     APIPermission::ID permission = APIPermission::kInvalid;
447     bool rv = PrefMapping::GetInstance()->FindEventForBrowserPref(
448         kPrefMapping[i].browser_pref, &event_name, &permission);
449     DCHECK(rv);
450     EventRouter::Get(profile_)->RegisterObserver(this, event_name);
451   }
452   content_settings_store()->AddObserver(this);
453 }
454
455 PreferenceAPI::~PreferenceAPI() {
456 }
457
458 void PreferenceAPI::Shutdown() {
459   EventRouter::Get(profile_)->UnregisterObserver(this);
460   if (!extension_prefs()->extensions_disabled())
461     ClearIncognitoSessionOnlyContentSettings();
462   content_settings_store()->RemoveObserver(this);
463 }
464
465 static base::LazyInstance<BrowserContextKeyedAPIFactory<PreferenceAPI> >
466     g_factory = LAZY_INSTANCE_INITIALIZER;
467
468 // static
469 BrowserContextKeyedAPIFactory<PreferenceAPI>*
470 PreferenceAPI::GetFactoryInstance() {
471   return g_factory.Pointer();
472 }
473
474 // static
475 PreferenceAPI* PreferenceAPI::Get(content::BrowserContext* context) {
476   return BrowserContextKeyedAPIFactory<PreferenceAPI>::Get(context);
477 }
478
479 void PreferenceAPI::OnListenerAdded(const EventListenerInfo& details) {
480   preference_event_router_.reset(new PreferenceEventRouter(profile_));
481   EventRouter::Get(profile_)->UnregisterObserver(this);
482 }
483
484 void PreferenceAPI::OnContentSettingChanged(const std::string& extension_id,
485                                             bool incognito) {
486   if (incognito) {
487     extension_prefs()->UpdateExtensionPref(
488         extension_id,
489         pref_names::kPrefIncognitoContentSettings,
490         content_settings_store()->GetSettingsForExtension(
491             extension_id, kExtensionPrefsScopeIncognitoPersistent));
492   } else {
493     extension_prefs()->UpdateExtensionPref(
494         extension_id,
495         pref_names::kPrefContentSettings,
496         content_settings_store()->GetSettingsForExtension(
497             extension_id, kExtensionPrefsScopeRegular));
498   }
499 }
500
501 void PreferenceAPI::ClearIncognitoSessionOnlyContentSettings() {
502   ExtensionIdList extension_ids;
503   extension_prefs()->GetExtensions(&extension_ids);
504   for (ExtensionIdList::iterator extension_id = extension_ids.begin();
505        extension_id != extension_ids.end(); ++extension_id) {
506     content_settings_store()->ClearContentSettingsForExtension(
507         *extension_id, kExtensionPrefsScopeIncognitoSessionOnly);
508   }
509 }
510
511 ExtensionPrefs* PreferenceAPI::extension_prefs() {
512   return ExtensionPrefs::Get(profile_);
513 }
514
515 ExtensionPrefValueMap* PreferenceAPI::extension_pref_value_map() {
516   return ExtensionPrefValueMapFactory::GetForBrowserContext(profile_);
517 }
518
519 scoped_refptr<ContentSettingsStore> PreferenceAPI::content_settings_store() {
520   return ContentSettingsService::Get(profile_)->content_settings_store();
521 }
522
523 template <>
524 void
525 BrowserContextKeyedAPIFactory<PreferenceAPI>::DeclareFactoryDependencies() {
526   DependsOn(ContentSettingsService::GetFactoryInstance());
527   DependsOn(ExtensionPrefsFactory::GetInstance());
528   DependsOn(ExtensionPrefValueMapFactory::GetInstance());
529   DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
530 }
531
532 PreferenceFunction::~PreferenceFunction() { }
533
534 bool PreferenceFunction::ValidateBrowserPref(
535     const std::string& extension_pref_key,
536     PreferenceFunction::PermissionType permission_type,
537     std::string* browser_pref_key) {
538   APIPermission::ID read_permission = APIPermission::kInvalid;
539   APIPermission::ID write_permission = APIPermission::kInvalid;
540   EXTENSION_FUNCTION_VALIDATE(
541       PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
542           extension_pref_key,
543           browser_pref_key,
544           &read_permission,
545           &write_permission));
546   APIPermission::ID permission = permission_type == PERMISSION_TYPE_READ
547                                      ? read_permission
548                                      : write_permission;
549   if (!extension()->permissions_data()->HasAPIPermission(permission)) {
550     error_ = ErrorUtils::FormatErrorMessage(
551         keys::kPermissionErrorMessage, extension_pref_key);
552     return false;
553   }
554   return true;
555 }
556
557 GetPreferenceFunction::~GetPreferenceFunction() { }
558
559 bool GetPreferenceFunction::RunSync() {
560   std::string pref_key;
561   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
562   base::DictionaryValue* details = NULL;
563   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
564
565   bool incognito = false;
566   if (details->HasKey(keys::kIncognitoKey))
567     EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(keys::kIncognitoKey,
568                                                     &incognito));
569
570   // Check incognito access.
571   if (incognito && !include_incognito()) {
572     error_ = keys::kIncognitoErrorMessage;
573     return false;
574   }
575
576   // Obtain pref.
577   std::string browser_pref;
578   if (!ValidateBrowserPref(
579           pref_key, PreferenceFunction::PERMISSION_TYPE_READ, &browser_pref)) {
580     return false;
581   }
582   PrefService* prefs = incognito ? GetProfile()->GetOffTheRecordPrefs()
583                                  : GetProfile()->GetPrefs();
584   const PrefService::Preference* pref =
585       prefs->FindPreference(browser_pref.c_str());
586   CHECK(pref);
587
588   scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);
589
590   // Retrieve level of control.
591   std::string level_of_control = helpers::GetLevelOfControl(
592       GetProfile(), extension_id(), browser_pref, incognito);
593   result->SetString(keys::kLevelOfControl, level_of_control);
594
595   // Retrieve pref value.
596   PrefTransformerInterface* transformer =
597       PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
598   base::Value* transformed_value =
599       transformer->BrowserToExtensionPref(pref->GetValue());
600   if (!transformed_value) {
601     LOG(ERROR) <<
602         ErrorUtils::FormatErrorMessage(kConversionErrorMessage,
603                                                 pref->name());
604     return false;
605   }
606   result->Set(keys::kValue, transformed_value);
607
608   // Retrieve incognito status.
609   if (incognito) {
610     ExtensionPrefs* ep = ExtensionPrefs::Get(GetProfile());
611     result->SetBoolean(keys::kIncognitoSpecific,
612                        ep->HasIncognitoPrefValue(browser_pref));
613   }
614
615   SetResult(result.release());
616   return true;
617 }
618
619 SetPreferenceFunction::~SetPreferenceFunction() { }
620
621 bool SetPreferenceFunction::RunSync() {
622   std::string pref_key;
623   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
624   base::DictionaryValue* details = NULL;
625   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
626
627   base::Value* value = NULL;
628   EXTENSION_FUNCTION_VALIDATE(details->Get(keys::kValue, &value));
629
630   ExtensionPrefsScope scope = kExtensionPrefsScopeRegular;
631   if (details->HasKey(keys::kScopeKey)) {
632     std::string scope_str;
633     EXTENSION_FUNCTION_VALIDATE(
634         details->GetString(keys::kScopeKey, &scope_str));
635
636     EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope));
637   }
638
639   // Check incognito scope.
640   bool incognito =
641       (scope == kExtensionPrefsScopeIncognitoPersistent ||
642        scope == kExtensionPrefsScopeIncognitoSessionOnly);
643   if (incognito) {
644     // Regular profiles can't access incognito unless include_incognito is true.
645     if (!GetProfile()->IsOffTheRecord() && !include_incognito()) {
646       error_ = keys::kIncognitoErrorMessage;
647       return false;
648     }
649   } else {
650     // Incognito profiles can't access regular mode ever, they only exist in
651     // split mode.
652     if (GetProfile()->IsOffTheRecord()) {
653       error_ = "Can't modify regular settings from an incognito context.";
654       return false;
655     }
656   }
657
658   if (scope == kExtensionPrefsScopeIncognitoSessionOnly &&
659       !GetProfile()->HasOffTheRecordProfile()) {
660     error_ = keys::kIncognitoSessionOnlyErrorMessage;
661     return false;
662   }
663
664   // Obtain pref.
665   std::string browser_pref;
666   if (!ValidateBrowserPref(
667           pref_key, PreferenceFunction::PERMISSION_TYPE_WRITE, &browser_pref)) {
668     return false;
669   }
670   ExtensionPrefs* prefs = ExtensionPrefs::Get(GetProfile());
671   const PrefService::Preference* pref =
672       prefs->pref_service()->FindPreference(browser_pref.c_str());
673   CHECK(pref);
674
675   // Validate new value.
676   PrefTransformerInterface* transformer =
677       PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
678   std::string error;
679   bool bad_message = false;
680   scoped_ptr<base::Value> browser_pref_value(
681       transformer->ExtensionToBrowserPref(value, &error, &bad_message));
682   if (!browser_pref_value) {
683     error_ = error;
684     bad_message_ = bad_message;
685     return false;
686   }
687   EXTENSION_FUNCTION_VALIDATE(browser_pref_value->GetType() == pref->GetType());
688
689   // Validate also that the stored value can be converted back by the
690   // transformer.
691   scoped_ptr<base::Value> extensionPrefValue(
692       transformer->BrowserToExtensionPref(browser_pref_value.get()));
693   if (!extensionPrefValue) {
694     error_ =  ErrorUtils::FormatErrorMessage(kConversionErrorMessage,
695                                                       pref->name());
696     bad_message_ = true;
697     return false;
698   }
699
700   PreferenceAPI::Get(GetProfile())->SetExtensionControlledPref(
701       extension_id(), browser_pref, scope, browser_pref_value.release());
702   return true;
703 }
704
705 ClearPreferenceFunction::~ClearPreferenceFunction() { }
706
707 bool ClearPreferenceFunction::RunSync() {
708   std::string pref_key;
709   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
710   base::DictionaryValue* details = NULL;
711   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
712
713   ExtensionPrefsScope scope = kExtensionPrefsScopeRegular;
714   if (details->HasKey(keys::kScopeKey)) {
715     std::string scope_str;
716     EXTENSION_FUNCTION_VALIDATE(
717         details->GetString(keys::kScopeKey, &scope_str));
718
719     EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope));
720   }
721
722   // Check incognito scope.
723   bool incognito =
724       (scope == kExtensionPrefsScopeIncognitoPersistent ||
725        scope == kExtensionPrefsScopeIncognitoSessionOnly);
726   if (incognito) {
727     // We don't check incognito permissions here, as an extension should be
728     // always allowed to clear its own settings.
729   } else {
730     // Incognito profiles can't access regular mode ever, they only exist in
731     // split mode.
732     if (GetProfile()->IsOffTheRecord()) {
733       error_ = "Can't modify regular settings from an incognito context.";
734       return false;
735     }
736   }
737
738   std::string browser_pref;
739   if (!ValidateBrowserPref(
740           pref_key, PreferenceFunction::PERMISSION_TYPE_WRITE, &browser_pref)) {
741     return false;
742   }
743
744   PreferenceAPI::Get(GetProfile())
745       ->RemoveExtensionControlledPref(extension_id(), browser_pref, scope);
746   return true;
747 }
748
749 }  // namespace extensions