OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_preference_api.h" | 5 #include "chrome/browser/extensions/extension_preference_api.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "base/memory/singleton.h" | 10 #include "base/memory/singleton.h" |
(...skipping 11 matching lines...) Expand all Loading... | |
22 #include "chrome/common/chrome_notification_types.h" | 22 #include "chrome/common/chrome_notification_types.h" |
23 #include "chrome/common/extensions/extension_error_utils.h" | 23 #include "chrome/common/extensions/extension_error_utils.h" |
24 #include "chrome/common/extensions/extension_permission_set.h" | 24 #include "chrome/common/extensions/extension_permission_set.h" |
25 #include "chrome/common/pref_names.h" | 25 #include "chrome/common/pref_names.h" |
26 #include "content/public/browser/notification_details.h" | 26 #include "content/public/browser/notification_details.h" |
27 #include "content/public/browser/notification_source.h" | 27 #include "content/public/browser/notification_source.h" |
28 | 28 |
29 namespace { | 29 namespace { |
30 | 30 |
31 struct PrefMappingEntry { | 31 struct PrefMappingEntry { |
32 // Name of the preference referenced by extension_api.json. | |
32 const char* extension_pref; | 33 const char* extension_pref; |
34 | |
35 // Name of the preference in the PrefStores. | |
33 const char* browser_pref; | 36 const char* browser_pref; |
37 | |
38 // Permission required to access this preference. | |
39 // Use ExtensionAPIPermission::kInvalid for |permission| to express that no | |
40 // permission is necessary. | |
34 ExtensionAPIPermission::ID permission; | 41 ExtensionAPIPermission::ID permission; |
35 }; | 42 }; |
36 | 43 |
37 const char kNotControllable[] = "not_controllable"; | 44 const char kNotControllable[] = "not_controllable"; |
38 const char kControlledByOtherExtensions[] = "controlled_by_other_extensions"; | 45 const char kControlledByOtherExtensions[] = "controlled_by_other_extensions"; |
39 const char kControllableByThisExtension[] = "controllable_by_this_extension"; | 46 const char kControllableByThisExtension[] = "controllable_by_this_extension"; |
40 const char kControlledByThisExtension[] = "controlled_by_this_extension"; | 47 const char kControlledByThisExtension[] = "controlled_by_this_extension"; |
41 | 48 |
42 const char kIncognitoSpecific[] = "incognitoSpecific"; | 49 const char kIncognitoSpecific[] = "incognitoSpecific"; |
43 const char kLevelOfControl[] = "levelOfControl"; | 50 const char kLevelOfControl[] = "levelOfControl"; |
44 const char kValue[] = "value"; | 51 const char kValue[] = "value"; |
45 | 52 |
46 const char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange"; | 53 const char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange"; |
47 | 54 |
55 const char* kReadOnlyPrefs[] = { | |
56 prefs::kIncognitoModeAvailability | |
57 }; | |
58 | |
48 PrefMappingEntry kPrefMapping[] = { | 59 PrefMappingEntry kPrefMapping[] = { |
49 { "alternateErrorPagesEnabled", | 60 { "alternateErrorPagesEnabled", |
50 prefs::kAlternateErrorPagesEnabled, | 61 prefs::kAlternateErrorPagesEnabled, |
51 ExtensionAPIPermission::kExperimental | 62 ExtensionAPIPermission::kExperimental |
52 }, | 63 }, |
53 { "autofillEnabled", | 64 { "autofillEnabled", |
54 prefs::kAutofillEnabled, | 65 prefs::kAutofillEnabled, |
55 ExtensionAPIPermission::kExperimental | 66 ExtensionAPIPermission::kExperimental |
56 }, | 67 }, |
57 { "hyperlinkAuditingEnabled", | 68 { "hyperlinkAuditingEnabled", |
(...skipping 29 matching lines...) Expand all Loading... | |
87 prefs::kSafeBrowsingEnabled, | 98 prefs::kSafeBrowsingEnabled, |
88 ExtensionAPIPermission::kExperimental | 99 ExtensionAPIPermission::kExperimental |
89 }, | 100 }, |
90 { "thirdPartyCookiesAllowed", | 101 { "thirdPartyCookiesAllowed", |
91 prefs::kBlockThirdPartyCookies, | 102 prefs::kBlockThirdPartyCookies, |
92 ExtensionAPIPermission::kExperimental | 103 ExtensionAPIPermission::kExperimental |
93 }, | 104 }, |
94 { "translationServiceEnabled", | 105 { "translationServiceEnabled", |
95 prefs::kEnableTranslate, | 106 prefs::kEnableTranslate, |
96 ExtensionAPIPermission::kExperimental | 107 ExtensionAPIPermission::kExperimental |
108 }, | |
109 { "incognitoModeAvailability", | |
110 prefs::kIncognitoModeAvailability, | |
111 ExtensionAPIPermission::kInvalid // kInvalid = none required. | |
97 } | 112 } |
98 }; | 113 }; |
99 | 114 |
115 // Maps prefs::kIncognitoModeAvailability values (0 = enabled, ...) | |
116 // to strings exposed to extensions. | |
117 const char* kIncognitoModeAvailabilityStrings[] = { | |
118 "enabled", | |
119 "disabled", | |
120 "forced" | |
121 }; | |
122 | |
100 class IdentityPrefTransformer : public PrefTransformerInterface { | 123 class IdentityPrefTransformer : public PrefTransformerInterface { |
101 public: | 124 public: |
102 virtual Value* ExtensionToBrowserPref(const Value* extension_pref, | 125 virtual Value* ExtensionToBrowserPref(const Value* extension_pref, |
103 std::string* error, | 126 std::string* error, |
104 bool* bad_message) { | 127 bool* bad_message) { |
105 return extension_pref->DeepCopy(); | 128 return extension_pref->DeepCopy(); |
106 } | 129 } |
107 | 130 |
108 virtual Value* BrowserToExtensionPref(const Value* browser_pref) { | 131 virtual Value* BrowserToExtensionPref(const Value* browser_pref) { |
109 return browser_pref->DeepCopy(); | 132 return browser_pref->DeepCopy(); |
(...skipping 14 matching lines...) Expand all Loading... | |
124 | 147 |
125 private: | 148 private: |
126 static Value* InvertBooleanValue(const Value* value) { | 149 static Value* InvertBooleanValue(const Value* value) { |
127 bool bool_value = false; | 150 bool bool_value = false; |
128 bool result = value->GetAsBoolean(&bool_value); | 151 bool result = value->GetAsBoolean(&bool_value); |
129 DCHECK(result); | 152 DCHECK(result); |
130 return Value::CreateBooleanValue(!bool_value); | 153 return Value::CreateBooleanValue(!bool_value); |
131 } | 154 } |
132 }; | 155 }; |
133 | 156 |
157 class IncognitoModeAvailabilityTransformer : public PrefTransformerInterface { | |
158 public: | |
159 virtual Value* ExtensionToBrowserPref(const Value* extension_pref, | |
160 std::string* error, | |
161 bool* bad_message) { | |
162 // We do not allow extensions to modify the IncognitoModeAvailability | |
163 // preference. Therefore, this function is never called. | |
164 NOTREACHED(); | |
165 return NULL; | |
166 } | |
167 | |
168 virtual Value* BrowserToExtensionPref(const Value* browser_pref) { | |
169 int browser_pref_value; | |
170 if (!browser_pref->GetAsInteger(&browser_pref_value) || | |
171 browser_pref_value < 0 || | |
172 browser_pref_value >= | |
173 static_cast<int>(arraysize(kIncognitoModeAvailabilityStrings))) { | |
174 return NULL; | |
175 } | |
176 return Value::CreateStringValue( | |
177 kIncognitoModeAvailabilityStrings[browser_pref_value]); | |
178 } | |
179 }; | |
180 | |
181 // Checks whether an extension has a specific permission but considers | |
182 // ExtensionAPIPermission::kInvalid a wildcard that is possessed by every | |
183 // extension. | |
184 bool HasAPIPermission(const Extension* extension, | |
185 ExtensionAPIPermission::ID permission) { | |
186 return permission == ExtensionAPIPermission::kInvalid || | |
187 extension->HasAPIPermission(permission); | |
188 } | |
189 | |
190 bool IsReadOnlyPreference(const std::string& browser_pref) { | |
191 for (size_t i = 0; i < arraysize(kReadOnlyPrefs); ++i) { | |
Bernhard Bauer
2011/11/23 15:53:57
Nit: Indent only two spaces.
battre
2011/11/23 15:56:05
Done.
| |
192 if (kReadOnlyPrefs[i] == browser_pref) | |
193 return true; | |
194 } | |
195 return false; | |
196 } | |
197 | |
134 // Returns a string constant (defined in the API) indicating the level of | 198 // Returns a string constant (defined in the API) indicating the level of |
135 // control this extension has over the specified preference. | 199 // control this extension has over the specified preference. |
136 const char* GetLevelOfControl( | 200 const char* GetLevelOfControl( |
137 Profile* profile, | 201 Profile* profile, |
138 const std::string& extension_id, | 202 const std::string& extension_id, |
139 const std::string& browser_pref, | 203 const std::string& browser_pref, |
140 bool incognito) { | 204 bool incognito) { |
141 PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs() | 205 PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs() |
142 : profile->GetPrefs(); | 206 : profile->GetPrefs(); |
143 const PrefService::Preference* pref = | 207 const PrefService::Preference* pref = |
144 prefs->FindPreference(browser_pref.c_str()); | 208 prefs->FindPreference(browser_pref.c_str()); |
145 CHECK(pref); | 209 CHECK(pref); |
146 ExtensionPrefs* ep = profile->GetExtensionService()->extension_prefs(); | 210 ExtensionPrefs* ep = profile->GetExtensionService()->extension_prefs(); |
147 | 211 |
212 if (IsReadOnlyPreference(browser_pref)) | |
213 return kNotControllable; | |
214 | |
148 if (!pref->IsExtensionModifiable()) | 215 if (!pref->IsExtensionModifiable()) |
149 return kNotControllable; | 216 return kNotControllable; |
150 | 217 |
151 if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito)) | 218 if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito)) |
152 return kControlledByThisExtension; | 219 return kControlledByThisExtension; |
153 | 220 |
154 if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito)) | 221 if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito)) |
155 return kControllableByThisExtension; | 222 return kControllableByThisExtension; |
156 | 223 |
157 return kControlledByOtherExtensions; | 224 return kControlledByOtherExtensions; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
209 std::string event_name = | 276 std::string event_name = |
210 base::StringPrintf(kOnPrefChangeFormat, | 277 base::StringPrintf(kOnPrefChangeFormat, |
211 kPrefMapping[i].extension_pref); | 278 kPrefMapping[i].extension_pref); |
212 event_mapping_[kPrefMapping[i].browser_pref] = | 279 event_mapping_[kPrefMapping[i].browser_pref] = |
213 std::make_pair(event_name, kPrefMapping[i].permission); | 280 std::make_pair(event_name, kPrefMapping[i].permission); |
214 } | 281 } |
215 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size()); | 282 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size()); |
216 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size()); | 283 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size()); |
217 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer()); | 284 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer()); |
218 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies, | 285 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies, |
219 new InvertBooleanTransformer()); | 286 new InvertBooleanTransformer()); |
287 RegisterPrefTransformer(prefs::kIncognitoModeAvailability, | |
288 new IncognitoModeAvailabilityTransformer()); | |
220 } | 289 } |
221 | 290 |
222 ~PrefMapping() { | 291 ~PrefMapping() { |
223 STLDeleteContainerPairSecondPointers(transformers_.begin(), | 292 STLDeleteContainerPairSecondPointers(transformers_.begin(), |
224 transformers_.end()); | 293 transformers_.end()); |
225 } | 294 } |
226 | 295 |
227 void RegisterPrefTransformer(const std::string& browser_pref, | 296 void RegisterPrefTransformer(const std::string& browser_pref, |
228 PrefTransformerInterface* transformer) { | 297 PrefTransformerInterface* transformer) { |
229 DCHECK_EQ(0u, transformers_.count(browser_pref)) << | 298 DCHECK_EQ(0u, transformers_.count(browser_pref)) << |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
308 | 377 |
309 ExtensionEventRouter* router = profile_->GetExtensionEventRouter(); | 378 ExtensionEventRouter* router = profile_->GetExtensionEventRouter(); |
310 if (!router || !router->HasEventListener(event_name)) | 379 if (!router || !router->HasEventListener(event_name)) |
311 return; | 380 return; |
312 const ExtensionList* extensions = extension_service->extensions(); | 381 const ExtensionList* extensions = extension_service->extensions(); |
313 for (ExtensionList::const_iterator it = extensions->begin(); | 382 for (ExtensionList::const_iterator it = extensions->begin(); |
314 it != extensions->end(); ++it) { | 383 it != extensions->end(); ++it) { |
315 std::string extension_id = (*it)->id(); | 384 std::string extension_id = (*it)->id(); |
316 // TODO(bauerb): Only iterate over registered event listeners. | 385 // TODO(bauerb): Only iterate over registered event listeners. |
317 if (router->ExtensionHasEventListener(extension_id, event_name) && | 386 if (router->ExtensionHasEventListener(extension_id, event_name) && |
318 (*it)->HasAPIPermission(permission) && | 387 HasAPIPermission(it->get(), permission) && |
319 (!incognito || extension_service->CanCrossIncognito(*it))) { | 388 (!incognito || extension_service->CanCrossIncognito(*it))) { |
320 std::string level_of_control = | 389 std::string level_of_control = |
321 GetLevelOfControl(profile_, extension_id, browser_pref, incognito); | 390 GetLevelOfControl(profile_, extension_id, browser_pref, incognito); |
322 dict->SetString(kLevelOfControl, level_of_control); | 391 dict->SetString(kLevelOfControl, level_of_control); |
323 | 392 |
324 std::string json_args; | 393 std::string json_args; |
325 base::JSONWriter::Write(&args, false, &json_args); | 394 base::JSONWriter::Write(&args, false, &json_args); |
326 | 395 |
327 DispatchEvent(extension_id, event_name, json_args); | 396 DispatchEvent(extension_id, event_name, json_args); |
328 } | 397 } |
(...skipping 28 matching lines...) Expand all Loading... | |
357 return false; | 426 return false; |
358 } | 427 } |
359 | 428 |
360 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs() | 429 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs() |
361 : profile_->GetPrefs(); | 430 : profile_->GetPrefs(); |
362 std::string browser_pref; | 431 std::string browser_pref; |
363 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; | 432 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; |
364 EXTENSION_FUNCTION_VALIDATE( | 433 EXTENSION_FUNCTION_VALIDATE( |
365 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( | 434 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( |
366 pref_key, &browser_pref, &permission)); | 435 pref_key, &browser_pref, &permission)); |
367 if (!GetExtension()->HasAPIPermission(permission)) { | 436 if (!HasAPIPermission(GetExtension(), permission)) { |
368 error_ = ExtensionErrorUtils::FormatErrorMessage( | 437 error_ = ExtensionErrorUtils::FormatErrorMessage( |
369 keys::kPermissionErrorMessage, pref_key); | 438 keys::kPermissionErrorMessage, pref_key); |
370 return false; | 439 return false; |
371 } | 440 } |
372 | 441 |
373 const PrefService::Preference* pref = | 442 const PrefService::Preference* pref = |
374 prefs->FindPreference(browser_pref.c_str()); | 443 prefs->FindPreference(browser_pref.c_str()); |
375 CHECK(pref); | 444 CHECK(pref); |
376 std::string level_of_control = | 445 std::string level_of_control = |
377 GetLevelOfControl(profile_, extension_id(), browser_pref, incognito); | 446 GetLevelOfControl(profile_, extension_id(), browser_pref, incognito); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
431 !profile_->HasOffTheRecordProfile()) { | 500 !profile_->HasOffTheRecordProfile()) { |
432 error_ = keys::kIncognitoSessionOnlyErrorMessage; | 501 error_ = keys::kIncognitoSessionOnlyErrorMessage; |
433 return false; | 502 return false; |
434 } | 503 } |
435 | 504 |
436 std::string browser_pref; | 505 std::string browser_pref; |
437 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; | 506 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; |
438 EXTENSION_FUNCTION_VALIDATE( | 507 EXTENSION_FUNCTION_VALIDATE( |
439 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( | 508 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( |
440 pref_key, &browser_pref, &permission)); | 509 pref_key, &browser_pref, &permission)); |
441 if (!GetExtension()->HasAPIPermission(permission)) { | 510 if (!HasAPIPermission(GetExtension(), permission)) { |
442 error_ = ExtensionErrorUtils::FormatErrorMessage( | 511 error_ = ExtensionErrorUtils::FormatErrorMessage( |
443 keys::kPermissionErrorMessage, pref_key); | 512 keys::kPermissionErrorMessage, pref_key); |
444 return false; | 513 return false; |
445 } | 514 } |
515 | |
516 if (IsReadOnlyPreference(browser_pref)) { | |
517 error_ = ExtensionErrorUtils::FormatErrorMessage( | |
518 keys::kCannotModifyReadOnlyMessage, pref_key); | |
519 return false; | |
520 } | |
521 | |
446 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); | 522 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); |
447 const PrefService::Preference* pref = | 523 const PrefService::Preference* pref = |
448 prefs->pref_service()->FindPreference(browser_pref.c_str()); | 524 prefs->pref_service()->FindPreference(browser_pref.c_str()); |
449 CHECK(pref); | 525 CHECK(pref); |
450 EXTENSION_FUNCTION_VALIDATE(value->GetType() == pref->GetType()); | 526 EXTENSION_FUNCTION_VALIDATE(value->GetType() == pref->GetType()); |
451 PrefTransformerInterface* transformer = | 527 PrefTransformerInterface* transformer = |
452 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); | 528 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); |
453 std::string error; | 529 std::string error; |
454 bool bad_message = false; | 530 bool bad_message = false; |
455 Value* browserPrefValue = | 531 Value* browserPrefValue = |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
495 error_ = "Can't modify regular settings from an incognito context."; | 571 error_ = "Can't modify regular settings from an incognito context."; |
496 return false; | 572 return false; |
497 } | 573 } |
498 } | 574 } |
499 | 575 |
500 std::string browser_pref; | 576 std::string browser_pref; |
501 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; | 577 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; |
502 EXTENSION_FUNCTION_VALIDATE( | 578 EXTENSION_FUNCTION_VALIDATE( |
503 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( | 579 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( |
504 pref_key, &browser_pref, &permission)); | 580 pref_key, &browser_pref, &permission)); |
505 if (!GetExtension()->HasAPIPermission(permission)) { | 581 if (!HasAPIPermission(GetExtension(), permission)) { |
506 error_ = ExtensionErrorUtils::FormatErrorMessage( | 582 error_ = ExtensionErrorUtils::FormatErrorMessage( |
507 keys::kPermissionErrorMessage, pref_key); | 583 keys::kPermissionErrorMessage, pref_key); |
508 return false; | 584 return false; |
509 } | 585 } |
586 | |
587 if (IsReadOnlyPreference(browser_pref)) { | |
588 error_ = ExtensionErrorUtils::FormatErrorMessage( | |
589 keys::kCannotModifyReadOnlyMessage, pref_key); | |
590 return false; | |
591 } | |
592 | |
510 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); | 593 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); |
511 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, scope); | 594 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, scope); |
512 return true; | 595 return true; |
513 } | 596 } |
OLD | NEW |