blob: 871d99bcac5fca3cc678cfa9226c7510fe0f745a [file] [log] [blame]
[email protected]598bbcc2011-02-24 10:03:251// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/extension_preference_api.h"
6
[email protected]3e3342692011-03-15 12:03:277#include <map>
8
9#include "base/json/json_writer.h"
[email protected]3b63f8f42011-03-28 01:54:1510#include "base/memory/singleton.h"
[email protected]7286e3fc2011-07-19 22:13:2411#include "base/stl_util.h"
[email protected]598bbcc2011-02-24 10:03:2512#include "base/stringprintf.h"
13#include "base/values.h"
[email protected]118de7892011-03-16 13:31:4014#include "chrome/browser/extensions/extension_event_router.h"
[email protected]fa0624262011-06-09 14:17:3815#include "chrome/browser/extensions/extension_preference_api_constants.h"
16#include "chrome/browser/extensions/extension_preference_helpers.h"
[email protected]598bbcc2011-02-24 10:03:2517#include "chrome/browser/extensions/extension_prefs.h"
[email protected]9783c162011-05-25 21:45:5118#include "chrome/browser/extensions/extension_prefs_scope.h"
[email protected]3e3342692011-03-15 12:03:2719#include "chrome/browser/extensions/extension_proxy_api.h"
[email protected]598bbcc2011-02-24 10:03:2520#include "chrome/browser/extensions/extension_service.h"
21#include "chrome/browser/profiles/profile.h"
[email protected]432115822011-07-10 15:52:2722#include "chrome/common/chrome_notification_types.h"
[email protected]fa0624262011-06-09 14:17:3823#include "chrome/common/extensions/extension_error_utils.h"
[email protected]0d3e4a22011-06-23 19:02:5224#include "chrome/common/extensions/extension_permission_set.h"
[email protected]598bbcc2011-02-24 10:03:2525#include "chrome/common/pref_names.h"
[email protected]ad50def52011-10-19 23:17:0726#include "content/public/browser/notification_details.h"
27#include "content/public/browser/notification_source.h"
[email protected]598bbcc2011-02-24 10:03:2528
29namespace {
30
31struct PrefMappingEntry {
32 const char* extension_pref;
33 const char* browser_pref;
[email protected]0d3e4a22011-06-23 19:02:5234 ExtensionAPIPermission::ID permission;
[email protected]598bbcc2011-02-24 10:03:2535};
36
[email protected]d20e8ce2011-05-25 23:54:2537const char kNotControllable[] = "not_controllable";
38const char kControlledByOtherExtensions[] = "controlled_by_other_extensions";
39const char kControllableByThisExtension[] = "controllable_by_this_extension";
40const char kControlledByThisExtension[] = "controlled_by_this_extension";
[email protected]9a28f132011-02-24 21:15:1641
[email protected]c0793562011-03-09 15:31:0342const char kIncognitoSpecific[] = "incognitoSpecific";
[email protected]c0793562011-03-09 15:31:0343const char kLevelOfControl[] = "levelOfControl";
[email protected]c0793562011-03-09 15:31:0344const char kValue[] = "value";
45
[email protected]023208cf2011-06-02 23:56:4146const char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange";
[email protected]118de7892011-03-16 13:31:4047
[email protected]3e3342692011-03-15 12:03:2748PrefMappingEntry kPrefMapping[] = {
[email protected]fbc660102011-08-26 05:41:2149 { "alternateErrorPagesEnabled",
50 prefs::kAlternateErrorPagesEnabled,
51 ExtensionAPIPermission::kExperimental
[email protected]598bbcc2011-02-24 10:03:2552 },
[email protected]fbc660102011-08-26 05:41:2153 { "autofillEnabled",
54 prefs::kAutofillEnabled,
55 ExtensionAPIPermission::kExperimental
[email protected]0a8db0d2011-04-13 15:15:4056 },
[email protected]c9471ea2011-06-02 18:09:0757 { "hyperlinkAuditingEnabled",
[email protected]0a8db0d2011-04-13 15:15:4058 prefs::kEnableHyperlinkAuditing,
[email protected]fbc660102011-08-26 05:41:2159 ExtensionAPIPermission::kExperimental
60 },
61 { "instantEnabled",
62 prefs::kInstantEnabled,
63 ExtensionAPIPermission::kExperimental
64 },
65 // TODO(mkwst): come back to this once the UMA discussion has been resolved.
66 // { "metricsReportingEnabled",
67 // prefs::kMetricsReportingEnabled,
68 // ExtensionAPIPermission::kMetrics
69 // },
70 { "networkPredictionEnabled",
71 prefs::kNetworkPredictionEnabled,
72 ExtensionAPIPermission::kExperimental
[email protected]0a8db0d2011-04-13 15:15:4073 },
[email protected]ccfdfbdf2011-02-24 12:41:4674 { "proxy",
75 prefs::kProxy,
[email protected]0d3e4a22011-06-23 19:02:5276 ExtensionAPIPermission::kProxy
[email protected]ccfdfbdf2011-02-24 12:41:4677 },
[email protected]fbc660102011-08-26 05:41:2178 { "referrersEnabled",
79 prefs::kEnableReferrers,
80 ExtensionAPIPermission::kExperimental
81 },
82 { "searchSuggestEnabled",
83 prefs::kSearchSuggestEnabled,
84 ExtensionAPIPermission::kExperimental
85 },
86 { "safeBrowsingEnabled",
87 prefs::kSafeBrowsingEnabled,
88 ExtensionAPIPermission::kExperimental
89 },
90 { "thirdPartyCookiesAllowed",
91 prefs::kBlockThirdPartyCookies,
92 ExtensionAPIPermission::kExperimental
93 },
94 { "translationServiceEnabled",
95 prefs::kEnableTranslate,
96 ExtensionAPIPermission::kExperimental
97 }
[email protected]598bbcc2011-02-24 10:03:2598};
99
[email protected]3e3342692011-03-15 12:03:27100class IdentityPrefTransformer : public PrefTransformerInterface {
101 public:
[email protected]3e3342692011-03-15 12:03:27102 virtual Value* ExtensionToBrowserPref(const Value* extension_pref,
[email protected]ca943e72011-05-03 16:58:04103 std::string* error,
104 bool* bad_message) {
[email protected]3e3342692011-03-15 12:03:27105 return extension_pref->DeepCopy();
106 }
107
108 virtual Value* BrowserToExtensionPref(const Value* browser_pref) {
109 return browser_pref->DeepCopy();
110 }
111};
112
[email protected]c9471ea2011-06-02 18:09:07113class InvertBooleanTransformer : public PrefTransformerInterface {
114 public:
115 virtual Value* ExtensionToBrowserPref(const Value* extension_pref,
116 std::string* error,
117 bool* bad_message) {
118 return InvertBooleanValue(extension_pref);
119 }
120
121 virtual Value* BrowserToExtensionPref(const Value* browser_pref) {
122 return InvertBooleanValue(browser_pref);
123 }
124
125 private:
126 static Value* InvertBooleanValue(const Value* value) {
127 bool bool_value = false;
128 bool result = value->GetAsBoolean(&bool_value);
129 DCHECK(result);
130 return Value::CreateBooleanValue(!bool_value);
131 }
132};
133
[email protected]118de7892011-03-16 13:31:40134// Returns a string constant (defined in the API) indicating the level of
135// control this extension has over the specified preference.
136const char* GetLevelOfControl(
137 Profile* profile,
138 const std::string& extension_id,
139 const std::string& browser_pref,
140 bool incognito) {
141 PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs()
142 : profile->GetPrefs();
143 const PrefService::Preference* pref =
144 prefs->FindPreference(browser_pref.c_str());
145 CHECK(pref);
146 ExtensionPrefs* ep = profile->GetExtensionService()->extension_prefs();
147
148 if (!pref->IsExtensionModifiable())
149 return kNotControllable;
150
151 if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito))
152 return kControlledByThisExtension;
153
154 if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito))
155 return kControllableByThisExtension;
156
157 return kControlledByOtherExtensions;
158}
159
[email protected]598bbcc2011-02-24 10:03:25160class PrefMapping {
161 public:
162 static PrefMapping* GetInstance() {
163 return Singleton<PrefMapping>::get();
164 }
165
166 bool FindBrowserPrefForExtensionPref(const std::string& extension_pref,
167 std::string* browser_pref,
[email protected]0d3e4a22011-06-23 19:02:52168 ExtensionAPIPermission::ID* permission) {
169 PrefMap::iterator it = mapping_.find(extension_pref);
[email protected]598bbcc2011-02-24 10:03:25170 if (it != mapping_.end()) {
171 *browser_pref = it->second.first;
172 *permission = it->second.second;
173 return true;
174 }
175 return false;
176 }
177
[email protected]118de7892011-03-16 13:31:40178 bool FindEventForBrowserPref(const std::string& browser_pref,
179 std::string* event_name,
[email protected]0d3e4a22011-06-23 19:02:52180 ExtensionAPIPermission::ID* permission) {
181 PrefMap::iterator it = event_mapping_.find(browser_pref);
[email protected]118de7892011-03-16 13:31:40182 if (it != event_mapping_.end()) {
183 *event_name = it->second.first;
184 *permission = it->second.second;
185 return true;
186 }
187 return false;
188 }
189
[email protected]3e3342692011-03-15 12:03:27190 PrefTransformerInterface* FindTransformerForBrowserPref(
191 const std::string& browser_pref) {
192 std::map<std::string, PrefTransformerInterface*>::iterator it =
193 transformers_.find(browser_pref);
194 if (it != transformers_.end())
195 return it->second;
196 else
197 return identity_transformer_.get();
198 }
199
[email protected]598bbcc2011-02-24 10:03:25200 private:
201 friend struct DefaultSingletonTraits<PrefMapping>;
202
[email protected]3e3342692011-03-15 12:03:27203 PrefMapping() {
204 identity_transformer_.reset(new IdentityPrefTransformer());
205 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
206 mapping_[kPrefMapping[i].extension_pref] =
207 std::make_pair(kPrefMapping[i].browser_pref,
208 kPrefMapping[i].permission);
[email protected]118de7892011-03-16 13:31:40209 std::string event_name =
210 base::StringPrintf(kOnPrefChangeFormat,
211 kPrefMapping[i].extension_pref);
212 event_mapping_[kPrefMapping[i].browser_pref] =
213 std::make_pair(event_name, kPrefMapping[i].permission);
[email protected]3e3342692011-03-15 12:03:27214 }
215 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size());
[email protected]118de7892011-03-16 13:31:40216 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size());
[email protected]3e3342692011-03-15 12:03:27217 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer());
[email protected]c9471ea2011-06-02 18:09:07218 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies,
219 new InvertBooleanTransformer());
[email protected]3e3342692011-03-15 12:03:27220 }
221
222 ~PrefMapping() {
223 STLDeleteContainerPairSecondPointers(transformers_.begin(),
224 transformers_.end());
225 }
226
227 void RegisterPrefTransformer(const std::string& browser_pref,
228 PrefTransformerInterface* transformer) {
229 DCHECK_EQ(0u, transformers_.count(browser_pref)) <<
230 "Trying to register pref transformer for " << browser_pref << " twice";
231 transformers_[browser_pref] = transformer;
232 }
233
[email protected]0d3e4a22011-06-23 19:02:52234 typedef std::map<std::string,
235 std::pair<std::string, ExtensionAPIPermission::ID> >
236 PrefMap;
237
[email protected]118de7892011-03-16 13:31:40238 // Mapping from extension pref keys to browser pref keys and permissions.
[email protected]0d3e4a22011-06-23 19:02:52239 PrefMap mapping_;
[email protected]598bbcc2011-02-24 10:03:25240
[email protected]118de7892011-03-16 13:31:40241 // Mapping from browser pref keys to extension event names and permissions.
[email protected]0d3e4a22011-06-23 19:02:52242 PrefMap event_mapping_;
[email protected]598bbcc2011-02-24 10:03:25243
[email protected]3e3342692011-03-15 12:03:27244 // Mapping from browser pref keys to transformers.
245 std::map<std::string, PrefTransformerInterface*> transformers_;
246
247 scoped_ptr<PrefTransformerInterface> identity_transformer_;
[email protected]118de7892011-03-16 13:31:40248
249 DISALLOW_COPY_AND_ASSIGN(PrefMapping);
[email protected]3e3342692011-03-15 12:03:27250};
[email protected]598bbcc2011-02-24 10:03:25251
252} // namespace
253
[email protected]fa0624262011-06-09 14:17:38254namespace keys = extension_preference_api_constants;
255namespace helpers = extension_preference_helpers;
256
[email protected]118de7892011-03-16 13:31:40257ExtensionPreferenceEventRouter::ExtensionPreferenceEventRouter(
258 Profile* profile) : profile_(profile) {
259 registrar_.Init(profile_->GetPrefs());
260 incognito_registrar_.Init(profile_->GetOffTheRecordPrefs());
261 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
262 registrar_.Add(kPrefMapping[i].browser_pref, this);
263 incognito_registrar_.Add(kPrefMapping[i].browser_pref, this);
264 }
265}
266
[email protected]7da9a8232011-05-27 21:07:11267ExtensionPreferenceEventRouter::~ExtensionPreferenceEventRouter() { }
268
[email protected]118de7892011-03-16 13:31:40269void ExtensionPreferenceEventRouter::Observe(
[email protected]432115822011-07-10 15:52:27270 int type,
[email protected]6c2381d2011-10-19 02:52:53271 const content::NotificationSource& source,
272 const content::NotificationDetails& details) {
[email protected]432115822011-07-10 15:52:27273 if (type == chrome::NOTIFICATION_PREF_CHANGED) {
[email protected]118de7892011-03-16 13:31:40274 const std::string* pref_key =
[email protected]6c2381d2011-10-19 02:52:53275 content::Details<const std::string>(details).ptr();
276 OnPrefChanged(content::Source<PrefService>(source).ptr(), *pref_key);
[email protected]118de7892011-03-16 13:31:40277 } else {
278 NOTREACHED();
279 }
280}
281
282void ExtensionPreferenceEventRouter::OnPrefChanged(
283 PrefService* pref_service,
284 const std::string& browser_pref) {
285 bool incognito = (pref_service != profile_->GetPrefs());
286
287 std::string event_name;
[email protected]0d3e4a22011-06-23 19:02:52288 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid;
[email protected]118de7892011-03-16 13:31:40289 bool rv = PrefMapping::GetInstance()->FindEventForBrowserPref(
290 browser_pref, &event_name, &permission);
291 DCHECK(rv);
292
293 ListValue args;
294 DictionaryValue* dict = new DictionaryValue();
295 args.Append(dict);
296 const PrefService::Preference* pref =
297 pref_service->FindPreference(browser_pref.c_str());
298 CHECK(pref);
299 ExtensionService* extension_service = profile_->GetExtensionService();
300 PrefTransformerInterface* transformer =
301 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
302 dict->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue()));
303 if (incognito) {
304 ExtensionPrefs* ep = extension_service->extension_prefs();
[email protected]fa0624262011-06-09 14:17:38305 dict->SetBoolean(kIncognitoSpecific,
306 ep->HasIncognitoPrefValue(browser_pref));
[email protected]118de7892011-03-16 13:31:40307 }
308
309 ExtensionEventRouter* router = profile_->GetExtensionEventRouter();
310 if (!router || !router->HasEventListener(event_name))
311 return;
312 const ExtensionList* extensions = extension_service->extensions();
313 for (ExtensionList::const_iterator it = extensions->begin();
314 it != extensions->end(); ++it) {
315 std::string extension_id = (*it)->id();
316 // TODO(bauerb): Only iterate over registered event listeners.
317 if (router->ExtensionHasEventListener(extension_id, event_name) &&
[email protected]0d3e4a22011-06-23 19:02:52318 (*it)->HasAPIPermission(permission) &&
[email protected]118de7892011-03-16 13:31:40319 (!incognito || extension_service->CanCrossIncognito(*it))) {
320 std::string level_of_control =
321 GetLevelOfControl(profile_, extension_id, browser_pref, incognito);
[email protected]fa0624262011-06-09 14:17:38322 dict->SetString(kLevelOfControl, level_of_control);
[email protected]118de7892011-03-16 13:31:40323
324 std::string json_args;
325 base::JSONWriter::Write(&args, false, &json_args);
326
327 DispatchEvent(extension_id, event_name, json_args);
328 }
329 }
330}
331
332void ExtensionPreferenceEventRouter::DispatchEvent(
333 const std::string& extension_id,
334 const std::string& event_name,
335 const std::string& json_args) {
336 profile_->GetExtensionEventRouter()->DispatchEventToExtension(
337 extension_id, event_name, json_args, NULL, GURL());
338}
339
[email protected]c433bcb2011-02-24 13:10:27340// TODO(battre): Factor out common parts once this is stable.
341
[email protected]598bbcc2011-02-24 10:03:25342GetPreferenceFunction::~GetPreferenceFunction() { }
343
344bool GetPreferenceFunction::RunImpl() {
345 std::string pref_key;
346 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
347 DictionaryValue* details = NULL;
348 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
349
350 bool incognito = false;
[email protected]fa0624262011-06-09 14:17:38351 if (details->HasKey(keys::kIncognitoKey))
352 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(keys::kIncognitoKey,
353 &incognito));
[email protected]c0793562011-03-09 15:31:03354
355 if (incognito && !include_incognito()) {
[email protected]fa0624262011-06-09 14:17:38356 error_ = keys::kIncognitoErrorMessage;
[email protected]c0793562011-03-09 15:31:03357 return false;
358 }
[email protected]598bbcc2011-02-24 10:03:25359
360 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs()
361 : profile_->GetPrefs();
362 std::string browser_pref;
[email protected]0d3e4a22011-06-23 19:02:52363 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid;
[email protected]598bbcc2011-02-24 10:03:25364 EXTENSION_FUNCTION_VALIDATE(
365 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
366 pref_key, &browser_pref, &permission));
[email protected]0d3e4a22011-06-23 19:02:52367 if (!GetExtension()->HasAPIPermission(permission)) {
[email protected]fa0624262011-06-09 14:17:38368 error_ = ExtensionErrorUtils::FormatErrorMessage(
369 keys::kPermissionErrorMessage, pref_key);
[email protected]598bbcc2011-02-24 10:03:25370 return false;
371 }
[email protected]9a28f132011-02-24 21:15:16372
[email protected]598bbcc2011-02-24 10:03:25373 const PrefService::Preference* pref =
374 prefs->FindPreference(browser_pref.c_str());
375 CHECK(pref);
[email protected]118de7892011-03-16 13:31:40376 std::string level_of_control =
377 GetLevelOfControl(profile_, extension_id(), browser_pref, incognito);
[email protected]9a28f132011-02-24 21:15:16378
379 scoped_ptr<DictionaryValue> result(new DictionaryValue);
[email protected]3e3342692011-03-15 12:03:27380 PrefTransformerInterface* transformer =
381 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
382 result->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue()));
[email protected]fa0624262011-06-09 14:17:38383 result->SetString(kLevelOfControl, level_of_control);
[email protected]c0793562011-03-09 15:31:03384 if (incognito) {
385 ExtensionPrefs* ep = profile_->GetExtensionService()->extension_prefs();
[email protected]fa0624262011-06-09 14:17:38386 result->SetBoolean(kIncognitoSpecific,
387 ep->HasIncognitoPrefValue(browser_pref));
[email protected]c0793562011-03-09 15:31:03388 }
[email protected]9a28f132011-02-24 21:15:16389 result_.reset(result.release());
[email protected]598bbcc2011-02-24 10:03:25390 return true;
391}
392
393SetPreferenceFunction::~SetPreferenceFunction() { }
394
395bool SetPreferenceFunction::RunImpl() {
396 std::string pref_key;
397 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
398 DictionaryValue* details = NULL;
399 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
400
401 Value* value = NULL;
[email protected]c0793562011-03-09 15:31:03402 EXTENSION_FUNCTION_VALIDATE(details->Get(kValue, &value));
[email protected]598bbcc2011-02-24 10:03:25403
[email protected]fa0624262011-06-09 14:17:38404 ExtensionPrefsScope scope = kExtensionPrefsScopeRegular;
405 if (details->HasKey(keys::kScopeKey)) {
406 std::string scope_str;
407 EXTENSION_FUNCTION_VALIDATE(
408 details->GetString(keys::kScopeKey, &scope_str));
[email protected]8b001f32011-05-25 19:03:23409
[email protected]fa0624262011-06-09 14:17:38410 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope));
411 }
[email protected]c0793562011-03-09 15:31:03412
[email protected]dece9a62011-06-07 17:38:59413 bool incognito = (scope == kExtensionPrefsScopeIncognitoPersistent ||
414 scope == kExtensionPrefsScopeIncognitoSessionOnly);
[email protected]9783c162011-05-25 21:45:51415 if (incognito) {
416 // Regular profiles can't access incognito unless include_incognito is true.
417 if (!profile()->IsOffTheRecord() && !include_incognito()) {
[email protected]fa0624262011-06-09 14:17:38418 error_ = keys::kIncognitoErrorMessage;
[email protected]9783c162011-05-25 21:45:51419 return false;
420 }
421 } else {
422 // Incognito profiles can't access regular mode ever, they only exist in
423 // split mode.
424 if (profile()->IsOffTheRecord()) {
425 error_ = "Can't modify regular settings from an incognito context.";
426 return false;
427 }
[email protected]c0793562011-03-09 15:31:03428 }
[email protected]598bbcc2011-02-24 10:03:25429
[email protected]dece9a62011-06-07 17:38:59430 if (scope == kExtensionPrefsScopeIncognitoSessionOnly &&
[email protected]31685742011-05-25 23:01:56431 !profile_->HasOffTheRecordProfile()) {
[email protected]fa0624262011-06-09 14:17:38432 error_ = keys::kIncognitoSessionOnlyErrorMessage;
[email protected]d20e8ce2011-05-25 23:54:25433 return false;
434 }
435
[email protected]598bbcc2011-02-24 10:03:25436 std::string browser_pref;
[email protected]0d3e4a22011-06-23 19:02:52437 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid;
[email protected]598bbcc2011-02-24 10:03:25438 EXTENSION_FUNCTION_VALIDATE(
439 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
440 pref_key, &browser_pref, &permission));
[email protected]0d3e4a22011-06-23 19:02:52441 if (!GetExtension()->HasAPIPermission(permission)) {
[email protected]fa0624262011-06-09 14:17:38442 error_ = ExtensionErrorUtils::FormatErrorMessage(
443 keys::kPermissionErrorMessage, pref_key);
[email protected]598bbcc2011-02-24 10:03:25444 return false;
445 }
446 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs();
447 const PrefService::Preference* pref =
448 prefs->pref_service()->FindPreference(browser_pref.c_str());
449 CHECK(pref);
450 EXTENSION_FUNCTION_VALIDATE(value->GetType() == pref->GetType());
[email protected]3e3342692011-03-15 12:03:27451 PrefTransformerInterface* transformer =
452 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
453 std::string error;
[email protected]ca943e72011-05-03 16:58:04454 bool bad_message = false;
455 Value* browserPrefValue =
456 transformer->ExtensionToBrowserPref(value, &error, &bad_message);
[email protected]3e3342692011-03-15 12:03:27457 if (!browserPrefValue) {
458 error_ = error;
[email protected]ca943e72011-05-03 16:58:04459 bad_message_ = bad_message;
[email protected]3e3342692011-03-15 12:03:27460 return false;
461 }
[email protected]598bbcc2011-02-24 10:03:25462 prefs->SetExtensionControlledPref(extension_id(),
463 browser_pref,
[email protected]9783c162011-05-25 21:45:51464 scope,
[email protected]3e3342692011-03-15 12:03:27465 browserPrefValue);
[email protected]598bbcc2011-02-24 10:03:25466 return true;
467}
[email protected]c433bcb2011-02-24 13:10:27468
469ClearPreferenceFunction::~ClearPreferenceFunction() { }
470
471bool ClearPreferenceFunction::RunImpl() {
472 std::string pref_key;
473 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
474 DictionaryValue* details = NULL;
475 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
476
[email protected]fa0624262011-06-09 14:17:38477 ExtensionPrefsScope scope = kExtensionPrefsScopeRegular;
478 if (details->HasKey(keys::kScopeKey)) {
479 std::string scope_str;
480 EXTENSION_FUNCTION_VALIDATE(
481 details->GetString(keys::kScopeKey, &scope_str));
[email protected]8b001f32011-05-25 19:03:23482
[email protected]fa0624262011-06-09 14:17:38483 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope));
484 }
[email protected]c0793562011-03-09 15:31:03485
[email protected]dece9a62011-06-07 17:38:59486 bool incognito = (scope == kExtensionPrefsScopeIncognitoPersistent ||
487 scope == kExtensionPrefsScopeIncognitoSessionOnly);
[email protected]9783c162011-05-25 21:45:51488 if (incognito) {
489 // We don't check incognito permissions here, as an extension should be
490 // always allowed to clear its own settings.
491 } else {
492 // Incognito profiles can't access regular mode ever, they only exist in
493 // split mode.
494 if (profile()->IsOffTheRecord()) {
495 error_ = "Can't modify regular settings from an incognito context.";
496 return false;
497 }
498 }
[email protected]c433bcb2011-02-24 13:10:27499
500 std::string browser_pref;
[email protected]0d3e4a22011-06-23 19:02:52501 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid;
[email protected]c433bcb2011-02-24 13:10:27502 EXTENSION_FUNCTION_VALIDATE(
503 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
504 pref_key, &browser_pref, &permission));
[email protected]0d3e4a22011-06-23 19:02:52505 if (!GetExtension()->HasAPIPermission(permission)) {
[email protected]fa0624262011-06-09 14:17:38506 error_ = ExtensionErrorUtils::FormatErrorMessage(
507 keys::kPermissionErrorMessage, pref_key);
[email protected]c433bcb2011-02-24 13:10:27508 return false;
509 }
510 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs();
[email protected]9783c162011-05-25 21:45:51511 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, scope);
[email protected]c433bcb2011-02-24 13:10:27512 return true;
513}