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/content_settings/core/common/pref_names.h"
26 #include "components/translate/core/common/translate_pref_names.h"
27 #include "content/public/browser/notification_details.h"
28 #include "content/public/browser/notification_source.h"
29 #include "extensions/browser/extension_pref_value_map.h"
30 #include "extensions/browser/extension_pref_value_map_factory.h"
31 #include "extensions/browser/extension_prefs.h"
32 #include "extensions/browser/extension_prefs_factory.h"
33 #include "extensions/browser/extension_system_provider.h"
34 #include "extensions/browser/extensions_browser_client.h"
35 #include "extensions/browser/pref_names.h"
36 #include "extensions/common/error_utils.h"
37 #include "extensions/common/permissions/api_permission.h"
38 #include "extensions/common/permissions/permissions_data.h"
40 namespace keys
= extensions::preference_api_constants
;
41 namespace helpers
= extensions::preference_helpers
;
43 using base::DictionaryValue
;
45 namespace extensions
{
49 struct PrefMappingEntry
{
50 // Name of the preference referenced by the extension API JSON.
51 const char* extension_pref
;
53 // Name of the preference in the PrefStores.
54 const char* browser_pref
;
56 // Permission required to read and observe this preference.
57 // Use APIPermission::kInvalid for |read_permission| to express that the read
58 // permission should not be granted.
59 APIPermission::ID read_permission
;
61 // Permission required to write this preference.
62 // Use APIPermission::kInvalid for |write_permission| to express that the
63 // write permission should not be granted.
64 APIPermission::ID write_permission
;
67 const char kOnPrefChangeFormat
[] = "types.ChromeSetting.%s.onChange";
68 const char kConversionErrorMessage
[] =
69 "Internal error: Stored value for preference '*' cannot be converted "
72 PrefMappingEntry kPrefMapping
[] = {
73 {"spdy_proxy.enabled",
74 data_reduction_proxy::prefs::kDataReductionProxyEnabled
,
75 APIPermission::kDataReductionProxy
, APIPermission::kDataReductionProxy
},
76 {"data_reduction.daily_original_length",
77 data_reduction_proxy::prefs::kDailyHttpOriginalContentLength
,
78 APIPermission::kDataReductionProxy
, APIPermission::kDataReductionProxy
},
79 {"data_reduction.daily_received_length",
80 data_reduction_proxy::prefs::kDailyHttpReceivedContentLength
,
81 APIPermission::kDataReductionProxy
, APIPermission::kDataReductionProxy
},
82 {"alternateErrorPagesEnabled", prefs::kAlternateErrorPagesEnabled
,
83 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
84 {"autofillEnabled", autofill::prefs::kAutofillEnabled
,
85 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
86 {"hyperlinkAuditingEnabled", prefs::kEnableHyperlinkAuditing
,
87 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
88 {"hotwordSearchEnabled", prefs::kHotwordSearchEnabled
,
89 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
90 {"networkPredictionEnabled", prefs::kNetworkPredictionOptions
,
91 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
92 {"passwordSavingEnabled",
93 password_manager::prefs::kPasswordManagerSavingEnabled
,
94 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
95 {"protectedContentEnabled", prefs::kEnableDRM
, APIPermission::kPrivacy
,
96 APIPermission::kPrivacy
},
97 {"proxy", prefs::kProxy
, APIPermission::kProxy
, APIPermission::kProxy
},
98 {"referrersEnabled", prefs::kEnableReferrers
, APIPermission::kPrivacy
,
99 APIPermission::kPrivacy
},
100 {"safeBrowsingEnabled", prefs::kSafeBrowsingEnabled
,
101 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
102 {"safeBrowsingExtendedReportingEnabled",
103 prefs::kSafeBrowsingExtendedReportingEnabled
, APIPermission::kPrivacy
,
104 APIPermission::kPrivacy
},
105 {"searchSuggestEnabled", prefs::kSearchSuggestEnabled
,
106 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
107 {"spellingServiceEnabled", prefs::kSpellCheckUseSpellingService
,
108 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
109 {"thirdPartyCookiesAllowed", prefs::kBlockThirdPartyCookies
,
110 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
111 {"translationServiceEnabled", prefs::kEnableTranslate
,
112 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
113 #if defined(ENABLE_WEBRTC)
114 {"webRTCMultipleRoutesEnabled", prefs::kWebRTCMultipleRoutesEnabled
,
115 APIPermission::kPrivacy
, APIPermission::kPrivacy
},
117 // accessibilityFeatures.animationPolicy is available for
118 // all platforms but the others from accessibilityFeatures
119 // is only available for OS_CHROMEOS.
120 {"animationPolicy", prefs::kAnimationPolicy
,
121 APIPermission::kAccessibilityFeaturesRead
,
122 APIPermission::kAccessibilityFeaturesModify
},
123 #if defined(OS_CHROMEOS)
124 {"autoclick", prefs::kAccessibilityAutoclickEnabled
,
125 APIPermission::kAccessibilityFeaturesRead
,
126 APIPermission::kAccessibilityFeaturesModify
},
127 {"highContrast", prefs::kAccessibilityHighContrastEnabled
,
128 APIPermission::kAccessibilityFeaturesRead
,
129 APIPermission::kAccessibilityFeaturesModify
},
130 {"largeCursor", prefs::kAccessibilityLargeCursorEnabled
,
131 APIPermission::kAccessibilityFeaturesRead
,
132 APIPermission::kAccessibilityFeaturesModify
},
133 {"screenMagnifier", prefs::kAccessibilityScreenMagnifierEnabled
,
134 APIPermission::kAccessibilityFeaturesRead
,
135 APIPermission::kAccessibilityFeaturesModify
},
136 {"spokenFeedback", prefs::kAccessibilitySpokenFeedbackEnabled
,
137 APIPermission::kAccessibilityFeaturesRead
,
138 APIPermission::kAccessibilityFeaturesModify
},
139 {"stickyKeys", prefs::kAccessibilityStickyKeysEnabled
,
140 APIPermission::kAccessibilityFeaturesRead
,
141 APIPermission::kAccessibilityFeaturesModify
},
142 {"virtualKeyboard", prefs::kAccessibilityVirtualKeyboardEnabled
,
143 APIPermission::kAccessibilityFeaturesRead
,
144 APIPermission::kAccessibilityFeaturesModify
},
148 class IdentityPrefTransformer
: public PrefTransformerInterface
{
150 base::Value
* ExtensionToBrowserPref(const base::Value
* extension_pref
,
152 bool* bad_message
) override
{
153 return extension_pref
->DeepCopy();
156 base::Value
* BrowserToExtensionPref(
157 const base::Value
* browser_pref
) override
{
158 return browser_pref
->DeepCopy();
162 class InvertBooleanTransformer
: public PrefTransformerInterface
{
164 base::Value
* ExtensionToBrowserPref(const base::Value
* extension_pref
,
166 bool* bad_message
) override
{
167 return InvertBooleanValue(extension_pref
);
170 base::Value
* BrowserToExtensionPref(
171 const base::Value
* browser_pref
) override
{
172 return InvertBooleanValue(browser_pref
);
176 static base::Value
* InvertBooleanValue(const base::Value
* value
) {
177 bool bool_value
= false;
178 bool result
= value
->GetAsBoolean(&bool_value
);
180 return new base::FundamentalValue(!bool_value
);
184 class NetworkPredictionTransformer
: public PrefTransformerInterface
{
186 base::Value
* ExtensionToBrowserPref(const base::Value
* extension_pref
,
188 bool* bad_message
) override
{
189 bool bool_value
= false;
190 const bool pref_found
= extension_pref
->GetAsBoolean(&bool_value
);
191 DCHECK(pref_found
) << "Preference not found.";
193 return new base::FundamentalValue(
194 chrome_browser_net::NETWORK_PREDICTION_DEFAULT
);
196 return new base::FundamentalValue(
197 chrome_browser_net::NETWORK_PREDICTION_NEVER
);
201 base::Value
* BrowserToExtensionPref(
202 const base::Value
* browser_pref
) override
{
203 int int_value
= chrome_browser_net::NETWORK_PREDICTION_DEFAULT
;
204 const bool pref_found
= browser_pref
->GetAsInteger(&int_value
);
205 DCHECK(pref_found
) << "Preference not found.";
206 return new base::FundamentalValue(
207 int_value
!= chrome_browser_net::NETWORK_PREDICTION_NEVER
);
213 static PrefMapping
* GetInstance() {
214 return Singleton
<PrefMapping
>::get();
217 bool FindBrowserPrefForExtensionPref(const std::string
& extension_pref
,
218 std::string
* browser_pref
,
219 APIPermission::ID
* read_permission
,
220 APIPermission::ID
* write_permission
) {
221 PrefMap::iterator it
= mapping_
.find(extension_pref
);
222 if (it
!= mapping_
.end()) {
223 *browser_pref
= it
->second
.pref_name
;
224 *read_permission
= it
->second
.read_permission
;
225 *write_permission
= it
->second
.write_permission
;
231 bool FindEventForBrowserPref(const std::string
& browser_pref
,
232 std::string
* event_name
,
233 APIPermission::ID
* permission
) {
234 PrefMap::iterator it
= event_mapping_
.find(browser_pref
);
235 if (it
!= event_mapping_
.end()) {
236 *event_name
= it
->second
.pref_name
;
237 *permission
= it
->second
.read_permission
;
243 PrefTransformerInterface
* FindTransformerForBrowserPref(
244 const std::string
& browser_pref
) {
245 std::map
<std::string
, PrefTransformerInterface
*>::iterator it
=
246 transformers_
.find(browser_pref
);
247 if (it
!= transformers_
.end())
250 return identity_transformer_
.get();
254 friend struct DefaultSingletonTraits
<PrefMapping
>;
257 identity_transformer_
.reset(new IdentityPrefTransformer());
258 for (size_t i
= 0; i
< arraysize(kPrefMapping
); ++i
) {
259 mapping_
[kPrefMapping
[i
].extension_pref
] =
260 PrefMapData(kPrefMapping
[i
].browser_pref
,
261 kPrefMapping
[i
].read_permission
,
262 kPrefMapping
[i
].write_permission
);
263 std::string event_name
=
264 base::StringPrintf(kOnPrefChangeFormat
,
265 kPrefMapping
[i
].extension_pref
);
266 event_mapping_
[kPrefMapping
[i
].browser_pref
] =
267 PrefMapData(event_name
,
268 kPrefMapping
[i
].read_permission
,
269 kPrefMapping
[i
].write_permission
);
271 DCHECK_EQ(arraysize(kPrefMapping
), mapping_
.size());
272 DCHECK_EQ(arraysize(kPrefMapping
), event_mapping_
.size());
273 RegisterPrefTransformer(prefs::kProxy
, new ProxyPrefTransformer());
274 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies
,
275 new InvertBooleanTransformer());
276 RegisterPrefTransformer(prefs::kNetworkPredictionOptions
,
277 new NetworkPredictionTransformer());
281 STLDeleteContainerPairSecondPointers(transformers_
.begin(),
282 transformers_
.end());
285 void RegisterPrefTransformer(const std::string
& browser_pref
,
286 PrefTransformerInterface
* transformer
) {
287 DCHECK_EQ(0u, transformers_
.count(browser_pref
)) <<
288 "Trying to register pref transformer for " << browser_pref
<< " twice";
289 transformers_
[browser_pref
] = transformer
;
294 : read_permission(APIPermission::kInvalid
),
295 write_permission(APIPermission::kInvalid
) {}
297 PrefMapData(const std::string
& pref_name
,
298 APIPermission::ID read
,
299 APIPermission::ID write
)
300 : pref_name(pref_name
),
301 read_permission(read
),
302 write_permission(write
) {}
304 // Browser or extension preference to which the data maps.
305 std::string pref_name
;
307 // Permission needed to read the preference.
308 APIPermission::ID read_permission
;
310 // Permission needed to write the preference.
311 APIPermission::ID write_permission
;
314 typedef std::map
<std::string
, PrefMapData
> PrefMap
;
316 // Mapping from extension pref keys to browser pref keys and permissions.
319 // Mapping from browser pref keys to extension event names and permissions.
320 PrefMap event_mapping_
;
322 // Mapping from browser pref keys to transformers.
323 std::map
<std::string
, PrefTransformerInterface
*> transformers_
;
325 scoped_ptr
<PrefTransformerInterface
> identity_transformer_
;
327 DISALLOW_COPY_AND_ASSIGN(PrefMapping
);
332 PreferenceEventRouter::PreferenceEventRouter(Profile
* profile
)
333 : profile_(profile
) {
334 registrar_
.Init(profile_
->GetPrefs());
335 incognito_registrar_
.Init(profile_
->GetOffTheRecordPrefs());
336 for (size_t i
= 0; i
< arraysize(kPrefMapping
); ++i
) {
337 registrar_
.Add(kPrefMapping
[i
].browser_pref
,
338 base::Bind(&PreferenceEventRouter::OnPrefChanged
,
339 base::Unretained(this),
340 registrar_
.prefs()));
341 incognito_registrar_
.Add(kPrefMapping
[i
].browser_pref
,
342 base::Bind(&PreferenceEventRouter::OnPrefChanged
,
343 base::Unretained(this),
344 incognito_registrar_
.prefs()));
348 PreferenceEventRouter::~PreferenceEventRouter() { }
350 void PreferenceEventRouter::OnPrefChanged(PrefService
* pref_service
,
351 const std::string
& browser_pref
) {
352 bool incognito
= (pref_service
!= profile_
->GetPrefs());
354 std::string event_name
;
355 APIPermission::ID permission
= APIPermission::kInvalid
;
356 bool rv
= PrefMapping::GetInstance()->FindEventForBrowserPref(
357 browser_pref
, &event_name
, &permission
);
360 base::ListValue args
;
361 base::DictionaryValue
* dict
= new base::DictionaryValue();
363 const PrefService::Preference
* pref
=
364 pref_service
->FindPreference(browser_pref
.c_str());
366 PrefTransformerInterface
* transformer
=
367 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref
);
368 base::Value
* transformed_value
=
369 transformer
->BrowserToExtensionPref(pref
->GetValue());
370 if (!transformed_value
) {
371 LOG(ERROR
) << ErrorUtils::FormatErrorMessage(kConversionErrorMessage
,
376 dict
->Set(keys::kValue
, transformed_value
);
378 ExtensionPrefs
* ep
= ExtensionPrefs::Get(profile_
);
379 dict
->SetBoolean(keys::kIncognitoSpecific
,
380 ep
->HasIncognitoPrefValue(browser_pref
));
383 // TODO(kalman): Have a histogram value for each pref type.
384 // This isn't so important for the current use case of these
385 // histograms, which is to track which event types are waking up event
386 // pages, or which are delivered to persistent background pages. Simply
387 // "a setting changed" is enough detail for that. However if we try to
388 // use these histograms for any fine-grained logic (like removing the
389 // string event name altogether), or if we discover this event is
390 // firing a lot and want to understand that better, then this will need
392 events::HistogramValue histogram_value
=
393 events::TYPES_CHROME_SETTING_ON_CHANGE
;
394 helpers::DispatchEventToExtensions(profile_
, histogram_value
, event_name
,
395 &args
, permission
, incognito
,
399 void PreferenceAPIBase::SetExtensionControlledPref(
400 const std::string
& extension_id
,
401 const std::string
& pref_key
,
402 ExtensionPrefsScope scope
,
403 base::Value
* value
) {
405 const PrefService::Preference
* pref
=
406 extension_prefs()->pref_service()->FindPreference(pref_key
.c_str());
407 DCHECK(pref
) << "Extension controlled preference key " << pref_key
408 << " not registered.";
409 DCHECK_EQ(pref
->GetType(), value
->GetType())
410 << "Extension controlled preference " << pref_key
<< " has wrong type.";
413 std::string scope_string
;
414 // ScopeToPrefName() returns false if the scope is not persisted.
415 if (pref_names::ScopeToPrefName(scope
, &scope_string
)) {
416 // Also store in persisted Preferences file to recover after a
418 ExtensionPrefs::ScopedDictionaryUpdate
update(extension_prefs(),
421 base::DictionaryValue
* preference
= update
.Get();
423 preference
= update
.Create();
424 preference
->SetWithoutPathExpansion(pref_key
, value
->DeepCopy());
426 extension_pref_value_map()->SetExtensionPref(
427 extension_id
, pref_key
, scope
, value
);
430 void PreferenceAPIBase::RemoveExtensionControlledPref(
431 const std::string
& extension_id
,
432 const std::string
& pref_key
,
433 ExtensionPrefsScope scope
) {
434 DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key
.c_str()))
435 << "Extension controlled preference key " << pref_key
436 << " not registered.";
438 std::string scope_string
;
439 if (pref_names::ScopeToPrefName(scope
, &scope_string
)) {
440 ExtensionPrefs::ScopedDictionaryUpdate
update(extension_prefs(),
443 base::DictionaryValue
* preference
= update
.Get();
445 preference
->RemoveWithoutPathExpansion(pref_key
, NULL
);
447 extension_pref_value_map()->RemoveExtensionPref(
448 extension_id
, pref_key
, scope
);
451 bool PreferenceAPIBase::CanExtensionControlPref(
452 const std::string
& extension_id
,
453 const std::string
& pref_key
,
455 DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key
.c_str()))
456 << "Extension controlled preference key " << pref_key
457 << " not registered.";
459 return extension_pref_value_map()->CanExtensionControlPref(
460 extension_id
, pref_key
, incognito
);
463 bool PreferenceAPIBase::DoesExtensionControlPref(
464 const std::string
& extension_id
,
465 const std::string
& pref_key
,
466 bool* from_incognito
) {
467 DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key
.c_str()))
468 << "Extension controlled preference key " << pref_key
469 << " not registered.";
471 return extension_pref_value_map()->DoesExtensionControlPref(
472 extension_id
, pref_key
, from_incognito
);
475 PreferenceAPI::PreferenceAPI(content::BrowserContext
* context
)
476 : profile_(Profile::FromBrowserContext(context
)) {
477 for (size_t i
= 0; i
< arraysize(kPrefMapping
); ++i
) {
478 std::string event_name
;
479 APIPermission::ID permission
= APIPermission::kInvalid
;
480 bool rv
= PrefMapping::GetInstance()->FindEventForBrowserPref(
481 kPrefMapping
[i
].browser_pref
, &event_name
, &permission
);
483 EventRouter::Get(profile_
)->RegisterObserver(this, event_name
);
485 content_settings_store()->AddObserver(this);
488 PreferenceAPI::~PreferenceAPI() {
491 void PreferenceAPI::Shutdown() {
492 EventRouter::Get(profile_
)->UnregisterObserver(this);
493 if (!extension_prefs()->extensions_disabled())
494 ClearIncognitoSessionOnlyContentSettings();
495 content_settings_store()->RemoveObserver(this);
498 static base::LazyInstance
<BrowserContextKeyedAPIFactory
<PreferenceAPI
> >
499 g_factory
= LAZY_INSTANCE_INITIALIZER
;
502 BrowserContextKeyedAPIFactory
<PreferenceAPI
>*
503 PreferenceAPI::GetFactoryInstance() {
504 return g_factory
.Pointer();
508 PreferenceAPI
* PreferenceAPI::Get(content::BrowserContext
* context
) {
509 return BrowserContextKeyedAPIFactory
<PreferenceAPI
>::Get(context
);
512 void PreferenceAPI::OnListenerAdded(const EventListenerInfo
& details
) {
513 preference_event_router_
.reset(new PreferenceEventRouter(profile_
));
514 EventRouter::Get(profile_
)->UnregisterObserver(this);
517 void PreferenceAPI::OnContentSettingChanged(const std::string
& extension_id
,
520 extension_prefs()->UpdateExtensionPref(
522 pref_names::kPrefIncognitoContentSettings
,
523 content_settings_store()->GetSettingsForExtension(
524 extension_id
, kExtensionPrefsScopeIncognitoPersistent
));
526 extension_prefs()->UpdateExtensionPref(
528 pref_names::kPrefContentSettings
,
529 content_settings_store()->GetSettingsForExtension(
530 extension_id
, kExtensionPrefsScopeRegular
));
534 void PreferenceAPI::ClearIncognitoSessionOnlyContentSettings() {
535 ExtensionIdList extension_ids
;
536 extension_prefs()->GetExtensions(&extension_ids
);
537 for (ExtensionIdList::iterator extension_id
= extension_ids
.begin();
538 extension_id
!= extension_ids
.end(); ++extension_id
) {
539 content_settings_store()->ClearContentSettingsForExtension(
540 *extension_id
, kExtensionPrefsScopeIncognitoSessionOnly
);
544 ExtensionPrefs
* PreferenceAPI::extension_prefs() {
545 return ExtensionPrefs::Get(profile_
);
548 ExtensionPrefValueMap
* PreferenceAPI::extension_pref_value_map() {
549 return ExtensionPrefValueMapFactory::GetForBrowserContext(profile_
);
552 scoped_refptr
<ContentSettingsStore
> PreferenceAPI::content_settings_store() {
553 return ContentSettingsService::Get(profile_
)->content_settings_store();
558 BrowserContextKeyedAPIFactory
<PreferenceAPI
>::DeclareFactoryDependencies() {
559 DependsOn(ContentSettingsService::GetFactoryInstance());
560 DependsOn(ExtensionPrefsFactory::GetInstance());
561 DependsOn(ExtensionPrefValueMapFactory::GetInstance());
562 DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
565 PreferenceFunction::~PreferenceFunction() { }
567 bool PreferenceFunction::ValidateBrowserPref(
568 const std::string
& extension_pref_key
,
569 PreferenceFunction::PermissionType permission_type
,
570 std::string
* browser_pref_key
) {
571 APIPermission::ID read_permission
= APIPermission::kInvalid
;
572 APIPermission::ID write_permission
= APIPermission::kInvalid
;
573 EXTENSION_FUNCTION_VALIDATE(
574 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
579 APIPermission::ID permission
= permission_type
== PERMISSION_TYPE_READ
582 if (!extension()->permissions_data()->HasAPIPermission(permission
)) {
583 error_
= ErrorUtils::FormatErrorMessage(
584 keys::kPermissionErrorMessage
, extension_pref_key
);
590 GetPreferenceFunction::~GetPreferenceFunction() { }
592 bool GetPreferenceFunction::RunSync() {
593 std::string pref_key
;
594 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(0, &pref_key
));
595 base::DictionaryValue
* details
= NULL
;
596 EXTENSION_FUNCTION_VALIDATE(args_
->GetDictionary(1, &details
));
598 bool incognito
= false;
599 if (details
->HasKey(keys::kIncognitoKey
))
600 EXTENSION_FUNCTION_VALIDATE(details
->GetBoolean(keys::kIncognitoKey
,
603 // Check incognito access.
604 if (incognito
&& !include_incognito()) {
605 error_
= keys::kIncognitoErrorMessage
;
610 std::string browser_pref
;
611 if (!ValidateBrowserPref(
612 pref_key
, PreferenceFunction::PERMISSION_TYPE_READ
, &browser_pref
)) {
615 PrefService
* prefs
= incognito
? GetProfile()->GetOffTheRecordPrefs()
616 : GetProfile()->GetPrefs();
617 const PrefService::Preference
* pref
=
618 prefs
->FindPreference(browser_pref
.c_str());
621 scoped_ptr
<base::DictionaryValue
> result(new base::DictionaryValue
);
623 // Retrieve level of control.
624 std::string level_of_control
= helpers::GetLevelOfControl(
625 GetProfile(), extension_id(), browser_pref
, incognito
);
626 result
->SetString(keys::kLevelOfControl
, level_of_control
);
628 // Retrieve pref value.
629 PrefTransformerInterface
* transformer
=
630 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref
);
631 base::Value
* transformed_value
=
632 transformer
->BrowserToExtensionPref(pref
->GetValue());
633 if (!transformed_value
) {
635 ErrorUtils::FormatErrorMessage(kConversionErrorMessage
,
639 result
->Set(keys::kValue
, transformed_value
);
641 // Retrieve incognito status.
643 ExtensionPrefs
* ep
= ExtensionPrefs::Get(GetProfile());
644 result
->SetBoolean(keys::kIncognitoSpecific
,
645 ep
->HasIncognitoPrefValue(browser_pref
));
648 SetResult(result
.release());
652 SetPreferenceFunction::~SetPreferenceFunction() { }
654 bool SetPreferenceFunction::RunSync() {
655 std::string pref_key
;
656 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(0, &pref_key
));
657 base::DictionaryValue
* details
= NULL
;
658 EXTENSION_FUNCTION_VALIDATE(args_
->GetDictionary(1, &details
));
660 base::Value
* value
= NULL
;
661 EXTENSION_FUNCTION_VALIDATE(details
->Get(keys::kValue
, &value
));
663 ExtensionPrefsScope scope
= kExtensionPrefsScopeRegular
;
664 if (details
->HasKey(keys::kScopeKey
)) {
665 std::string scope_str
;
666 EXTENSION_FUNCTION_VALIDATE(
667 details
->GetString(keys::kScopeKey
, &scope_str
));
669 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str
, &scope
));
672 // Check incognito scope.
674 (scope
== kExtensionPrefsScopeIncognitoPersistent
||
675 scope
== kExtensionPrefsScopeIncognitoSessionOnly
);
677 // Regular profiles can't access incognito unless include_incognito is true.
678 if (!GetProfile()->IsOffTheRecord() && !include_incognito()) {
679 error_
= keys::kIncognitoErrorMessage
;
683 // Incognito profiles can't access regular mode ever, they only exist in
685 if (GetProfile()->IsOffTheRecord()) {
686 error_
= "Can't modify regular settings from an incognito context.";
691 if (scope
== kExtensionPrefsScopeIncognitoSessionOnly
&&
692 !GetProfile()->HasOffTheRecordProfile()) {
693 error_
= keys::kIncognitoSessionOnlyErrorMessage
;
698 std::string browser_pref
;
699 if (!ValidateBrowserPref(
700 pref_key
, PreferenceFunction::PERMISSION_TYPE_WRITE
, &browser_pref
)) {
703 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(GetProfile());
704 const PrefService::Preference
* pref
=
705 prefs
->pref_service()->FindPreference(browser_pref
.c_str());
708 // Validate new value.
709 PrefTransformerInterface
* transformer
=
710 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref
);
712 bool bad_message
= false;
713 scoped_ptr
<base::Value
> browser_pref_value(
714 transformer
->ExtensionToBrowserPref(value
, &error
, &bad_message
));
715 if (!browser_pref_value
) {
717 bad_message_
= bad_message
;
720 EXTENSION_FUNCTION_VALIDATE(browser_pref_value
->GetType() == pref
->GetType());
722 // Validate also that the stored value can be converted back by the
724 scoped_ptr
<base::Value
> extensionPrefValue(
725 transformer
->BrowserToExtensionPref(browser_pref_value
.get()));
726 if (!extensionPrefValue
) {
727 error_
= ErrorUtils::FormatErrorMessage(kConversionErrorMessage
,
733 PreferenceAPI::Get(GetProfile())->SetExtensionControlledPref(
734 extension_id(), browser_pref
, scope
, browser_pref_value
.release());
738 ClearPreferenceFunction::~ClearPreferenceFunction() { }
740 bool ClearPreferenceFunction::RunSync() {
741 std::string pref_key
;
742 EXTENSION_FUNCTION_VALIDATE(args_
->GetString(0, &pref_key
));
743 base::DictionaryValue
* details
= NULL
;
744 EXTENSION_FUNCTION_VALIDATE(args_
->GetDictionary(1, &details
));
746 ExtensionPrefsScope scope
= kExtensionPrefsScopeRegular
;
747 if (details
->HasKey(keys::kScopeKey
)) {
748 std::string scope_str
;
749 EXTENSION_FUNCTION_VALIDATE(
750 details
->GetString(keys::kScopeKey
, &scope_str
));
752 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str
, &scope
));
755 // Check incognito scope.
757 (scope
== kExtensionPrefsScopeIncognitoPersistent
||
758 scope
== kExtensionPrefsScopeIncognitoSessionOnly
);
760 // We don't check incognito permissions here, as an extension should be
761 // always allowed to clear its own settings.
763 // Incognito profiles can't access regular mode ever, they only exist in
765 if (GetProfile()->IsOffTheRecord()) {
766 error_
= "Can't modify regular settings from an incognito context.";
771 std::string browser_pref
;
772 if (!ValidateBrowserPref(
773 pref_key
, PreferenceFunction::PERMISSION_TYPE_WRITE
, &browser_pref
)) {
777 PreferenceAPI::Get(GetProfile())
778 ->RemoveExtensionControlledPref(extension_id(), browser_pref
, scope
);
782 } // namespace extensions