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.
5 #include "chrome/browser/extensions/api/preference/preference_api.h"
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"
39 namespace keys
= extensions::preference_api_constants
;
40 namespace helpers
= extensions::preference_helpers
;
42 using base::DictionaryValue
;
44 namespace extensions
{
48 struct PrefMappingEntry
{
49 // Name of the preference referenced by the extension API JSON.
50 const char* extension_pref
;
52 // Name of the preference in the PrefStores.
53 const char* browser_pref
;
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
;
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
;
66 const char kOnPrefChangeFormat
[] = "types.ChromeSetting.%s.onChange";
67 const char kConversionErrorMessage
[] =
68 "Internal error: Stored value for preference '*' cannot be converted "
71 PrefMappingEntry kPrefMapping
[] = {
72 {"spdy_proxy.enabled",
73 data_reduction_proxy::prefs::kDataReductionProxyEnabled
,
74 APIPermission::kDataReductionProxy
, APIPermission::kDataReductionProxy
},
75 {"data_reduction.daily_original_length",
76 data_reduction_proxy::prefs::kDailyHttpOriginalContentLength
,
77 APIPermission::kDataReductionProxy
, APIPermission::kDataReductionProxy
},
78 {"data_reduction.daily_received_length",
79 data_reduction_proxy::prefs::kDailyHttpReceivedContentLength
,
80 APIPermission::kDataReductionProxy
, APIPermission::kDataReductionProxy
},
81 {"data_reduction.update_daily_lengths",
82 data_reduction_proxy::prefs::kUpdateDailyReceivedContentLengths
,
83 APIPermission::kDataReductionProxy
, APIPermission::kDataReductionProxy
},
84 {"alternateErrorPagesEnabled", prefs::kAlternateErrorPagesEnabled
,
85 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
86 {"autofillEnabled", autofill::prefs::kAutofillEnabled
,
87 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
88 {"hyperlinkAuditingEnabled", prefs::kEnableHyperlinkAuditing
,
89 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
90 {"hotwordSearchEnabled", prefs::kHotwordSearchEnabled
,
91 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
92 {"networkPredictionEnabled", prefs::kNetworkPredictionOptions
,
93 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
94 {"passwordSavingEnabled",
95 password_manager::prefs::kPasswordManagerSavingEnabled
,
96 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
97 {"protectedContentEnabled", prefs::kEnableDRM
, APIPermission::kPrivacy
,
98 APIPermission::kPrivacy
},
99 {"proxy", prefs::kProxy
, APIPermission::kProxy
, APIPermission::kProxy
},
100 {"referrersEnabled", prefs::kEnableReferrers
, APIPermission::kPrivacy
,
101 APIPermission::kPrivacy
},
102 {"safeBrowsingEnabled", prefs::kSafeBrowsingEnabled
,
103 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
104 {"safeBrowsingExtendedReportingEnabled",
105 prefs::kSafeBrowsingExtendedReportingEnabled
, APIPermission::kPrivacy
,
106 APIPermission::kPrivacy
},
107 {"searchSuggestEnabled", prefs::kSearchSuggestEnabled
,
108 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
109 {"spellingServiceEnabled", prefs::kSpellCheckUseSpellingService
,
110 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
111 {"thirdPartyCookiesAllowed", prefs::kBlockThirdPartyCookies
,
112 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
113 {"translationServiceEnabled", prefs::kEnableTranslate
,
114 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
115 #if defined(ENABLE_WEBRTC)
116 {"webRTCMultipleRoutesEnabled", prefs::kWebRTCMultipleRoutesEnabled
,
117 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
119 // accessibilityFeatures.animationPolicy is available for
120 // all platforms but the others from accessibilityFeatures
121 // is only available for OS_CHROMEOS.
122 {"animationPolicy", prefs::kAnimationPolicy
,
123 APIPermission::kAccessibilityFeaturesRead
,
124 APIPermission::kAccessibilityFeaturesModify
},
125 #if defined(OS_CHROMEOS)
126 {"autoclick", prefs::kAccessibilityAutoclickEnabled
,
127 APIPermission::kAccessibilityFeaturesRead
,
128 APIPermission::kAccessibilityFeaturesModify
},
129 {"highContrast", prefs::kAccessibilityHighContrastEnabled
,
130 APIPermission::kAccessibilityFeaturesRead
,
131 APIPermission::kAccessibilityFeaturesModify
},
132 {"largeCursor", prefs::kAccessibilityLargeCursorEnabled
,
133 APIPermission::kAccessibilityFeaturesRead
,
134 APIPermission::kAccessibilityFeaturesModify
},
135 {"screenMagnifier", prefs::kAccessibilityScreenMagnifierEnabled
,
136 APIPermission::kAccessibilityFeaturesRead
,
137 APIPermission::kAccessibilityFeaturesModify
},
138 {"spokenFeedback", prefs::kAccessibilitySpokenFeedbackEnabled
,
139 APIPermission::kAccessibilityFeaturesRead
,
140 APIPermission::kAccessibilityFeaturesModify
},
141 {"stickyKeys", prefs::kAccessibilityStickyKeysEnabled
,
142 APIPermission::kAccessibilityFeaturesRead
,
143 APIPermission::kAccessibilityFeaturesModify
},
144 {"virtualKeyboard", prefs::kAccessibilityVirtualKeyboardEnabled
,
145 APIPermission::kAccessibilityFeaturesRead
,
146 APIPermission::kAccessibilityFeaturesModify
},
150 class IdentityPrefTransformer
: public PrefTransformerInterface
{
152 base::Value
* ExtensionToBrowserPref(const base::Value
* extension_pref
,
154 bool* bad_message
) override
{
155 return extension_pref
->DeepCopy();
158 base::Value
* BrowserToExtensionPref(
159 const base::Value
* browser_pref
) override
{
160 return browser_pref
->DeepCopy();
164 class InvertBooleanTransformer
: public PrefTransformerInterface
{
166 base::Value
* ExtensionToBrowserPref(const base::Value
* extension_pref
,
168 bool* bad_message
) override
{
169 return InvertBooleanValue(extension_pref
);
172 base::Value
* BrowserToExtensionPref(
173 const base::Value
* browser_pref
) override
{
174 return InvertBooleanValue(browser_pref
);
178 static base::Value
* InvertBooleanValue(const base::Value
* value
) {
179 bool bool_value
= false;
180 bool result
= value
->GetAsBoolean(&bool_value
);
182 return new base::FundamentalValue(!bool_value
);
186 class NetworkPredictionTransformer
: public PrefTransformerInterface
{
188 base::Value
* ExtensionToBrowserPref(const base::Value
* extension_pref
,
190 bool* bad_message
) override
{
191 bool bool_value
= false;
192 const bool pref_found
= extension_pref
->GetAsBoolean(&bool_value
);
193 DCHECK(pref_found
) << "Preference not found.";
195 return new base::FundamentalValue(
196 chrome_browser_net::NETWORK_PREDICTION_DEFAULT
);
198 return new base::FundamentalValue(
199 chrome_browser_net::NETWORK_PREDICTION_NEVER
);
203 base::Value
* BrowserToExtensionPref(
204 const base::Value
* browser_pref
) override
{
205 int int_value
= chrome_browser_net::NETWORK_PREDICTION_DEFAULT
;
206 const bool pref_found
= browser_pref
->GetAsInteger(&int_value
);
207 DCHECK(pref_found
) << "Preference not found.";
208 return new base::FundamentalValue(
209 int_value
!= chrome_browser_net::NETWORK_PREDICTION_NEVER
);
215 static PrefMapping
* GetInstance() {
216 return Singleton
<PrefMapping
>::get();
219 bool FindBrowserPrefForExtensionPref(const std::string
& extension_pref
,
220 std::string
* browser_pref
,
221 APIPermission::ID
* read_permission
,
222 APIPermission::ID
* write_permission
) {
223 PrefMap::iterator it
= mapping_
.find(extension_pref
);
224 if (it
!= mapping_
.end()) {
225 *browser_pref
= it
->second
.pref_name
;
226 *read_permission
= it
->second
.read_permission
;
227 *write_permission
= it
->second
.write_permission
;
233 bool FindEventForBrowserPref(const std::string
& browser_pref
,
234 std::string
* event_name
,
235 APIPermission::ID
* permission
) {
236 PrefMap::iterator it
= event_mapping_
.find(browser_pref
);
237 if (it
!= event_mapping_
.end()) {
238 *event_name
= it
->second
.pref_name
;
239 *permission
= it
->second
.read_permission
;
245 PrefTransformerInterface
* FindTransformerForBrowserPref(
246 const std::string
& browser_pref
) {
247 std::map
<std::string
, PrefTransformerInterface
*>::iterator it
=
248 transformers_
.find(browser_pref
);
249 if (it
!= transformers_
.end())
252 return identity_transformer_
.get();
256 friend struct DefaultSingletonTraits
<PrefMapping
>;
259 identity_transformer_
.reset(new IdentityPrefTransformer());
260 for (size_t i
= 0; i
< arraysize(kPrefMapping
); ++i
) {
261 mapping_
[kPrefMapping
[i
].extension_pref
] =
262 PrefMapData(kPrefMapping
[i
].browser_pref
,
263 kPrefMapping
[i
].read_permission
,
264 kPrefMapping
[i
].write_permission
);
265 std::string event_name
=
266 base::StringPrintf(kOnPrefChangeFormat
,
267 kPrefMapping
[i
].extension_pref
);
268 event_mapping_
[kPrefMapping
[i
].browser_pref
] =
269 PrefMapData(event_name
,
270 kPrefMapping
[i
].read_permission
,
271 kPrefMapping
[i
].write_permission
);
273 DCHECK_EQ(arraysize(kPrefMapping
), mapping_
.size());
274 DCHECK_EQ(arraysize(kPrefMapping
), event_mapping_
.size());
275 RegisterPrefTransformer(prefs::kProxy
, new ProxyPrefTransformer());
276 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies
,
277 new InvertBooleanTransformer());
278 RegisterPrefTransformer(prefs::kNetworkPredictionOptions
,
279 new NetworkPredictionTransformer());
283 STLDeleteContainerPairSecondPointers(transformers_
.begin(),
284 transformers_
.end());
287 void RegisterPrefTransformer(const std::string
& browser_pref
,
288 PrefTransformerInterface
* transformer
) {
289 DCHECK_EQ(0u, transformers_
.count(browser_pref
)) <<
290 "Trying to register pref transformer for " << browser_pref
<< " twice";
291 transformers_
[browser_pref
] = transformer
;
296 : read_permission(APIPermission::kInvalid
),
297 write_permission(APIPermission::kInvalid
) {}
299 PrefMapData(const std::string
& pref_name
,
300 APIPermission::ID read
,
301 APIPermission::ID write
)
302 : pref_name(pref_name
),
303 read_permission(read
),
304 write_permission(write
) {}
306 // Browser or extension preference to which the data maps.
307 std::string pref_name
;
309 // Permission needed to read the preference.
310 APIPermission::ID read_permission
;
312 // Permission needed to write the preference.
313 APIPermission::ID write_permission
;
316 typedef std::map
<std::string
, PrefMapData
> PrefMap
;
318 // Mapping from extension pref keys to browser pref keys and permissions.
321 // Mapping from browser pref keys to extension event names and permissions.
322 PrefMap event_mapping_
;
324 // Mapping from browser pref keys to transformers.
325 std::map
<std::string
, PrefTransformerInterface
*> transformers_
;
327 scoped_ptr
<PrefTransformerInterface
> identity_transformer_
;
329 DISALLOW_COPY_AND_ASSIGN(PrefMapping
);
334 PreferenceEventRouter::PreferenceEventRouter(Profile
* profile
)
335 : profile_(profile
) {
336 registrar_
.Init(profile_
->GetPrefs());
337 incognito_registrar_
.Init(profile_
->GetOffTheRecordPrefs());
338 for (size_t i
= 0; i
< arraysize(kPrefMapping
); ++i
) {
339 registrar_
.Add(kPrefMapping
[i
].browser_pref
,
340 base::Bind(&PreferenceEventRouter::OnPrefChanged
,
341 base::Unretained(this),
342 registrar_
.prefs()));
343 incognito_registrar_
.Add(kPrefMapping
[i
].browser_pref
,
344 base::Bind(&PreferenceEventRouter::OnPrefChanged
,
345 base::Unretained(this),
346 incognito_registrar_
.prefs()));
350 PreferenceEventRouter::~PreferenceEventRouter() { }
352 void PreferenceEventRouter::OnPrefChanged(PrefService
* pref_service
,
353 const std::string
& browser_pref
) {
354 bool incognito
= (pref_service
!= profile_
->GetPrefs());
356 std::string event_name
;
357 APIPermission::ID permission
= APIPermission::kInvalid
;
358 bool rv
= PrefMapping::GetInstance()->FindEventForBrowserPref(
359 browser_pref
, &event_name
, &permission
);
362 base::ListValue args
;
363 base::DictionaryValue
* dict
= new base::DictionaryValue();
365 const PrefService::Preference
* pref
=
366 pref_service
->FindPreference(browser_pref
.c_str());
368 PrefTransformerInterface
* transformer
=
369 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref
);
370 base::Value
* transformed_value
=
371 transformer
->BrowserToExtensionPref(pref
->GetValue());
372 if (!transformed_value
) {
373 LOG(ERROR
) << ErrorUtils::FormatErrorMessage(kConversionErrorMessage
,
378 dict
->Set(keys::kValue
, transformed_value
);
380 ExtensionPrefs
* ep
= ExtensionPrefs::Get(profile_
);
381 dict
->SetBoolean(keys::kIncognitoSpecific
,
382 ep
->HasIncognitoPrefValue(browser_pref
));
385 helpers::DispatchEventToExtensions(profile_
,
393 void PreferenceAPIBase::SetExtensionControlledPref(
394 const std::string
& extension_id
,
395 const std::string
& pref_key
,
396 ExtensionPrefsScope scope
,
397 base::Value
* value
) {
399 const PrefService::Preference
* pref
=
400 extension_prefs()->pref_service()->FindPreference(pref_key
.c_str());
401 DCHECK(pref
) << "Extension controlled preference key " << pref_key
402 << " not registered.";
403 DCHECK_EQ(pref
->GetType(), value
->GetType())
404 << "Extension controlled preference " << pref_key
<< " has wrong type.";
407 std::string scope_string
;
408 // ScopeToPrefName() returns false if the scope is not persisted.
409 if (pref_names::ScopeToPrefName(scope
, &scope_string
)) {
410 // Also store in persisted Preferences file to recover after a
412 ExtensionPrefs::ScopedDictionaryUpdate
update(extension_prefs(),
415 base::DictionaryValue
* preference
= update
.Get();
417 preference
= update
.Create();
418 preference
->SetWithoutPathExpansion(pref_key
, value
->DeepCopy());
420 extension_pref_value_map()->SetExtensionPref(
421 extension_id
, pref_key
, scope
, value
);
424 void PreferenceAPIBase::RemoveExtensionControlledPref(
425 const std::string
& extension_id
,
426 const std::string
& pref_key
,
427 ExtensionPrefsScope scope
) {
428 DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key
.c_str()))
429 << "Extension controlled preference key " << pref_key
430 << " not registered.";
432 std::string scope_string
;
433 if (pref_names::ScopeToPrefName(scope
, &scope_string
)) {
434 ExtensionPrefs::ScopedDictionaryUpdate
update(extension_prefs(),
437 base::DictionaryValue
* preference
= update
.Get();
439 preference
->RemoveWithoutPathExpansion(pref_key
, NULL
);
441 extension_pref_value_map()->RemoveExtensionPref(
442 extension_id
, pref_key
, scope
);
445 bool PreferenceAPIBase::CanExtensionControlPref(
446 const std::string
& extension_id
,
447 const std::string
& pref_key
,
449 DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key
.c_str()))
450 << "Extension controlled preference key " << pref_key
451 << " not registered.";
453 return extension_pref_value_map()->CanExtensionControlPref(
454 extension_id
, pref_key
, incognito
);
457 bool PreferenceAPIBase::DoesExtensionControlPref(
458 const std::string
& extension_id
,
459 const std::string
& pref_key
,
460 bool* from_incognito
) {
461 DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key
.c_str()))
462 << "Extension controlled preference key " << pref_key
463 << " not registered.";
465 return extension_pref_value_map()->DoesExtensionControlPref(
466 extension_id
, pref_key
, from_incognito
);
469 PreferenceAPI::PreferenceAPI(content::BrowserContext
* context
)
470 : profile_(Profile::FromBrowserContext(context
)) {
471 for (size_t i
= 0; i
< arraysize(kPrefMapping
); ++i
) {
472 std::string event_name
;
473 APIPermission::ID permission
= APIPermission::kInvalid
;
474 bool rv
= PrefMapping::GetInstance()->FindEventForBrowserPref(
475 kPrefMapping
[i
].browser_pref
, &event_name
, &permission
);
477 EventRouter::Get(profile_
)->RegisterObserver(this, event_name
);
479 content_settings_store()->AddObserver(this);
482 PreferenceAPI::~PreferenceAPI() {
485 void PreferenceAPI::Shutdown() {
486 EventRouter::Get(profile_
)->UnregisterObserver(this);
487 if (!extension_prefs()->extensions_disabled())
488 ClearIncognitoSessionOnlyContentSettings();
489 content_settings_store()->RemoveObserver(this);
492 static base::LazyInstance
<BrowserContextKeyedAPIFactory
<PreferenceAPI
> >
493 g_factory
= LAZY_INSTANCE_INITIALIZER
;
496 BrowserContextKeyedAPIFactory
<PreferenceAPI
>*
497 PreferenceAPI::GetFactoryInstance() {
498 return g_factory
.Pointer();
502 PreferenceAPI
* PreferenceAPI::Get(content::BrowserContext
* context
) {
503 return BrowserContextKeyedAPIFactory
<PreferenceAPI
>::Get(context
);
506 void PreferenceAPI::OnListenerAdded(const EventListenerInfo
& details
) {
507 preference_event_router_
.reset(new PreferenceEventRouter(profile_
));
508 EventRouter::Get(profile_
)->UnregisterObserver(this);
511 void PreferenceAPI::OnContentSettingChanged(const std::string
& extension_id
,
514 extension_prefs()->UpdateExtensionPref(
516 pref_names::kPrefIncognitoContentSettings
,
517 content_settings_store()->GetSettingsForExtension(
518 extension_id
, kExtensionPrefsScopeIncognitoPersistent
));
520 extension_prefs()->UpdateExtensionPref(
522 pref_names::kPrefContentSettings
,
523 content_settings_store()->GetSettingsForExtension(
524 extension_id
, kExtensionPrefsScopeRegular
));
528 void PreferenceAPI::ClearIncognitoSessionOnlyContentSettings() {
529 ExtensionIdList extension_ids
;
530 extension_prefs()->GetExtensions(&extension_ids
);
531 for (ExtensionIdList::iterator extension_id
= extension_ids
.begin();
532 extension_id
!= extension_ids
.end(); ++extension_id
) {
533 content_settings_store()->ClearContentSettingsForExtension(
534 *extension_id
, kExtensionPrefsScopeIncognitoSessionOnly
);
538 ExtensionPrefs
* PreferenceAPI::extension_prefs() {
539 return ExtensionPrefs::Get(profile_
);
542 ExtensionPrefValueMap
* PreferenceAPI::extension_pref_value_map() {
543 return ExtensionPrefValueMapFactory::GetForBrowserContext(profile_
);
546 scoped_refptr
<ContentSettingsStore
> PreferenceAPI::content_settings_store() {
547 return ContentSettingsService::Get(profile_
)->content_settings_store();
552 BrowserContextKeyedAPIFactory
<PreferenceAPI
>::DeclareFactoryDependencies() {
553 DependsOn(ContentSettingsService::GetFactoryInstance());
554 DependsOn(ExtensionPrefsFactory::GetInstance());
555 DependsOn(ExtensionPrefValueMapFactory::GetInstance());
556 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
559 PreferenceFunction::~PreferenceFunction() { }
561 bool PreferenceFunction::ValidateBrowserPref(
562 const std::string
& extension_pref_key
,
563 PreferenceFunction::PermissionType permission_type
,
564 std::string
* browser_pref_key
) {
565 APIPermission::ID read_permission
= APIPermission::kInvalid
;
566 APIPermission::ID write_permission
= APIPermission::kInvalid
;
567 EXTENSION_FUNCTION_VALIDATE(
568 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
573 APIPermission::ID permission
= permission_type
== PERMISSION_TYPE_READ
576 if (!extension()->permissions_data()->HasAPIPermission(permission
)) {
577 error_
= ErrorUtils::FormatErrorMessage(
578 keys::kPermissionErrorMessage
, extension_pref_key
);
584 GetPreferenceFunction::~GetPreferenceFunction() { }
586 bool GetPreferenceFunction::RunSync() {
587 std::string pref_key
;
588 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(0, &pref_key
));
589 base::DictionaryValue
* details
= NULL
;
590 EXTENSION_FUNCTION_VALIDATE(args_
->GetDictionary(1, &details
));
592 bool incognito
= false;
593 if (details
->HasKey(keys::kIncognitoKey
))
594 EXTENSION_FUNCTION_VALIDATE(details
->GetBoolean(keys::kIncognitoKey
,
597 // Check incognito access.
598 if (incognito
&& !include_incognito()) {
599 error_
= keys::kIncognitoErrorMessage
;
604 std::string browser_pref
;
605 if (!ValidateBrowserPref(
606 pref_key
, PreferenceFunction::PERMISSION_TYPE_READ
, &browser_pref
)) {
609 PrefService
* prefs
= incognito
? GetProfile()->GetOffTheRecordPrefs()
610 : GetProfile()->GetPrefs();
611 const PrefService::Preference
* pref
=
612 prefs
->FindPreference(browser_pref
.c_str());
615 scoped_ptr
<base::DictionaryValue
> result(new base::DictionaryValue
);
617 // Retrieve level of control.
618 std::string level_of_control
= helpers::GetLevelOfControl(
619 GetProfile(), extension_id(), browser_pref
, incognito
);
620 result
->SetString(keys::kLevelOfControl
, level_of_control
);
622 // Retrieve pref value.
623 PrefTransformerInterface
* transformer
=
624 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref
);
625 base::Value
* transformed_value
=
626 transformer
->BrowserToExtensionPref(pref
->GetValue());
627 if (!transformed_value
) {
629 ErrorUtils::FormatErrorMessage(kConversionErrorMessage
,
633 result
->Set(keys::kValue
, transformed_value
);
635 // Retrieve incognito status.
637 ExtensionPrefs
* ep
= ExtensionPrefs::Get(GetProfile());
638 result
->SetBoolean(keys::kIncognitoSpecific
,
639 ep
->HasIncognitoPrefValue(browser_pref
));
642 SetResult(result
.release());
646 SetPreferenceFunction::~SetPreferenceFunction() { }
648 bool SetPreferenceFunction::RunSync() {
649 std::string pref_key
;
650 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(0, &pref_key
));
651 base::DictionaryValue
* details
= NULL
;
652 EXTENSION_FUNCTION_VALIDATE(args_
->GetDictionary(1, &details
));
654 base::Value
* value
= NULL
;
655 EXTENSION_FUNCTION_VALIDATE(details
->Get(keys::kValue
, &value
));
657 ExtensionPrefsScope scope
= kExtensionPrefsScopeRegular
;
658 if (details
->HasKey(keys::kScopeKey
)) {
659 std::string scope_str
;
660 EXTENSION_FUNCTION_VALIDATE(
661 details
->GetString(keys::kScopeKey
, &scope_str
));
663 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str
, &scope
));
666 // Check incognito scope.
668 (scope
== kExtensionPrefsScopeIncognitoPersistent
||
669 scope
== kExtensionPrefsScopeIncognitoSessionOnly
);
671 // Regular profiles can't access incognito unless include_incognito is true.
672 if (!GetProfile()->IsOffTheRecord() && !include_incognito()) {
673 error_
= keys::kIncognitoErrorMessage
;
677 // Incognito profiles can't access regular mode ever, they only exist in
679 if (GetProfile()->IsOffTheRecord()) {
680 error_
= "Can't modify regular settings from an incognito context.";
685 if (scope
== kExtensionPrefsScopeIncognitoSessionOnly
&&
686 !GetProfile()->HasOffTheRecordProfile()) {
687 error_
= keys::kIncognitoSessionOnlyErrorMessage
;
692 std::string browser_pref
;
693 if (!ValidateBrowserPref(
694 pref_key
, PreferenceFunction::PERMISSION_TYPE_WRITE
, &browser_pref
)) {
697 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(GetProfile());
698 const PrefService::Preference
* pref
=
699 prefs
->pref_service()->FindPreference(browser_pref
.c_str());
702 // Validate new value.
703 PrefTransformerInterface
* transformer
=
704 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref
);
706 bool bad_message
= false;
707 scoped_ptr
<base::Value
> browser_pref_value(
708 transformer
->ExtensionToBrowserPref(value
, &error
, &bad_message
));
709 if (!browser_pref_value
) {
711 bad_message_
= bad_message
;
714 EXTENSION_FUNCTION_VALIDATE(browser_pref_value
->GetType() == pref
->GetType());
716 // Validate also that the stored value can be converted back by the
718 scoped_ptr
<base::Value
> extensionPrefValue(
719 transformer
->BrowserToExtensionPref(browser_pref_value
.get()));
720 if (!extensionPrefValue
) {
721 error_
= ErrorUtils::FormatErrorMessage(kConversionErrorMessage
,
727 PreferenceAPI::Get(GetProfile())->SetExtensionControlledPref(
728 extension_id(), browser_pref
, scope
, browser_pref_value
.release());
732 ClearPreferenceFunction::~ClearPreferenceFunction() { }
734 bool ClearPreferenceFunction::RunSync() {
735 std::string pref_key
;
736 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(0, &pref_key
));
737 base::DictionaryValue
* details
= NULL
;
738 EXTENSION_FUNCTION_VALIDATE(args_
->GetDictionary(1, &details
));
740 ExtensionPrefsScope scope
= kExtensionPrefsScopeRegular
;
741 if (details
->HasKey(keys::kScopeKey
)) {
742 std::string scope_str
;
743 EXTENSION_FUNCTION_VALIDATE(
744 details
->GetString(keys::kScopeKey
, &scope_str
));
746 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str
, &scope
));
749 // Check incognito scope.
751 (scope
== kExtensionPrefsScopeIncognitoPersistent
||
752 scope
== kExtensionPrefsScopeIncognitoSessionOnly
);
754 // We don't check incognito permissions here, as an extension should be
755 // always allowed to clear its own settings.
757 // Incognito profiles can't access regular mode ever, they only exist in
759 if (GetProfile()->IsOffTheRecord()) {
760 error_
= "Can't modify regular settings from an incognito context.";
765 std::string browser_pref
;
766 if (!ValidateBrowserPref(
767 pref_key
, PreferenceFunction::PERMISSION_TYPE_WRITE
, &browser_pref
)) {
771 PreferenceAPI::Get(GetProfile())
772 ->RemoveExtensionControlledPref(extension_id(), browser_pref
, scope
);
776 } // namespace extensions