blob: 463e5ad798e65be3aef92ef5af25f556a6bc7fb7 [file] [log] [blame]
[email protected]607e6522012-01-25 08:14:521// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]598bbcc2011-02-24 10:03:252// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]135e4782012-09-19 20:36:525#include "chrome/browser/extensions/api/preference/preference_api.h"
[email protected]598bbcc2011-02-24 10:03:256
[email protected]3e3342692011-03-15 12:03:277#include <map>
[email protected]8e7b2cf42012-04-18 14:26:588#include <utility>
[email protected]3e3342692011-03-15 12:03:279
[email protected]c39df1a2013-01-08 18:22:0710#include "base/lazy_instance.h"
[email protected]3b63f8f42011-03-28 01:54:1511#include "base/memory/singleton.h"
[email protected]3853a4c2013-02-11 17:15:5712#include "base/prefs/pref_service.h"
[email protected]7286e3fc2011-07-19 22:13:2413#include "base/stl_util.h"
[email protected]598bbcc2011-02-24 10:03:2514#include "base/stringprintf.h"
15#include "base/values.h"
[email protected]135e4782012-09-19 20:36:5216#include "chrome/browser/extensions/api/preference/preference_api_constants.h"
17#include "chrome/browser/extensions/api/preference/preference_helpers.h"
[email protected]c454fe672012-03-12 21:18:0118#include "chrome/browser/extensions/api/proxy/proxy_api.h"
[email protected]598bbcc2011-02-24 10:03:2519#include "chrome/browser/extensions/extension_prefs.h"
[email protected]9783c162011-05-25 21:45:5120#include "chrome/browser/extensions/extension_prefs_scope.h"
[email protected]598bbcc2011-02-24 10:03:2521#include "chrome/browser/extensions/extension_service.h"
[email protected]06bdd2b2012-11-30 18:47:1322#include "chrome/browser/extensions/extension_system.h"
[email protected]598bbcc2011-02-24 10:03:2523#include "chrome/browser/profiles/profile.h"
[email protected]432115822011-07-10 15:52:2724#include "chrome/common/chrome_notification_types.h"
[email protected]c2e66e12012-06-27 06:27:0625#include "chrome/common/extensions/permissions/api_permission.h"
[email protected]598bbcc2011-02-24 10:03:2526#include "chrome/common/pref_names.h"
[email protected]ad50def52011-10-19 23:17:0727#include "content/public/browser/notification_details.h"
28#include "content/public/browser/notification_source.h"
[email protected]e9f541a2012-11-19 21:52:3129#include "extensions/common/error_utils.h"
[email protected]598bbcc2011-02-24 10:03:2530
[email protected]135e4782012-09-19 20:36:5231namespace keys = extensions::preference_api_constants;
32namespace helpers = extensions::preference_helpers;
[email protected]dcac1fec2012-03-06 21:00:4933
[email protected]135e4782012-09-19 20:36:5234namespace extensions {
[email protected]c2e66e12012-06-27 06:27:0635
[email protected]598bbcc2011-02-24 10:03:2536namespace {
37
38struct PrefMappingEntry {
[email protected]80f95f512011-12-19 00:51:0439 // Name of the preference referenced by the extension API JSON.
[email protected]598bbcc2011-02-24 10:03:2540 const char* extension_pref;
[email protected]a4f98922011-12-06 11:32:2341
42 // Name of the preference in the PrefStores.
[email protected]598bbcc2011-02-24 10:03:2543 const char* browser_pref;
[email protected]a4f98922011-12-06 11:32:2344
45 // Permission required to access this preference.
[email protected]c2e66e12012-06-27 06:27:0646 // Use APIPermission::kInvalid for |permission| to express that no
[email protected]a4f98922011-12-06 11:32:2347 // permission is necessary.
[email protected]c2e66e12012-06-27 06:27:0648 APIPermission::ID permission;
[email protected]598bbcc2011-02-24 10:03:2549};
50
[email protected]023208cf2011-06-02 23:56:4151const char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange";
[email protected]ca2bbaf2012-10-22 10:36:2152const char kConversionErrorMessage[] =
53 "Internal error: Stored value for preference '*' cannot be converted "
54 "properly.";
[email protected]118de7892011-03-16 13:31:4055
[email protected]3e3342692011-03-15 12:03:2756PrefMappingEntry kPrefMapping[] = {
[email protected]cc3a5c82012-05-09 16:54:5757#if defined(OS_CHROMEOS)
58 { "protectedContentEnabled",
59 prefs::kEnableCrosDRM,
[email protected]c2e66e12012-06-27 06:27:0660 APIPermission::kPrivacy
[email protected]cc3a5c82012-05-09 16:54:5761 },
62#endif // defined(OS_CHROMEOS)
[email protected]fbc660102011-08-26 05:41:2163 { "alternateErrorPagesEnabled",
64 prefs::kAlternateErrorPagesEnabled,
[email protected]c2e66e12012-06-27 06:27:0665 APIPermission::kPrivacy
[email protected]598bbcc2011-02-24 10:03:2566 },
[email protected]fbc660102011-08-26 05:41:2167 { "autofillEnabled",
68 prefs::kAutofillEnabled,
[email protected]c2e66e12012-06-27 06:27:0669 APIPermission::kPrivacy
[email protected]0a8db0d2011-04-13 15:15:4070 },
[email protected]c9471ea2011-06-02 18:09:0771 { "hyperlinkAuditingEnabled",
[email protected]0a8db0d2011-04-13 15:15:4072 prefs::kEnableHyperlinkAuditing,
[email protected]c2e66e12012-06-27 06:27:0673 APIPermission::kPrivacy
[email protected]fbc660102011-08-26 05:41:2174 },
75 { "instantEnabled",
76 prefs::kInstantEnabled,
[email protected]c2e66e12012-06-27 06:27:0677 APIPermission::kPrivacy
[email protected]fbc660102011-08-26 05:41:2178 },
[email protected]dcac1fec2012-03-06 21:00:4979 { "managedModeEnabled",
80 prefs::kInManagedMode,
[email protected]c2e66e12012-06-27 06:27:0681 APIPermission::kManagedModePrivate
[email protected]dcac1fec2012-03-06 21:00:4982 },
[email protected]fbc660102011-08-26 05:41:2183 { "networkPredictionEnabled",
84 prefs::kNetworkPredictionEnabled,
[email protected]c2e66e12012-06-27 06:27:0685 APIPermission::kPrivacy
[email protected]0a8db0d2011-04-13 15:15:4086 },
[email protected]ccfdfbdf2011-02-24 12:41:4687 { "proxy",
88 prefs::kProxy,
[email protected]c2e66e12012-06-27 06:27:0689 APIPermission::kProxy
[email protected]ccfdfbdf2011-02-24 12:41:4690 },
[email protected]fbc660102011-08-26 05:41:2191 { "referrersEnabled",
92 prefs::kEnableReferrers,
[email protected]c2e66e12012-06-27 06:27:0693 APIPermission::kPrivacy
[email protected]fbc660102011-08-26 05:41:2194 },
[email protected]75fc2592012-04-05 13:00:3395 { "safeBrowsingEnabled",
96 prefs::kSafeBrowsingEnabled,
[email protected]c2e66e12012-06-27 06:27:0697 APIPermission::kPrivacy
[email protected]75fc2592012-04-05 13:00:3398 },
[email protected]fbc660102011-08-26 05:41:2199 { "searchSuggestEnabled",
100 prefs::kSearchSuggestEnabled,
[email protected]c2e66e12012-06-27 06:27:06101 APIPermission::kPrivacy
[email protected]fbc660102011-08-26 05:41:21102 },
[email protected]75fc2592012-04-05 13:00:33103 { "spellingServiceEnabled",
104 prefs::kSpellCheckUseSpellingService,
[email protected]c2e66e12012-06-27 06:27:06105 APIPermission::kPrivacy
[email protected]fbc660102011-08-26 05:41:21106 },
107 { "thirdPartyCookiesAllowed",
108 prefs::kBlockThirdPartyCookies,
[email protected]c2e66e12012-06-27 06:27:06109 APIPermission::kPrivacy
[email protected]fbc660102011-08-26 05:41:21110 },
111 { "translationServiceEnabled",
112 prefs::kEnableTranslate,
[email protected]c2e66e12012-06-27 06:27:06113 APIPermission::kPrivacy
[email protected]fbc660102011-08-26 05:41:21114 }
[email protected]598bbcc2011-02-24 10:03:25115};
116
[email protected]3e3342692011-03-15 12:03:27117class IdentityPrefTransformer : public PrefTransformerInterface {
118 public:
[email protected]3e3342692011-03-15 12:03:27119 virtual Value* ExtensionToBrowserPref(const Value* extension_pref,
[email protected]ca943e72011-05-03 16:58:04120 std::string* error,
[email protected]49aeab62013-02-07 02:53:11121 bool* bad_message) OVERRIDE {
[email protected]3e3342692011-03-15 12:03:27122 return extension_pref->DeepCopy();
123 }
124
[email protected]49aeab62013-02-07 02:53:11125 virtual Value* BrowserToExtensionPref(const Value* browser_pref) OVERRIDE {
[email protected]3e3342692011-03-15 12:03:27126 return browser_pref->DeepCopy();
127 }
128};
129
[email protected]c9471ea2011-06-02 18:09:07130class InvertBooleanTransformer : public PrefTransformerInterface {
131 public:
132 virtual Value* ExtensionToBrowserPref(const Value* extension_pref,
133 std::string* error,
[email protected]49aeab62013-02-07 02:53:11134 bool* bad_message) OVERRIDE {
[email protected]c9471ea2011-06-02 18:09:07135 return InvertBooleanValue(extension_pref);
136 }
137
[email protected]49aeab62013-02-07 02:53:11138 virtual Value* BrowserToExtensionPref(const Value* browser_pref) OVERRIDE {
[email protected]c9471ea2011-06-02 18:09:07139 return InvertBooleanValue(browser_pref);
140 }
141
142 private:
143 static Value* InvertBooleanValue(const Value* value) {
144 bool bool_value = false;
145 bool result = value->GetAsBoolean(&bool_value);
146 DCHECK(result);
147 return Value::CreateBooleanValue(!bool_value);
148 }
149};
150
[email protected]598bbcc2011-02-24 10:03:25151class PrefMapping {
152 public:
153 static PrefMapping* GetInstance() {
154 return Singleton<PrefMapping>::get();
155 }
156
157 bool FindBrowserPrefForExtensionPref(const std::string& extension_pref,
158 std::string* browser_pref,
[email protected]c2e66e12012-06-27 06:27:06159 APIPermission::ID* permission) {
[email protected]0d3e4a22011-06-23 19:02:52160 PrefMap::iterator it = mapping_.find(extension_pref);
[email protected]598bbcc2011-02-24 10:03:25161 if (it != mapping_.end()) {
162 *browser_pref = it->second.first;
163 *permission = it->second.second;
164 return true;
165 }
166 return false;
167 }
168
[email protected]118de7892011-03-16 13:31:40169 bool FindEventForBrowserPref(const std::string& browser_pref,
170 std::string* event_name,
[email protected]c2e66e12012-06-27 06:27:06171 APIPermission::ID* permission) {
[email protected]0d3e4a22011-06-23 19:02:52172 PrefMap::iterator it = event_mapping_.find(browser_pref);
[email protected]118de7892011-03-16 13:31:40173 if (it != event_mapping_.end()) {
174 *event_name = it->second.first;
175 *permission = it->second.second;
176 return true;
177 }
178 return false;
179 }
180
[email protected]3e3342692011-03-15 12:03:27181 PrefTransformerInterface* FindTransformerForBrowserPref(
182 const std::string& browser_pref) {
183 std::map<std::string, PrefTransformerInterface*>::iterator it =
184 transformers_.find(browser_pref);
185 if (it != transformers_.end())
186 return it->second;
187 else
188 return identity_transformer_.get();
189 }
190
[email protected]598bbcc2011-02-24 10:03:25191 private:
192 friend struct DefaultSingletonTraits<PrefMapping>;
193
[email protected]3e3342692011-03-15 12:03:27194 PrefMapping() {
195 identity_transformer_.reset(new IdentityPrefTransformer());
196 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
197 mapping_[kPrefMapping[i].extension_pref] =
198 std::make_pair(kPrefMapping[i].browser_pref,
199 kPrefMapping[i].permission);
[email protected]118de7892011-03-16 13:31:40200 std::string event_name =
201 base::StringPrintf(kOnPrefChangeFormat,
202 kPrefMapping[i].extension_pref);
203 event_mapping_[kPrefMapping[i].browser_pref] =
204 std::make_pair(event_name, kPrefMapping[i].permission);
[email protected]3e3342692011-03-15 12:03:27205 }
206 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size());
[email protected]118de7892011-03-16 13:31:40207 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size());
[email protected]da01ca52012-12-12 22:42:55208 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer());
[email protected]c9471ea2011-06-02 18:09:07209 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies,
210 new InvertBooleanTransformer());
[email protected]3e3342692011-03-15 12:03:27211 }
212
213 ~PrefMapping() {
214 STLDeleteContainerPairSecondPointers(transformers_.begin(),
215 transformers_.end());
216 }
217
218 void RegisterPrefTransformer(const std::string& browser_pref,
219 PrefTransformerInterface* transformer) {
220 DCHECK_EQ(0u, transformers_.count(browser_pref)) <<
221 "Trying to register pref transformer for " << browser_pref << " twice";
222 transformers_[browser_pref] = transformer;
223 }
224
[email protected]0d3e4a22011-06-23 19:02:52225 typedef std::map<std::string,
[email protected]c2e66e12012-06-27 06:27:06226 std::pair<std::string, APIPermission::ID> >
[email protected]0d3e4a22011-06-23 19:02:52227 PrefMap;
228
[email protected]118de7892011-03-16 13:31:40229 // Mapping from extension pref keys to browser pref keys and permissions.
[email protected]0d3e4a22011-06-23 19:02:52230 PrefMap mapping_;
[email protected]598bbcc2011-02-24 10:03:25231
[email protected]118de7892011-03-16 13:31:40232 // Mapping from browser pref keys to extension event names and permissions.
[email protected]0d3e4a22011-06-23 19:02:52233 PrefMap event_mapping_;
[email protected]598bbcc2011-02-24 10:03:25234
[email protected]3e3342692011-03-15 12:03:27235 // Mapping from browser pref keys to transformers.
236 std::map<std::string, PrefTransformerInterface*> transformers_;
237
238 scoped_ptr<PrefTransformerInterface> identity_transformer_;
[email protected]118de7892011-03-16 13:31:40239
240 DISALLOW_COPY_AND_ASSIGN(PrefMapping);
[email protected]3e3342692011-03-15 12:03:27241};
[email protected]598bbcc2011-02-24 10:03:25242
243} // namespace
244
[email protected]135e4782012-09-19 20:36:52245PreferenceEventRouter::PreferenceEventRouter(Profile* profile)
246 : profile_(profile) {
[email protected]118de7892011-03-16 13:31:40247 registrar_.Init(profile_->GetPrefs());
248 incognito_registrar_.Init(profile_->GetOffTheRecordPrefs());
249 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
[email protected]90bb38d2012-11-14 18:36:03250 registrar_.Add(kPrefMapping[i].browser_pref,
251 base::Bind(&PreferenceEventRouter::OnPrefChanged,
252 base::Unretained(this),
253 registrar_.prefs()));
254 incognito_registrar_.Add(kPrefMapping[i].browser_pref,
255 base::Bind(&PreferenceEventRouter::OnPrefChanged,
256 base::Unretained(this),
257 incognito_registrar_.prefs()));
[email protected]118de7892011-03-16 13:31:40258 }
259}
260
[email protected]135e4782012-09-19 20:36:52261PreferenceEventRouter::~PreferenceEventRouter() { }
[email protected]7da9a8232011-05-27 21:07:11262
[email protected]a6a7ced2012-11-01 17:24:18263void PreferenceEventRouter::OnPrefChanged(PrefServiceBase* pref_service,
[email protected]135e4782012-09-19 20:36:52264 const std::string& browser_pref) {
[email protected]118de7892011-03-16 13:31:40265 bool incognito = (pref_service != profile_->GetPrefs());
266
267 std::string event_name;
[email protected]c2e66e12012-06-27 06:27:06268 APIPermission::ID permission = APIPermission::kInvalid;
[email protected]118de7892011-03-16 13:31:40269 bool rv = PrefMapping::GetInstance()->FindEventForBrowserPref(
270 browser_pref, &event_name, &permission);
271 DCHECK(rv);
272
273 ListValue args;
274 DictionaryValue* dict = new DictionaryValue();
275 args.Append(dict);
[email protected]a6a7ced2012-11-01 17:24:18276 const PrefServiceBase::Preference* pref =
[email protected]118de7892011-03-16 13:31:40277 pref_service->FindPreference(browser_pref.c_str());
278 CHECK(pref);
[email protected]06bdd2b2012-11-30 18:47:13279 ExtensionService* extension_service =
[email protected]da01ca52012-12-12 22:42:55280 ExtensionSystem::Get(profile_)->extension_service();
[email protected]118de7892011-03-16 13:31:40281 PrefTransformerInterface* transformer =
282 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
[email protected]ca2bbaf2012-10-22 10:36:21283 Value* transformed_value =
284 transformer->BrowserToExtensionPref(pref->GetValue());
285 if (!transformed_value) {
[email protected]da01ca52012-12-12 22:42:55286 LOG(ERROR) << ErrorUtils::FormatErrorMessage(kConversionErrorMessage,
287 pref->name());
[email protected]ca2bbaf2012-10-22 10:36:21288 return;
289 }
290
291 dict->Set(keys::kValue, transformed_value);
[email protected]118de7892011-03-16 13:31:40292 if (incognito) {
[email protected]da01ca52012-12-12 22:42:55293 ExtensionPrefs* ep = extension_service->extension_prefs();
[email protected]dcac1fec2012-03-06 21:00:49294 dict->SetBoolean(keys::kIncognitoSpecific,
[email protected]fa0624262011-06-09 14:17:38295 ep->HasIncognitoPrefValue(browser_pref));
[email protected]118de7892011-03-16 13:31:40296 }
297
[email protected]bdd34452012-04-16 15:58:40298 helpers::DispatchEventToExtensions(profile_,
299 event_name,
300 &args,
301 permission,
302 incognito,
303 browser_pref);
[email protected]118de7892011-03-16 13:31:40304}
305
[email protected]da01ca52012-12-12 22:42:55306PreferenceAPI::PreferenceAPI(Profile* profile) : profile_(profile) {
307 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
308 std::string event_name;
309 APIPermission::ID permission = APIPermission::kInvalid;
310 bool rv = PrefMapping::GetInstance()->FindEventForBrowserPref(
311 kPrefMapping[i].browser_pref, &event_name, &permission);
312 DCHECK(rv);
313 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
314 this, event_name);
315 }
316}
317
318PreferenceAPI::~PreferenceAPI() {
319}
320
321void PreferenceAPI::Shutdown() {
322 ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
323}
324
[email protected]c39df1a2013-01-08 18:22:07325static base::LazyInstance<ProfileKeyedAPIFactory<PreferenceAPI> >
326g_factory = LAZY_INSTANCE_INITIALIZER;
327
328// static
329ProfileKeyedAPIFactory<PreferenceAPI>* PreferenceAPI::GetFactoryInstance() {
330 return &g_factory.Get();
331}
332
[email protected]da01ca52012-12-12 22:42:55333void PreferenceAPI::OnListenerAdded(const EventListenerInfo& details) {
334 preference_event_router_.reset(new PreferenceEventRouter(profile_));
335 ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
336}
337
[email protected]dcac1fec2012-03-06 21:00:49338PreferenceFunction::~PreferenceFunction() { }
339
340bool PreferenceFunction::ValidateBrowserPref(
341 const std::string& extension_pref_key,
342 std::string* browser_pref_key) {
[email protected]c2e66e12012-06-27 06:27:06343 APIPermission::ID permission = APIPermission::kInvalid;
[email protected]dcac1fec2012-03-06 21:00:49344 EXTENSION_FUNCTION_VALIDATE(
345 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
346 extension_pref_key, browser_pref_key, &permission));
347 if (!GetExtension()->HasAPIPermission(permission)) {
[email protected]e9f541a2012-11-19 21:52:31348 error_ = ErrorUtils::FormatErrorMessage(
[email protected]dcac1fec2012-03-06 21:00:49349 keys::kPermissionErrorMessage, extension_pref_key);
350 return false;
351 }
352 return true;
353}
[email protected]c433bcb2011-02-24 13:10:27354
[email protected]598bbcc2011-02-24 10:03:25355GetPreferenceFunction::~GetPreferenceFunction() { }
356
357bool GetPreferenceFunction::RunImpl() {
358 std::string pref_key;
359 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
360 DictionaryValue* details = NULL;
361 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
362
363 bool incognito = false;
[email protected]fa0624262011-06-09 14:17:38364 if (details->HasKey(keys::kIncognitoKey))
365 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(keys::kIncognitoKey,
366 &incognito));
[email protected]c0793562011-03-09 15:31:03367
[email protected]dcac1fec2012-03-06 21:00:49368 // Check incognito access.
[email protected]c0793562011-03-09 15:31:03369 if (incognito && !include_incognito()) {
[email protected]fa0624262011-06-09 14:17:38370 error_ = keys::kIncognitoErrorMessage;
[email protected]c0793562011-03-09 15:31:03371 return false;
372 }
[email protected]598bbcc2011-02-24 10:03:25373
[email protected]dcac1fec2012-03-06 21:00:49374 // Obtain pref.
375 std::string browser_pref;
376 if (!ValidateBrowserPref(pref_key, &browser_pref))
377 return false;
[email protected]598bbcc2011-02-24 10:03:25378 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs()
379 : profile_->GetPrefs();
[email protected]598bbcc2011-02-24 10:03:25380 const PrefService::Preference* pref =
381 prefs->FindPreference(browser_pref.c_str());
382 CHECK(pref);
[email protected]9a28f132011-02-24 21:15:16383
384 scoped_ptr<DictionaryValue> result(new DictionaryValue);
[email protected]dcac1fec2012-03-06 21:00:49385
386 // Retrieve level of control.
387 std::string level_of_control =
[email protected]bdd34452012-04-16 15:58:40388 helpers::GetLevelOfControl(profile_, extension_id(), browser_pref,
389 incognito);
[email protected]dcac1fec2012-03-06 21:00:49390 result->SetString(keys::kLevelOfControl, level_of_control);
391
392 // Retrieve pref value.
[email protected]3e3342692011-03-15 12:03:27393 PrefTransformerInterface* transformer =
394 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
[email protected]ca2bbaf2012-10-22 10:36:21395 Value* transformed_value =
396 transformer->BrowserToExtensionPref(pref->GetValue());
397 if (!transformed_value) {
398 LOG(ERROR) <<
[email protected]e9f541a2012-11-19 21:52:31399 ErrorUtils::FormatErrorMessage(kConversionErrorMessage,
[email protected]ca2bbaf2012-10-22 10:36:21400 pref->name());
401 return false;
402 }
403 result->Set(keys::kValue, transformed_value);
[email protected]dcac1fec2012-03-06 21:00:49404
405 // Retrieve incognito status.
[email protected]c0793562011-03-09 15:31:03406 if (incognito) {
[email protected]da01ca52012-12-12 22:42:55407 ExtensionPrefs* ep =
408 ExtensionSystem::Get(profile_)->extension_service()->extension_prefs();
[email protected]dcac1fec2012-03-06 21:00:49409 result->SetBoolean(keys::kIncognitoSpecific,
[email protected]fa0624262011-06-09 14:17:38410 ep->HasIncognitoPrefValue(browser_pref));
[email protected]c0793562011-03-09 15:31:03411 }
[email protected]dcac1fec2012-03-06 21:00:49412
[email protected]07ff5fd2012-07-12 22:39:09413 SetResult(result.release());
[email protected]598bbcc2011-02-24 10:03:25414 return true;
415}
416
417SetPreferenceFunction::~SetPreferenceFunction() { }
418
419bool SetPreferenceFunction::RunImpl() {
420 std::string pref_key;
421 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
422 DictionaryValue* details = NULL;
423 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
424
425 Value* value = NULL;
[email protected]dcac1fec2012-03-06 21:00:49426 EXTENSION_FUNCTION_VALIDATE(details->Get(keys::kValue, &value));
[email protected]598bbcc2011-02-24 10:03:25427
[email protected]da01ca52012-12-12 22:42:55428 ExtensionPrefsScope scope = kExtensionPrefsScopeRegular;
[email protected]fa0624262011-06-09 14:17:38429 if (details->HasKey(keys::kScopeKey)) {
430 std::string scope_str;
431 EXTENSION_FUNCTION_VALIDATE(
432 details->GetString(keys::kScopeKey, &scope_str));
[email protected]8b001f32011-05-25 19:03:23433
[email protected]fa0624262011-06-09 14:17:38434 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope));
435 }
[email protected]c0793562011-03-09 15:31:03436
[email protected]dcac1fec2012-03-06 21:00:49437 // Check incognito scope.
[email protected]45759612012-07-10 17:21:23438 bool incognito =
[email protected]da01ca52012-12-12 22:42:55439 (scope == kExtensionPrefsScopeIncognitoPersistent ||
440 scope == kExtensionPrefsScopeIncognitoSessionOnly);
[email protected]9783c162011-05-25 21:45:51441 if (incognito) {
442 // Regular profiles can't access incognito unless include_incognito is true.
443 if (!profile()->IsOffTheRecord() && !include_incognito()) {
[email protected]fa0624262011-06-09 14:17:38444 error_ = keys::kIncognitoErrorMessage;
[email protected]9783c162011-05-25 21:45:51445 return false;
446 }
447 } else {
448 // Incognito profiles can't access regular mode ever, they only exist in
449 // split mode.
450 if (profile()->IsOffTheRecord()) {
451 error_ = "Can't modify regular settings from an incognito context.";
452 return false;
453 }
[email protected]c0793562011-03-09 15:31:03454 }
[email protected]598bbcc2011-02-24 10:03:25455
[email protected]da01ca52012-12-12 22:42:55456 if (scope == kExtensionPrefsScopeIncognitoSessionOnly &&
[email protected]31685742011-05-25 23:01:56457 !profile_->HasOffTheRecordProfile()) {
[email protected]fa0624262011-06-09 14:17:38458 error_ = keys::kIncognitoSessionOnlyErrorMessage;
[email protected]d20e8ce2011-05-25 23:54:25459 return false;
460 }
461
[email protected]dcac1fec2012-03-06 21:00:49462 // Obtain pref.
[email protected]598bbcc2011-02-24 10:03:25463 std::string browser_pref;
[email protected]dcac1fec2012-03-06 21:00:49464 if (!ValidateBrowserPref(pref_key, &browser_pref))
[email protected]598bbcc2011-02-24 10:03:25465 return false;
[email protected]da01ca52012-12-12 22:42:55466 ExtensionPrefs* prefs =
467 ExtensionSystem::Get(profile_)->extension_service()->extension_prefs();
[email protected]598bbcc2011-02-24 10:03:25468 const PrefService::Preference* pref =
469 prefs->pref_service()->FindPreference(browser_pref.c_str());
470 CHECK(pref);
[email protected]dcac1fec2012-03-06 21:00:49471
472 // Validate new value.
[email protected]598bbcc2011-02-24 10:03:25473 EXTENSION_FUNCTION_VALIDATE(value->GetType() == pref->GetType());
[email protected]3e3342692011-03-15 12:03:27474 PrefTransformerInterface* transformer =
475 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
476 std::string error;
[email protected]ca943e72011-05-03 16:58:04477 bool bad_message = false;
[email protected]ca2bbaf2012-10-22 10:36:21478 scoped_ptr<Value> browser_pref_value(
479 transformer->ExtensionToBrowserPref(value, &error, &bad_message));
480 if (!browser_pref_value) {
[email protected]3e3342692011-03-15 12:03:27481 error_ = error;
[email protected]ca943e72011-05-03 16:58:04482 bad_message_ = bad_message;
[email protected]3e3342692011-03-15 12:03:27483 return false;
484 }
[email protected]dcac1fec2012-03-06 21:00:49485
[email protected]ca2bbaf2012-10-22 10:36:21486 // Validate also that the stored value can be converted back by the
487 // transformer.
488 scoped_ptr<Value> extensionPrefValue(
489 transformer->BrowserToExtensionPref(browser_pref_value.get()));
490 if (!extensionPrefValue) {
[email protected]e9f541a2012-11-19 21:52:31491 error_ = ErrorUtils::FormatErrorMessage(kConversionErrorMessage,
[email protected]ca2bbaf2012-10-22 10:36:21492 pref->name());
493 bad_message_ = true;
494 return false;
495 }
496
[email protected]598bbcc2011-02-24 10:03:25497 prefs->SetExtensionControlledPref(extension_id(),
498 browser_pref,
[email protected]9783c162011-05-25 21:45:51499 scope,
[email protected]ca2bbaf2012-10-22 10:36:21500 browser_pref_value.release());
[email protected]598bbcc2011-02-24 10:03:25501 return true;
502}
[email protected]c433bcb2011-02-24 13:10:27503
504ClearPreferenceFunction::~ClearPreferenceFunction() { }
505
506bool ClearPreferenceFunction::RunImpl() {
507 std::string pref_key;
508 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
509 DictionaryValue* details = NULL;
510 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
511
[email protected]da01ca52012-12-12 22:42:55512 ExtensionPrefsScope scope = kExtensionPrefsScopeRegular;
[email protected]fa0624262011-06-09 14:17:38513 if (details->HasKey(keys::kScopeKey)) {
514 std::string scope_str;
515 EXTENSION_FUNCTION_VALIDATE(
516 details->GetString(keys::kScopeKey, &scope_str));
[email protected]8b001f32011-05-25 19:03:23517
[email protected]fa0624262011-06-09 14:17:38518 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope));
519 }
[email protected]c0793562011-03-09 15:31:03520
[email protected]dcac1fec2012-03-06 21:00:49521 // Check incognito scope.
[email protected]45759612012-07-10 17:21:23522 bool incognito =
[email protected]da01ca52012-12-12 22:42:55523 (scope == kExtensionPrefsScopeIncognitoPersistent ||
524 scope == kExtensionPrefsScopeIncognitoSessionOnly);
[email protected]9783c162011-05-25 21:45:51525 if (incognito) {
526 // We don't check incognito permissions here, as an extension should be
527 // always allowed to clear its own settings.
528 } else {
529 // Incognito profiles can't access regular mode ever, they only exist in
530 // split mode.
531 if (profile()->IsOffTheRecord()) {
532 error_ = "Can't modify regular settings from an incognito context.";
533 return false;
534 }
535 }
[email protected]c433bcb2011-02-24 13:10:27536
537 std::string browser_pref;
[email protected]dcac1fec2012-03-06 21:00:49538 if (!ValidateBrowserPref(pref_key, &browser_pref))
[email protected]c433bcb2011-02-24 13:10:27539 return false;
[email protected]dcac1fec2012-03-06 21:00:49540
[email protected]da01ca52012-12-12 22:42:55541 ExtensionPrefs* prefs =
542 ExtensionSystem::Get(profile_)->extension_service()->extension_prefs();
[email protected]9783c162011-05-25 21:45:51543 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, scope);
[email protected]c433bcb2011-02-24 13:10:27544 return true;
545}
[email protected]135e4782012-09-19 20:36:52546
547} // namespace extensions