blob: 222572b1a86c1cdd3a935b8148939d597e60fd8e [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 {
[email protected]80f95f512011-12-19 00:51:0432 // Name of the preference referenced by the extension API JSON.
[email protected]598bbcc2011-02-24 10:03:2533 const char* extension_pref;
[email protected]a4f98922011-12-06 11:32:2334
35 // Name of the preference in the PrefStores.
[email protected]598bbcc2011-02-24 10:03:2536 const char* browser_pref;
[email protected]a4f98922011-12-06 11:32:2337
38 // Permission required to access this preference.
39 // Use ExtensionAPIPermission::kInvalid for |permission| to express that no
40 // permission is necessary.
[email protected]0d3e4a22011-06-23 19:02:5241 ExtensionAPIPermission::ID permission;
[email protected]598bbcc2011-02-24 10:03:2542};
43
[email protected]d20e8ce2011-05-25 23:54:2544const char kNotControllable[] = "not_controllable";
45const char kControlledByOtherExtensions[] = "controlled_by_other_extensions";
46const char kControllableByThisExtension[] = "controllable_by_this_extension";
47const char kControlledByThisExtension[] = "controlled_by_this_extension";
[email protected]9a28f132011-02-24 21:15:1648
[email protected]c0793562011-03-09 15:31:0349const char kIncognitoSpecific[] = "incognitoSpecific";
[email protected]c0793562011-03-09 15:31:0350const char kLevelOfControl[] = "levelOfControl";
[email protected]c0793562011-03-09 15:31:0351const char kValue[] = "value";
52
[email protected]023208cf2011-06-02 23:56:4153const char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange";
[email protected]118de7892011-03-16 13:31:4054
[email protected]3e3342692011-03-15 12:03:2755PrefMappingEntry kPrefMapping[] = {
[email protected]fbc660102011-08-26 05:41:2156 { "alternateErrorPagesEnabled",
57 prefs::kAlternateErrorPagesEnabled,
58 ExtensionAPIPermission::kExperimental
[email protected]598bbcc2011-02-24 10:03:2559 },
[email protected]fbc660102011-08-26 05:41:2160 { "autofillEnabled",
61 prefs::kAutofillEnabled,
62 ExtensionAPIPermission::kExperimental
[email protected]0a8db0d2011-04-13 15:15:4063 },
[email protected]c9471ea2011-06-02 18:09:0764 { "hyperlinkAuditingEnabled",
[email protected]0a8db0d2011-04-13 15:15:4065 prefs::kEnableHyperlinkAuditing,
[email protected]fbc660102011-08-26 05:41:2166 ExtensionAPIPermission::kExperimental
67 },
68 { "instantEnabled",
69 prefs::kInstantEnabled,
70 ExtensionAPIPermission::kExperimental
71 },
72 // TODO(mkwst): come back to this once the UMA discussion has been resolved.
73 // { "metricsReportingEnabled",
74 // prefs::kMetricsReportingEnabled,
75 // ExtensionAPIPermission::kMetrics
76 // },
77 { "networkPredictionEnabled",
78 prefs::kNetworkPredictionEnabled,
79 ExtensionAPIPermission::kExperimental
[email protected]0a8db0d2011-04-13 15:15:4080 },
[email protected]ccfdfbdf2011-02-24 12:41:4681 { "proxy",
82 prefs::kProxy,
[email protected]0d3e4a22011-06-23 19:02:5283 ExtensionAPIPermission::kProxy
[email protected]ccfdfbdf2011-02-24 12:41:4684 },
[email protected]fbc660102011-08-26 05:41:2185 { "referrersEnabled",
86 prefs::kEnableReferrers,
87 ExtensionAPIPermission::kExperimental
88 },
89 { "searchSuggestEnabled",
90 prefs::kSearchSuggestEnabled,
91 ExtensionAPIPermission::kExperimental
92 },
93 { "safeBrowsingEnabled",
94 prefs::kSafeBrowsingEnabled,
95 ExtensionAPIPermission::kExperimental
96 },
97 { "thirdPartyCookiesAllowed",
98 prefs::kBlockThirdPartyCookies,
99 ExtensionAPIPermission::kExperimental
100 },
101 { "translationServiceEnabled",
102 prefs::kEnableTranslate,
103 ExtensionAPIPermission::kExperimental
104 }
[email protected]598bbcc2011-02-24 10:03:25105};
106
[email protected]3e3342692011-03-15 12:03:27107class IdentityPrefTransformer : public PrefTransformerInterface {
108 public:
[email protected]3e3342692011-03-15 12:03:27109 virtual Value* ExtensionToBrowserPref(const Value* extension_pref,
[email protected]ca943e72011-05-03 16:58:04110 std::string* error,
111 bool* bad_message) {
[email protected]3e3342692011-03-15 12:03:27112 return extension_pref->DeepCopy();
113 }
114
115 virtual Value* BrowserToExtensionPref(const Value* browser_pref) {
116 return browser_pref->DeepCopy();
117 }
118};
119
[email protected]c9471ea2011-06-02 18:09:07120class InvertBooleanTransformer : public PrefTransformerInterface {
121 public:
122 virtual Value* ExtensionToBrowserPref(const Value* extension_pref,
123 std::string* error,
124 bool* bad_message) {
125 return InvertBooleanValue(extension_pref);
126 }
127
128 virtual Value* BrowserToExtensionPref(const Value* browser_pref) {
129 return InvertBooleanValue(browser_pref);
130 }
131
132 private:
133 static Value* InvertBooleanValue(const Value* value) {
134 bool bool_value = false;
135 bool result = value->GetAsBoolean(&bool_value);
136 DCHECK(result);
137 return Value::CreateBooleanValue(!bool_value);
138 }
139};
140
[email protected]118de7892011-03-16 13:31:40141// Returns a string constant (defined in the API) indicating the level of
142// control this extension has over the specified preference.
143const char* GetLevelOfControl(
144 Profile* profile,
145 const std::string& extension_id,
146 const std::string& browser_pref,
147 bool incognito) {
148 PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs()
149 : profile->GetPrefs();
150 const PrefService::Preference* pref =
151 prefs->FindPreference(browser_pref.c_str());
152 CHECK(pref);
153 ExtensionPrefs* ep = profile->GetExtensionService()->extension_prefs();
154
155 if (!pref->IsExtensionModifiable())
156 return kNotControllable;
157
158 if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito))
159 return kControlledByThisExtension;
160
161 if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito))
162 return kControllableByThisExtension;
163
164 return kControlledByOtherExtensions;
165}
166
[email protected]598bbcc2011-02-24 10:03:25167class PrefMapping {
168 public:
169 static PrefMapping* GetInstance() {
170 return Singleton<PrefMapping>::get();
171 }
172
173 bool FindBrowserPrefForExtensionPref(const std::string& extension_pref,
174 std::string* browser_pref,
[email protected]0d3e4a22011-06-23 19:02:52175 ExtensionAPIPermission::ID* permission) {
176 PrefMap::iterator it = mapping_.find(extension_pref);
[email protected]598bbcc2011-02-24 10:03:25177 if (it != mapping_.end()) {
178 *browser_pref = it->second.first;
179 *permission = it->second.second;
180 return true;
181 }
182 return false;
183 }
184
[email protected]118de7892011-03-16 13:31:40185 bool FindEventForBrowserPref(const std::string& browser_pref,
186 std::string* event_name,
[email protected]0d3e4a22011-06-23 19:02:52187 ExtensionAPIPermission::ID* permission) {
188 PrefMap::iterator it = event_mapping_.find(browser_pref);
[email protected]118de7892011-03-16 13:31:40189 if (it != event_mapping_.end()) {
190 *event_name = it->second.first;
191 *permission = it->second.second;
192 return true;
193 }
194 return false;
195 }
196
[email protected]3e3342692011-03-15 12:03:27197 PrefTransformerInterface* FindTransformerForBrowserPref(
198 const std::string& browser_pref) {
199 std::map<std::string, PrefTransformerInterface*>::iterator it =
200 transformers_.find(browser_pref);
201 if (it != transformers_.end())
202 return it->second;
203 else
204 return identity_transformer_.get();
205 }
206
[email protected]598bbcc2011-02-24 10:03:25207 private:
208 friend struct DefaultSingletonTraits<PrefMapping>;
209
[email protected]3e3342692011-03-15 12:03:27210 PrefMapping() {
211 identity_transformer_.reset(new IdentityPrefTransformer());
212 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
213 mapping_[kPrefMapping[i].extension_pref] =
214 std::make_pair(kPrefMapping[i].browser_pref,
215 kPrefMapping[i].permission);
[email protected]118de7892011-03-16 13:31:40216 std::string event_name =
217 base::StringPrintf(kOnPrefChangeFormat,
218 kPrefMapping[i].extension_pref);
219 event_mapping_[kPrefMapping[i].browser_pref] =
220 std::make_pair(event_name, kPrefMapping[i].permission);
[email protected]3e3342692011-03-15 12:03:27221 }
222 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size());
[email protected]118de7892011-03-16 13:31:40223 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size());
[email protected]3e3342692011-03-15 12:03:27224 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer());
[email protected]c9471ea2011-06-02 18:09:07225 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies,
226 new InvertBooleanTransformer());
[email protected]3e3342692011-03-15 12:03:27227 }
228
229 ~PrefMapping() {
230 STLDeleteContainerPairSecondPointers(transformers_.begin(),
231 transformers_.end());
232 }
233
234 void RegisterPrefTransformer(const std::string& browser_pref,
235 PrefTransformerInterface* transformer) {
236 DCHECK_EQ(0u, transformers_.count(browser_pref)) <<
237 "Trying to register pref transformer for " << browser_pref << " twice";
238 transformers_[browser_pref] = transformer;
239 }
240
[email protected]0d3e4a22011-06-23 19:02:52241 typedef std::map<std::string,
242 std::pair<std::string, ExtensionAPIPermission::ID> >
243 PrefMap;
244
[email protected]118de7892011-03-16 13:31:40245 // Mapping from extension pref keys to browser pref keys and permissions.
[email protected]0d3e4a22011-06-23 19:02:52246 PrefMap mapping_;
[email protected]598bbcc2011-02-24 10:03:25247
[email protected]118de7892011-03-16 13:31:40248 // Mapping from browser pref keys to extension event names and permissions.
[email protected]0d3e4a22011-06-23 19:02:52249 PrefMap event_mapping_;
[email protected]598bbcc2011-02-24 10:03:25250
[email protected]3e3342692011-03-15 12:03:27251 // Mapping from browser pref keys to transformers.
252 std::map<std::string, PrefTransformerInterface*> transformers_;
253
254 scoped_ptr<PrefTransformerInterface> identity_transformer_;
[email protected]118de7892011-03-16 13:31:40255
256 DISALLOW_COPY_AND_ASSIGN(PrefMapping);
[email protected]3e3342692011-03-15 12:03:27257};
[email protected]598bbcc2011-02-24 10:03:25258
259} // namespace
260
[email protected]fa0624262011-06-09 14:17:38261namespace keys = extension_preference_api_constants;
262namespace helpers = extension_preference_helpers;
263
[email protected]118de7892011-03-16 13:31:40264ExtensionPreferenceEventRouter::ExtensionPreferenceEventRouter(
265 Profile* profile) : profile_(profile) {
266 registrar_.Init(profile_->GetPrefs());
267 incognito_registrar_.Init(profile_->GetOffTheRecordPrefs());
268 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
269 registrar_.Add(kPrefMapping[i].browser_pref, this);
270 incognito_registrar_.Add(kPrefMapping[i].browser_pref, this);
271 }
272}
273
[email protected]7da9a8232011-05-27 21:07:11274ExtensionPreferenceEventRouter::~ExtensionPreferenceEventRouter() { }
275
[email protected]118de7892011-03-16 13:31:40276void ExtensionPreferenceEventRouter::Observe(
[email protected]432115822011-07-10 15:52:27277 int type,
[email protected]6c2381d2011-10-19 02:52:53278 const content::NotificationSource& source,
279 const content::NotificationDetails& details) {
[email protected]432115822011-07-10 15:52:27280 if (type == chrome::NOTIFICATION_PREF_CHANGED) {
[email protected]118de7892011-03-16 13:31:40281 const std::string* pref_key =
[email protected]6c2381d2011-10-19 02:52:53282 content::Details<const std::string>(details).ptr();
283 OnPrefChanged(content::Source<PrefService>(source).ptr(), *pref_key);
[email protected]118de7892011-03-16 13:31:40284 } else {
285 NOTREACHED();
286 }
287}
288
289void ExtensionPreferenceEventRouter::OnPrefChanged(
290 PrefService* pref_service,
291 const std::string& browser_pref) {
292 bool incognito = (pref_service != profile_->GetPrefs());
293
294 std::string event_name;
[email protected]0d3e4a22011-06-23 19:02:52295 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid;
[email protected]118de7892011-03-16 13:31:40296 bool rv = PrefMapping::GetInstance()->FindEventForBrowserPref(
297 browser_pref, &event_name, &permission);
298 DCHECK(rv);
299
300 ListValue args;
301 DictionaryValue* dict = new DictionaryValue();
302 args.Append(dict);
303 const PrefService::Preference* pref =
304 pref_service->FindPreference(browser_pref.c_str());
305 CHECK(pref);
306 ExtensionService* extension_service = profile_->GetExtensionService();
307 PrefTransformerInterface* transformer =
308 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
309 dict->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue()));
310 if (incognito) {
311 ExtensionPrefs* ep = extension_service->extension_prefs();
[email protected]fa0624262011-06-09 14:17:38312 dict->SetBoolean(kIncognitoSpecific,
313 ep->HasIncognitoPrefValue(browser_pref));
[email protected]118de7892011-03-16 13:31:40314 }
315
316 ExtensionEventRouter* router = profile_->GetExtensionEventRouter();
317 if (!router || !router->HasEventListener(event_name))
318 return;
[email protected]84df8332011-12-06 18:22:46319 const ExtensionSet* extensions = extension_service->extensions();
320 for (ExtensionSet::const_iterator it = extensions->begin();
[email protected]118de7892011-03-16 13:31:40321 it != extensions->end(); ++it) {
322 std::string extension_id = (*it)->id();
323 // TODO(bauerb): Only iterate over registered event listeners.
324 if (router->ExtensionHasEventListener(extension_id, event_name) &&
[email protected]0d3e4a22011-06-23 19:02:52325 (*it)->HasAPIPermission(permission) &&
[email protected]118de7892011-03-16 13:31:40326 (!incognito || extension_service->CanCrossIncognito(*it))) {
327 std::string level_of_control =
328 GetLevelOfControl(profile_, extension_id, browser_pref, incognito);
[email protected]fa0624262011-06-09 14:17:38329 dict->SetString(kLevelOfControl, level_of_control);
[email protected]118de7892011-03-16 13:31:40330
331 std::string json_args;
332 base::JSONWriter::Write(&args, false, &json_args);
333
334 DispatchEvent(extension_id, event_name, json_args);
335 }
336 }
337}
338
339void ExtensionPreferenceEventRouter::DispatchEvent(
340 const std::string& extension_id,
341 const std::string& event_name,
342 const std::string& json_args) {
343 profile_->GetExtensionEventRouter()->DispatchEventToExtension(
344 extension_id, event_name, json_args, NULL, GURL());
345}
346
[email protected]c433bcb2011-02-24 13:10:27347// TODO(battre): Factor out common parts once this is stable.
348
[email protected]598bbcc2011-02-24 10:03:25349GetPreferenceFunction::~GetPreferenceFunction() { }
350
351bool GetPreferenceFunction::RunImpl() {
352 std::string pref_key;
353 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
354 DictionaryValue* details = NULL;
355 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
356
357 bool incognito = false;
[email protected]fa0624262011-06-09 14:17:38358 if (details->HasKey(keys::kIncognitoKey))
359 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(keys::kIncognitoKey,
360 &incognito));
[email protected]c0793562011-03-09 15:31:03361
362 if (incognito && !include_incognito()) {
[email protected]fa0624262011-06-09 14:17:38363 error_ = keys::kIncognitoErrorMessage;
[email protected]c0793562011-03-09 15:31:03364 return false;
365 }
[email protected]598bbcc2011-02-24 10:03:25366
367 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs()
368 : profile_->GetPrefs();
369 std::string browser_pref;
[email protected]0d3e4a22011-06-23 19:02:52370 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid;
[email protected]598bbcc2011-02-24 10:03:25371 EXTENSION_FUNCTION_VALIDATE(
372 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
373 pref_key, &browser_pref, &permission));
[email protected]0d3e4a22011-06-23 19:02:52374 if (!GetExtension()->HasAPIPermission(permission)) {
[email protected]fa0624262011-06-09 14:17:38375 error_ = ExtensionErrorUtils::FormatErrorMessage(
376 keys::kPermissionErrorMessage, pref_key);
[email protected]598bbcc2011-02-24 10:03:25377 return false;
378 }
[email protected]9a28f132011-02-24 21:15:16379
[email protected]598bbcc2011-02-24 10:03:25380 const PrefService::Preference* pref =
381 prefs->FindPreference(browser_pref.c_str());
382 CHECK(pref);
[email protected]118de7892011-03-16 13:31:40383 std::string level_of_control =
384 GetLevelOfControl(profile_, extension_id(), browser_pref, incognito);
[email protected]9a28f132011-02-24 21:15:16385
386 scoped_ptr<DictionaryValue> result(new DictionaryValue);
[email protected]3e3342692011-03-15 12:03:27387 PrefTransformerInterface* transformer =
388 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
389 result->Set(kValue, transformer->BrowserToExtensionPref(pref->GetValue()));
[email protected]fa0624262011-06-09 14:17:38390 result->SetString(kLevelOfControl, level_of_control);
[email protected]c0793562011-03-09 15:31:03391 if (incognito) {
392 ExtensionPrefs* ep = profile_->GetExtensionService()->extension_prefs();
[email protected]fa0624262011-06-09 14:17:38393 result->SetBoolean(kIncognitoSpecific,
394 ep->HasIncognitoPrefValue(browser_pref));
[email protected]c0793562011-03-09 15:31:03395 }
[email protected]9a28f132011-02-24 21:15:16396 result_.reset(result.release());
[email protected]598bbcc2011-02-24 10:03:25397 return true;
398}
399
400SetPreferenceFunction::~SetPreferenceFunction() { }
401
402bool SetPreferenceFunction::RunImpl() {
403 std::string pref_key;
404 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
405 DictionaryValue* details = NULL;
406 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
407
408 Value* value = NULL;
[email protected]c0793562011-03-09 15:31:03409 EXTENSION_FUNCTION_VALIDATE(details->Get(kValue, &value));
[email protected]598bbcc2011-02-24 10:03:25410
[email protected]fa0624262011-06-09 14:17:38411 ExtensionPrefsScope scope = kExtensionPrefsScopeRegular;
412 if (details->HasKey(keys::kScopeKey)) {
413 std::string scope_str;
414 EXTENSION_FUNCTION_VALIDATE(
415 details->GetString(keys::kScopeKey, &scope_str));
[email protected]8b001f32011-05-25 19:03:23416
[email protected]fa0624262011-06-09 14:17:38417 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope));
418 }
[email protected]c0793562011-03-09 15:31:03419
[email protected]dece9a62011-06-07 17:38:59420 bool incognito = (scope == kExtensionPrefsScopeIncognitoPersistent ||
421 scope == kExtensionPrefsScopeIncognitoSessionOnly);
[email protected]9783c162011-05-25 21:45:51422 if (incognito) {
423 // Regular profiles can't access incognito unless include_incognito is true.
424 if (!profile()->IsOffTheRecord() && !include_incognito()) {
[email protected]fa0624262011-06-09 14:17:38425 error_ = keys::kIncognitoErrorMessage;
[email protected]9783c162011-05-25 21:45:51426 return false;
427 }
428 } else {
429 // Incognito profiles can't access regular mode ever, they only exist in
430 // split mode.
431 if (profile()->IsOffTheRecord()) {
432 error_ = "Can't modify regular settings from an incognito context.";
433 return false;
434 }
[email protected]c0793562011-03-09 15:31:03435 }
[email protected]598bbcc2011-02-24 10:03:25436
[email protected]dece9a62011-06-07 17:38:59437 if (scope == kExtensionPrefsScopeIncognitoSessionOnly &&
[email protected]31685742011-05-25 23:01:56438 !profile_->HasOffTheRecordProfile()) {
[email protected]fa0624262011-06-09 14:17:38439 error_ = keys::kIncognitoSessionOnlyErrorMessage;
[email protected]d20e8ce2011-05-25 23:54:25440 return false;
441 }
442
[email protected]598bbcc2011-02-24 10:03:25443 std::string browser_pref;
[email protected]0d3e4a22011-06-23 19:02:52444 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid;
[email protected]598bbcc2011-02-24 10:03:25445 EXTENSION_FUNCTION_VALIDATE(
446 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
447 pref_key, &browser_pref, &permission));
[email protected]0d3e4a22011-06-23 19:02:52448 if (!GetExtension()->HasAPIPermission(permission)) {
[email protected]fa0624262011-06-09 14:17:38449 error_ = ExtensionErrorUtils::FormatErrorMessage(
450 keys::kPermissionErrorMessage, pref_key);
[email protected]598bbcc2011-02-24 10:03:25451 return false;
452 }
453 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs();
454 const PrefService::Preference* pref =
455 prefs->pref_service()->FindPreference(browser_pref.c_str());
456 CHECK(pref);
457 EXTENSION_FUNCTION_VALIDATE(value->GetType() == pref->GetType());
[email protected]3e3342692011-03-15 12:03:27458 PrefTransformerInterface* transformer =
459 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref);
460 std::string error;
[email protected]ca943e72011-05-03 16:58:04461 bool bad_message = false;
462 Value* browserPrefValue =
463 transformer->ExtensionToBrowserPref(value, &error, &bad_message);
[email protected]3e3342692011-03-15 12:03:27464 if (!browserPrefValue) {
465 error_ = error;
[email protected]ca943e72011-05-03 16:58:04466 bad_message_ = bad_message;
[email protected]3e3342692011-03-15 12:03:27467 return false;
468 }
[email protected]598bbcc2011-02-24 10:03:25469 prefs->SetExtensionControlledPref(extension_id(),
470 browser_pref,
[email protected]9783c162011-05-25 21:45:51471 scope,
[email protected]3e3342692011-03-15 12:03:27472 browserPrefValue);
[email protected]598bbcc2011-02-24 10:03:25473 return true;
474}
[email protected]c433bcb2011-02-24 13:10:27475
476ClearPreferenceFunction::~ClearPreferenceFunction() { }
477
478bool ClearPreferenceFunction::RunImpl() {
479 std::string pref_key;
480 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key));
481 DictionaryValue* details = NULL;
482 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details));
483
[email protected]fa0624262011-06-09 14:17:38484 ExtensionPrefsScope scope = kExtensionPrefsScopeRegular;
485 if (details->HasKey(keys::kScopeKey)) {
486 std::string scope_str;
487 EXTENSION_FUNCTION_VALIDATE(
488 details->GetString(keys::kScopeKey, &scope_str));
[email protected]8b001f32011-05-25 19:03:23489
[email protected]fa0624262011-06-09 14:17:38490 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope));
491 }
[email protected]c0793562011-03-09 15:31:03492
[email protected]dece9a62011-06-07 17:38:59493 bool incognito = (scope == kExtensionPrefsScopeIncognitoPersistent ||
494 scope == kExtensionPrefsScopeIncognitoSessionOnly);
[email protected]9783c162011-05-25 21:45:51495 if (incognito) {
496 // We don't check incognito permissions here, as an extension should be
497 // always allowed to clear its own settings.
498 } else {
499 // Incognito profiles can't access regular mode ever, they only exist in
500 // split mode.
501 if (profile()->IsOffTheRecord()) {
502 error_ = "Can't modify regular settings from an incognito context.";
503 return false;
504 }
505 }
[email protected]c433bcb2011-02-24 13:10:27506
507 std::string browser_pref;
[email protected]0d3e4a22011-06-23 19:02:52508 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid;
[email protected]c433bcb2011-02-24 13:10:27509 EXTENSION_FUNCTION_VALIDATE(
510 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
511 pref_key, &browser_pref, &permission));
[email protected]0d3e4a22011-06-23 19:02:52512 if (!GetExtension()->HasAPIPermission(permission)) {
[email protected]fa0624262011-06-09 14:17:38513 error_ = ExtensionErrorUtils::FormatErrorMessage(
514 keys::kPermissionErrorMessage, pref_key);
[email protected]c433bcb2011-02-24 13:10:27515 return false;
516 }
517 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs();
[email protected]9783c162011-05-25 21:45:51518 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, scope);
[email protected]c433bcb2011-02-24 13:10:27519 return true;
520}