OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
Aaron Boodman
2011/11/28 19:32:44
Can you file one or more bugs for yourself to fix
battre
2011/11/28 20:23:16
I will do that, though I am pretty sad seeing that
Bernhard Bauer
2011/11/29 10:00:01
If we want to move this outside of chrome/browser/
| |
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" |
11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
12 #include "base/stringprintf.h" | 12 #include "base/stringprintf.h" |
13 #include "base/values.h" | 13 #include "base/values.h" |
14 #include "chrome/browser/extensions/extension_event_router.h" | 14 #include "chrome/browser/extensions/extension_event_router.h" |
15 #include "chrome/browser/extensions/extension_preference_api_constants.h" | 15 #include "chrome/browser/extensions/extension_preference_api_constants.h" |
16 #include "chrome/browser/extensions/extension_preference_helpers.h" | 16 #include "chrome/browser/extensions/extension_preference_helpers.h" |
17 #include "chrome/browser/extensions/extension_prefs.h" | 17 #include "chrome/browser/extensions/extension_prefs.h" |
18 #include "chrome/browser/extensions/extension_prefs_scope.h" | 18 #include "chrome/browser/extensions/extension_prefs_scope.h" |
19 #include "chrome/browser/extensions/extension_proxy_api.h" | 19 #include "chrome/browser/extensions/extension_proxy_api.h" |
20 #include "chrome/browser/extensions/extension_service.h" | 20 #include "chrome/browser/extensions/extension_service.h" |
21 #include "chrome/browser/extensions/extension_system_api.h" | |
21 #include "chrome/browser/profiles/profile.h" | 22 #include "chrome/browser/profiles/profile.h" |
22 #include "chrome/common/chrome_notification_types.h" | 23 #include "chrome/common/chrome_notification_types.h" |
23 #include "chrome/common/extensions/extension_error_utils.h" | 24 #include "chrome/common/extensions/extension_error_utils.h" |
24 #include "chrome/common/extensions/extension_permission_set.h" | 25 #include "chrome/common/extensions/extension_permission_set.h" |
25 #include "chrome/common/pref_names.h" | 26 #include "chrome/common/pref_names.h" |
26 #include "content/public/browser/notification_details.h" | 27 #include "content/public/browser/notification_details.h" |
27 #include "content/public/browser/notification_source.h" | 28 #include "content/public/browser/notification_source.h" |
28 | 29 |
29 namespace { | 30 namespace { |
30 | 31 |
31 struct PrefMappingEntry { | 32 struct PrefMappingEntry { |
33 // Name of the preference referenced by extension_api.json. | |
32 const char* extension_pref; | 34 const char* extension_pref; |
35 | |
36 // Name of the preference in the PrefStores. | |
33 const char* browser_pref; | 37 const char* browser_pref; |
38 | |
39 // Permission required to access this preference. | |
40 // Use ExtensionAPIPermission::kInvalid for |permission| to express that no | |
41 // permission is necessary. | |
34 ExtensionAPIPermission::ID permission; | 42 ExtensionAPIPermission::ID permission; |
35 }; | 43 }; |
36 | 44 |
37 const char kNotControllable[] = "not_controllable"; | 45 const char kNotControllable[] = "not_controllable"; |
38 const char kControlledByOtherExtensions[] = "controlled_by_other_extensions"; | 46 const char kControlledByOtherExtensions[] = "controlled_by_other_extensions"; |
39 const char kControllableByThisExtension[] = "controllable_by_this_extension"; | 47 const char kControllableByThisExtension[] = "controllable_by_this_extension"; |
40 const char kControlledByThisExtension[] = "controlled_by_this_extension"; | 48 const char kControlledByThisExtension[] = "controlled_by_this_extension"; |
41 | 49 |
42 const char kIncognitoSpecific[] = "incognitoSpecific"; | 50 const char kIncognitoSpecific[] = "incognitoSpecific"; |
43 const char kLevelOfControl[] = "levelOfControl"; | 51 const char kLevelOfControl[] = "levelOfControl"; |
44 const char kValue[] = "value"; | 52 const char kValue[] = "value"; |
45 | 53 |
46 const char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange"; | 54 const char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange"; |
47 | 55 |
56 const char* kReadOnlyPrefs[] = { | |
Aaron Boodman
2011/11/28 19:32:44
Does it really make sense to overload the content
battre
2011/11/28 20:23:16
We lose two things:
- subscription to changes (the
| |
57 prefs::kIncognitoModeAvailability | |
58 }; | |
59 | |
48 PrefMappingEntry kPrefMapping[] = { | 60 PrefMappingEntry kPrefMapping[] = { |
49 { "alternateErrorPagesEnabled", | 61 { "alternateErrorPagesEnabled", |
50 prefs::kAlternateErrorPagesEnabled, | 62 prefs::kAlternateErrorPagesEnabled, |
51 ExtensionAPIPermission::kExperimental | 63 ExtensionAPIPermission::kExperimental |
52 }, | 64 }, |
53 { "autofillEnabled", | 65 { "autofillEnabled", |
54 prefs::kAutofillEnabled, | 66 prefs::kAutofillEnabled, |
55 ExtensionAPIPermission::kExperimental | 67 ExtensionAPIPermission::kExperimental |
56 }, | 68 }, |
57 { "hyperlinkAuditingEnabled", | 69 { "hyperlinkAuditingEnabled", |
(...skipping 29 matching lines...) Expand all Loading... | |
87 prefs::kSafeBrowsingEnabled, | 99 prefs::kSafeBrowsingEnabled, |
88 ExtensionAPIPermission::kExperimental | 100 ExtensionAPIPermission::kExperimental |
89 }, | 101 }, |
90 { "thirdPartyCookiesAllowed", | 102 { "thirdPartyCookiesAllowed", |
91 prefs::kBlockThirdPartyCookies, | 103 prefs::kBlockThirdPartyCookies, |
92 ExtensionAPIPermission::kExperimental | 104 ExtensionAPIPermission::kExperimental |
93 }, | 105 }, |
94 { "translationServiceEnabled", | 106 { "translationServiceEnabled", |
95 prefs::kEnableTranslate, | 107 prefs::kEnableTranslate, |
96 ExtensionAPIPermission::kExperimental | 108 ExtensionAPIPermission::kExperimental |
109 }, | |
110 { "incognitoModeAvailability", | |
111 prefs::kIncognitoModeAvailability, | |
112 ExtensionAPIPermission::kInvalid // kInvalid = none required. | |
97 } | 113 } |
98 }; | 114 }; |
99 | 115 |
100 class IdentityPrefTransformer : public PrefTransformerInterface { | 116 class IdentityPrefTransformer : public PrefTransformerInterface { |
101 public: | 117 public: |
102 virtual Value* ExtensionToBrowserPref(const Value* extension_pref, | 118 virtual Value* ExtensionToBrowserPref(const Value* extension_pref, |
103 std::string* error, | 119 std::string* error, |
104 bool* bad_message) { | 120 bool* bad_message) { |
105 return extension_pref->DeepCopy(); | 121 return extension_pref->DeepCopy(); |
106 } | 122 } |
(...skipping 17 matching lines...) Expand all Loading... | |
124 | 140 |
125 private: | 141 private: |
126 static Value* InvertBooleanValue(const Value* value) { | 142 static Value* InvertBooleanValue(const Value* value) { |
127 bool bool_value = false; | 143 bool bool_value = false; |
128 bool result = value->GetAsBoolean(&bool_value); | 144 bool result = value->GetAsBoolean(&bool_value); |
129 DCHECK(result); | 145 DCHECK(result); |
130 return Value::CreateBooleanValue(!bool_value); | 146 return Value::CreateBooleanValue(!bool_value); |
131 } | 147 } |
132 }; | 148 }; |
133 | 149 |
150 // Checks whether an extension has a specific permission but considers | |
151 // ExtensionAPIPermission::kInvalid a wildcard that is possessed by every | |
152 // extension. | |
153 bool HasAPIPermission(const Extension* extension, | |
154 ExtensionAPIPermission::ID permission) { | |
155 return permission == ExtensionAPIPermission::kInvalid || | |
156 extension->HasAPIPermission(permission); | |
157 } | |
158 | |
159 bool IsReadOnlyPreference(const std::string& browser_pref) { | |
160 for (size_t i = 0; i < arraysize(kReadOnlyPrefs); ++i) { | |
161 if (kReadOnlyPrefs[i] == browser_pref) | |
162 return true; | |
163 } | |
164 return false; | |
165 } | |
166 | |
134 // Returns a string constant (defined in the API) indicating the level of | 167 // Returns a string constant (defined in the API) indicating the level of |
135 // control this extension has over the specified preference. | 168 // control this extension has over the specified preference. |
136 const char* GetLevelOfControl( | 169 const char* GetLevelOfControl( |
137 Profile* profile, | 170 Profile* profile, |
138 const std::string& extension_id, | 171 const std::string& extension_id, |
139 const std::string& browser_pref, | 172 const std::string& browser_pref, |
140 bool incognito) { | 173 bool incognito) { |
141 PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs() | 174 PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs() |
142 : profile->GetPrefs(); | 175 : profile->GetPrefs(); |
143 const PrefService::Preference* pref = | 176 const PrefService::Preference* pref = |
144 prefs->FindPreference(browser_pref.c_str()); | 177 prefs->FindPreference(browser_pref.c_str()); |
145 CHECK(pref); | 178 CHECK(pref); |
146 ExtensionPrefs* ep = profile->GetExtensionService()->extension_prefs(); | 179 ExtensionPrefs* ep = profile->GetExtensionService()->extension_prefs(); |
147 | 180 |
181 if (IsReadOnlyPreference(browser_pref)) | |
182 return kNotControllable; | |
183 | |
148 if (!pref->IsExtensionModifiable()) | 184 if (!pref->IsExtensionModifiable()) |
149 return kNotControllable; | 185 return kNotControllable; |
150 | 186 |
151 if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito)) | 187 if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito)) |
152 return kControlledByThisExtension; | 188 return kControlledByThisExtension; |
153 | 189 |
154 if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito)) | 190 if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito)) |
155 return kControllableByThisExtension; | 191 return kControllableByThisExtension; |
156 | 192 |
157 return kControlledByOtherExtensions; | 193 return kControlledByOtherExtensions; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
209 std::string event_name = | 245 std::string event_name = |
210 base::StringPrintf(kOnPrefChangeFormat, | 246 base::StringPrintf(kOnPrefChangeFormat, |
211 kPrefMapping[i].extension_pref); | 247 kPrefMapping[i].extension_pref); |
212 event_mapping_[kPrefMapping[i].browser_pref] = | 248 event_mapping_[kPrefMapping[i].browser_pref] = |
213 std::make_pair(event_name, kPrefMapping[i].permission); | 249 std::make_pair(event_name, kPrefMapping[i].permission); |
214 } | 250 } |
215 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size()); | 251 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size()); |
216 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size()); | 252 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size()); |
217 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer()); | 253 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer()); |
218 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies, | 254 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies, |
219 new InvertBooleanTransformer()); | 255 new InvertBooleanTransformer()); |
256 RegisterPrefTransformer(prefs::kIncognitoModeAvailability, | |
257 new IncognitoModeAvailabilityTransformer()); | |
220 } | 258 } |
221 | 259 |
222 ~PrefMapping() { | 260 ~PrefMapping() { |
223 STLDeleteContainerPairSecondPointers(transformers_.begin(), | 261 STLDeleteContainerPairSecondPointers(transformers_.begin(), |
224 transformers_.end()); | 262 transformers_.end()); |
225 } | 263 } |
226 | 264 |
227 void RegisterPrefTransformer(const std::string& browser_pref, | 265 void RegisterPrefTransformer(const std::string& browser_pref, |
228 PrefTransformerInterface* transformer) { | 266 PrefTransformerInterface* transformer) { |
229 DCHECK_EQ(0u, transformers_.count(browser_pref)) << | 267 DCHECK_EQ(0u, transformers_.count(browser_pref)) << |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
308 | 346 |
309 ExtensionEventRouter* router = profile_->GetExtensionEventRouter(); | 347 ExtensionEventRouter* router = profile_->GetExtensionEventRouter(); |
310 if (!router || !router->HasEventListener(event_name)) | 348 if (!router || !router->HasEventListener(event_name)) |
311 return; | 349 return; |
312 const ExtensionList* extensions = extension_service->extensions(); | 350 const ExtensionList* extensions = extension_service->extensions(); |
313 for (ExtensionList::const_iterator it = extensions->begin(); | 351 for (ExtensionList::const_iterator it = extensions->begin(); |
314 it != extensions->end(); ++it) { | 352 it != extensions->end(); ++it) { |
315 std::string extension_id = (*it)->id(); | 353 std::string extension_id = (*it)->id(); |
316 // TODO(bauerb): Only iterate over registered event listeners. | 354 // TODO(bauerb): Only iterate over registered event listeners. |
317 if (router->ExtensionHasEventListener(extension_id, event_name) && | 355 if (router->ExtensionHasEventListener(extension_id, event_name) && |
318 (*it)->HasAPIPermission(permission) && | 356 HasAPIPermission(it->get(), permission) && |
319 (!incognito || extension_service->CanCrossIncognito(*it))) { | 357 (!incognito || extension_service->CanCrossIncognito(*it))) { |
320 std::string level_of_control = | 358 std::string level_of_control = |
321 GetLevelOfControl(profile_, extension_id, browser_pref, incognito); | 359 GetLevelOfControl(profile_, extension_id, browser_pref, incognito); |
322 dict->SetString(kLevelOfControl, level_of_control); | 360 dict->SetString(kLevelOfControl, level_of_control); |
323 | 361 |
324 std::string json_args; | 362 std::string json_args; |
325 base::JSONWriter::Write(&args, false, &json_args); | 363 base::JSONWriter::Write(&args, false, &json_args); |
326 | 364 |
327 DispatchEvent(extension_id, event_name, json_args); | 365 DispatchEvent(extension_id, event_name, json_args); |
328 } | 366 } |
(...skipping 28 matching lines...) Expand all Loading... | |
357 return false; | 395 return false; |
358 } | 396 } |
359 | 397 |
360 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs() | 398 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs() |
361 : profile_->GetPrefs(); | 399 : profile_->GetPrefs(); |
362 std::string browser_pref; | 400 std::string browser_pref; |
363 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; | 401 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; |
364 EXTENSION_FUNCTION_VALIDATE( | 402 EXTENSION_FUNCTION_VALIDATE( |
365 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( | 403 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( |
366 pref_key, &browser_pref, &permission)); | 404 pref_key, &browser_pref, &permission)); |
367 if (!GetExtension()->HasAPIPermission(permission)) { | 405 if (!HasAPIPermission(GetExtension(), permission)) { |
368 error_ = ExtensionErrorUtils::FormatErrorMessage( | 406 error_ = ExtensionErrorUtils::FormatErrorMessage( |
369 keys::kPermissionErrorMessage, pref_key); | 407 keys::kPermissionErrorMessage, pref_key); |
370 return false; | 408 return false; |
371 } | 409 } |
372 | 410 |
373 const PrefService::Preference* pref = | 411 const PrefService::Preference* pref = |
374 prefs->FindPreference(browser_pref.c_str()); | 412 prefs->FindPreference(browser_pref.c_str()); |
375 CHECK(pref); | 413 CHECK(pref); |
376 std::string level_of_control = | 414 std::string level_of_control = |
377 GetLevelOfControl(profile_, extension_id(), browser_pref, incognito); | 415 GetLevelOfControl(profile_, extension_id(), browser_pref, incognito); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
431 !profile_->HasOffTheRecordProfile()) { | 469 !profile_->HasOffTheRecordProfile()) { |
432 error_ = keys::kIncognitoSessionOnlyErrorMessage; | 470 error_ = keys::kIncognitoSessionOnlyErrorMessage; |
433 return false; | 471 return false; |
434 } | 472 } |
435 | 473 |
436 std::string browser_pref; | 474 std::string browser_pref; |
437 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; | 475 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; |
438 EXTENSION_FUNCTION_VALIDATE( | 476 EXTENSION_FUNCTION_VALIDATE( |
439 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( | 477 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( |
440 pref_key, &browser_pref, &permission)); | 478 pref_key, &browser_pref, &permission)); |
441 if (!GetExtension()->HasAPIPermission(permission)) { | 479 if (!HasAPIPermission(GetExtension(), permission)) { |
442 error_ = ExtensionErrorUtils::FormatErrorMessage( | 480 error_ = ExtensionErrorUtils::FormatErrorMessage( |
443 keys::kPermissionErrorMessage, pref_key); | 481 keys::kPermissionErrorMessage, pref_key); |
444 return false; | 482 return false; |
445 } | 483 } |
484 | |
485 if (IsReadOnlyPreference(browser_pref)) { | |
486 error_ = ExtensionErrorUtils::FormatErrorMessage( | |
487 keys::kCannotModifyReadOnlyMessage, pref_key); | |
488 return false; | |
489 } | |
490 | |
446 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); | 491 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); |
447 const PrefService::Preference* pref = | 492 const PrefService::Preference* pref = |
448 prefs->pref_service()->FindPreference(browser_pref.c_str()); | 493 prefs->pref_service()->FindPreference(browser_pref.c_str()); |
449 CHECK(pref); | 494 CHECK(pref); |
450 EXTENSION_FUNCTION_VALIDATE(value->GetType() == pref->GetType()); | 495 EXTENSION_FUNCTION_VALIDATE(value->GetType() == pref->GetType()); |
451 PrefTransformerInterface* transformer = | 496 PrefTransformerInterface* transformer = |
452 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); | 497 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); |
453 std::string error; | 498 std::string error; |
454 bool bad_message = false; | 499 bool bad_message = false; |
455 Value* browserPrefValue = | 500 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."; | 540 error_ = "Can't modify regular settings from an incognito context."; |
496 return false; | 541 return false; |
497 } | 542 } |
498 } | 543 } |
499 | 544 |
500 std::string browser_pref; | 545 std::string browser_pref; |
501 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; | 546 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; |
502 EXTENSION_FUNCTION_VALIDATE( | 547 EXTENSION_FUNCTION_VALIDATE( |
503 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( | 548 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( |
504 pref_key, &browser_pref, &permission)); | 549 pref_key, &browser_pref, &permission)); |
505 if (!GetExtension()->HasAPIPermission(permission)) { | 550 if (!HasAPIPermission(GetExtension(), permission)) { |
506 error_ = ExtensionErrorUtils::FormatErrorMessage( | 551 error_ = ExtensionErrorUtils::FormatErrorMessage( |
507 keys::kPermissionErrorMessage, pref_key); | 552 keys::kPermissionErrorMessage, pref_key); |
508 return false; | 553 return false; |
509 } | 554 } |
555 | |
556 if (IsReadOnlyPreference(browser_pref)) { | |
557 error_ = ExtensionErrorUtils::FormatErrorMessage( | |
558 keys::kCannotModifyReadOnlyMessage, pref_key); | |
559 return false; | |
560 } | |
561 | |
510 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); | 562 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); |
511 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, scope); | 563 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, scope); |
512 return true; | 564 return true; |
513 } | 565 } |
OLD | NEW |