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 requried to access this preference. | |
Bernhard Bauer
2011/11/23 13:03:35
Nit: "required"
battre
2011/11/23 15:43:53
Done.
| |
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 std::string extension_pref_string; | |
163 bool result = extension_pref->GetAsString(&extension_pref_string); | |
164 DCHECK(result); | |
165 for (size_t i = 0; i < arraysize(kIncognitoModeAvailabilityStrings); ++i) { | |
166 if (kIncognitoModeAvailabilityStrings[i] == extension_pref_string) | |
167 return Value::CreateIntegerValue(i); | |
168 } | |
169 *error = extension_preference_api_constants::kInvalidParameter; | |
Bernhard Bauer
2011/11/23 13:03:35
Wait, do we actually need this if the preference c
battre
2011/11/23 15:43:53
I have removed the content of this function and re
| |
170 *bad_message = true; | |
171 return NULL; | |
172 } | |
173 | |
174 virtual Value* BrowserToExtensionPref(const Value* browser_pref) { | |
175 int browser_pref_value; | |
176 if (!browser_pref->GetAsInteger(&browser_pref_value) || | |
177 0 < browser_pref_value || | |
178 browser_pref_value >= | |
179 static_cast<int>(arraysize(kIncognitoModeAvailabilityStrings))) { | |
180 return NULL; | |
181 } | |
182 return Value::CreateStringValue( | |
183 kIncognitoModeAvailabilityStrings[browser_pref_value]); | |
184 } | |
185 }; | |
186 | |
134 // Returns a string constant (defined in the API) indicating the level of | 187 // Returns a string constant (defined in the API) indicating the level of |
135 // control this extension has over the specified preference. | 188 // control this extension has over the specified preference. |
136 const char* GetLevelOfControl( | 189 const char* GetLevelOfControl( |
137 Profile* profile, | 190 Profile* profile, |
138 const std::string& extension_id, | 191 const std::string& extension_id, |
139 const std::string& browser_pref, | 192 const std::string& browser_pref, |
140 bool incognito) { | 193 bool incognito) { |
141 PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs() | 194 PrefService* prefs = incognito ? profile->GetOffTheRecordPrefs() |
142 : profile->GetPrefs(); | 195 : profile->GetPrefs(); |
143 const PrefService::Preference* pref = | 196 const PrefService::Preference* pref = |
144 prefs->FindPreference(browser_pref.c_str()); | 197 prefs->FindPreference(browser_pref.c_str()); |
145 CHECK(pref); | 198 CHECK(pref); |
146 ExtensionPrefs* ep = profile->GetExtensionService()->extension_prefs(); | 199 ExtensionPrefs* ep = profile->GetExtensionService()->extension_prefs(); |
147 | 200 |
201 // Prevent changing read-only preferences. | |
202 for (size_t i = 0; i < arraysize(kReadOnlyPrefs); ++i) { | |
203 if (kReadOnlyPrefs[i] == browser_pref) | |
204 return kNotControllable; | |
205 } | |
206 | |
148 if (!pref->IsExtensionModifiable()) | 207 if (!pref->IsExtensionModifiable()) |
149 return kNotControllable; | 208 return kNotControllable; |
150 | 209 |
151 if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito)) | 210 if (ep->DoesExtensionControlPref(extension_id, browser_pref, incognito)) |
152 return kControlledByThisExtension; | 211 return kControlledByThisExtension; |
153 | 212 |
154 if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito)) | 213 if (ep->CanExtensionControlPref(extension_id, browser_pref, incognito)) |
155 return kControllableByThisExtension; | 214 return kControllableByThisExtension; |
156 | 215 |
157 return kControlledByOtherExtensions; | 216 return kControlledByOtherExtensions; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
209 std::string event_name = | 268 std::string event_name = |
210 base::StringPrintf(kOnPrefChangeFormat, | 269 base::StringPrintf(kOnPrefChangeFormat, |
211 kPrefMapping[i].extension_pref); | 270 kPrefMapping[i].extension_pref); |
212 event_mapping_[kPrefMapping[i].browser_pref] = | 271 event_mapping_[kPrefMapping[i].browser_pref] = |
213 std::make_pair(event_name, kPrefMapping[i].permission); | 272 std::make_pair(event_name, kPrefMapping[i].permission); |
214 } | 273 } |
215 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size()); | 274 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size()); |
216 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size()); | 275 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size()); |
217 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer()); | 276 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer()); |
218 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies, | 277 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies, |
219 new InvertBooleanTransformer()); | 278 new InvertBooleanTransformer()); |
279 RegisterPrefTransformer(prefs::kIncognitoModeAvailability, | |
280 new IncognitoModeAvailabilityTransformer()); | |
220 } | 281 } |
221 | 282 |
222 ~PrefMapping() { | 283 ~PrefMapping() { |
223 STLDeleteContainerPairSecondPointers(transformers_.begin(), | 284 STLDeleteContainerPairSecondPointers(transformers_.begin(), |
224 transformers_.end()); | 285 transformers_.end()); |
225 } | 286 } |
226 | 287 |
227 void RegisterPrefTransformer(const std::string& browser_pref, | 288 void RegisterPrefTransformer(const std::string& browser_pref, |
228 PrefTransformerInterface* transformer) { | 289 PrefTransformerInterface* transformer) { |
229 DCHECK_EQ(0u, transformers_.count(browser_pref)) << | 290 DCHECK_EQ(0u, transformers_.count(browser_pref)) << |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
308 | 369 |
309 ExtensionEventRouter* router = profile_->GetExtensionEventRouter(); | 370 ExtensionEventRouter* router = profile_->GetExtensionEventRouter(); |
310 if (!router || !router->HasEventListener(event_name)) | 371 if (!router || !router->HasEventListener(event_name)) |
311 return; | 372 return; |
312 const ExtensionList* extensions = extension_service->extensions(); | 373 const ExtensionList* extensions = extension_service->extensions(); |
313 for (ExtensionList::const_iterator it = extensions->begin(); | 374 for (ExtensionList::const_iterator it = extensions->begin(); |
314 it != extensions->end(); ++it) { | 375 it != extensions->end(); ++it) { |
315 std::string extension_id = (*it)->id(); | 376 std::string extension_id = (*it)->id(); |
316 // TODO(bauerb): Only iterate over registered event listeners. | 377 // TODO(bauerb): Only iterate over registered event listeners. |
317 if (router->ExtensionHasEventListener(extension_id, event_name) && | 378 if (router->ExtensionHasEventListener(extension_id, event_name) && |
318 (*it)->HasAPIPermission(permission) && | 379 (permission == ExtensionAPIPermission::kInvalid || |
380 (*it)->HasAPIPermission(permission)) && | |
319 (!incognito || extension_service->CanCrossIncognito(*it))) { | 381 (!incognito || extension_service->CanCrossIncognito(*it))) { |
320 std::string level_of_control = | 382 std::string level_of_control = |
321 GetLevelOfControl(profile_, extension_id, browser_pref, incognito); | 383 GetLevelOfControl(profile_, extension_id, browser_pref, incognito); |
322 dict->SetString(kLevelOfControl, level_of_control); | 384 dict->SetString(kLevelOfControl, level_of_control); |
323 | 385 |
324 std::string json_args; | 386 std::string json_args; |
325 base::JSONWriter::Write(&args, false, &json_args); | 387 base::JSONWriter::Write(&args, false, &json_args); |
326 | 388 |
327 DispatchEvent(extension_id, event_name, json_args); | 389 DispatchEvent(extension_id, event_name, json_args); |
328 } | 390 } |
(...skipping 28 matching lines...) Expand all Loading... | |
357 return false; | 419 return false; |
358 } | 420 } |
359 | 421 |
360 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs() | 422 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs() |
361 : profile_->GetPrefs(); | 423 : profile_->GetPrefs(); |
362 std::string browser_pref; | 424 std::string browser_pref; |
363 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; | 425 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; |
364 EXTENSION_FUNCTION_VALIDATE( | 426 EXTENSION_FUNCTION_VALIDATE( |
365 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( | 427 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( |
366 pref_key, &browser_pref, &permission)); | 428 pref_key, &browser_pref, &permission)); |
367 if (!GetExtension()->HasAPIPermission(permission)) { | 429 if (permission != ExtensionAPIPermission::kInvalid && |
Bernhard Bauer
2011/11/23 13:03:35
Could you move this into a helper method?
battre
2011/11/23 15:43:53
Done.
| |
430 !GetExtension()->HasAPIPermission(permission)) { | |
368 error_ = ExtensionErrorUtils::FormatErrorMessage( | 431 error_ = ExtensionErrorUtils::FormatErrorMessage( |
369 keys::kPermissionErrorMessage, pref_key); | 432 keys::kPermissionErrorMessage, pref_key); |
370 return false; | 433 return false; |
371 } | 434 } |
372 | 435 |
373 const PrefService::Preference* pref = | 436 const PrefService::Preference* pref = |
374 prefs->FindPreference(browser_pref.c_str()); | 437 prefs->FindPreference(browser_pref.c_str()); |
375 CHECK(pref); | 438 CHECK(pref); |
376 std::string level_of_control = | 439 std::string level_of_control = |
377 GetLevelOfControl(profile_, extension_id(), browser_pref, incognito); | 440 GetLevelOfControl(profile_, extension_id(), browser_pref, incognito); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
431 !profile_->HasOffTheRecordProfile()) { | 494 !profile_->HasOffTheRecordProfile()) { |
432 error_ = keys::kIncognitoSessionOnlyErrorMessage; | 495 error_ = keys::kIncognitoSessionOnlyErrorMessage; |
433 return false; | 496 return false; |
434 } | 497 } |
435 | 498 |
436 std::string browser_pref; | 499 std::string browser_pref; |
437 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; | 500 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; |
438 EXTENSION_FUNCTION_VALIDATE( | 501 EXTENSION_FUNCTION_VALIDATE( |
439 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( | 502 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( |
440 pref_key, &browser_pref, &permission)); | 503 pref_key, &browser_pref, &permission)); |
441 if (!GetExtension()->HasAPIPermission(permission)) { | 504 if (permission != ExtensionAPIPermission::kInvalid && |
505 !GetExtension()->HasAPIPermission(permission)) { | |
442 error_ = ExtensionErrorUtils::FormatErrorMessage( | 506 error_ = ExtensionErrorUtils::FormatErrorMessage( |
443 keys::kPermissionErrorMessage, pref_key); | 507 keys::kPermissionErrorMessage, pref_key); |
444 return false; | 508 return false; |
445 } | 509 } |
510 | |
511 // Prevent changing read-only preferences. | |
512 for (size_t i = 0; i < arraysize(kReadOnlyPrefs); ++i) { | |
Bernhard Bauer
2011/11/23 13:03:35
Could you move this into a helper method that retu
battre
2011/11/23 15:43:53
Done.
| |
513 if (kReadOnlyPrefs[i] == browser_pref) { | |
514 error_ = ExtensionErrorUtils::FormatErrorMessage( | |
515 keys::kCannotModifyReadOnlyMessage, pref_key); | |
516 return false; | |
517 } | |
518 } | |
519 | |
446 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); | 520 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); |
447 const PrefService::Preference* pref = | 521 const PrefService::Preference* pref = |
448 prefs->pref_service()->FindPreference(browser_pref.c_str()); | 522 prefs->pref_service()->FindPreference(browser_pref.c_str()); |
449 CHECK(pref); | 523 CHECK(pref); |
450 EXTENSION_FUNCTION_VALIDATE(value->GetType() == pref->GetType()); | 524 EXTENSION_FUNCTION_VALIDATE(value->GetType() == pref->GetType()); |
451 PrefTransformerInterface* transformer = | 525 PrefTransformerInterface* transformer = |
452 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); | 526 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); |
453 std::string error; | 527 std::string error; |
454 bool bad_message = false; | 528 bool bad_message = false; |
455 Value* browserPrefValue = | 529 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."; | 569 error_ = "Can't modify regular settings from an incognito context."; |
496 return false; | 570 return false; |
497 } | 571 } |
498 } | 572 } |
499 | 573 |
500 std::string browser_pref; | 574 std::string browser_pref; |
501 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; | 575 ExtensionAPIPermission::ID permission = ExtensionAPIPermission::kInvalid; |
502 EXTENSION_FUNCTION_VALIDATE( | 576 EXTENSION_FUNCTION_VALIDATE( |
503 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( | 577 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( |
504 pref_key, &browser_pref, &permission)); | 578 pref_key, &browser_pref, &permission)); |
505 if (!GetExtension()->HasAPIPermission(permission)) { | 579 if (permission != ExtensionAPIPermission::kInvalid && |
580 !GetExtension()->HasAPIPermission(permission)) { | |
506 error_ = ExtensionErrorUtils::FormatErrorMessage( | 581 error_ = ExtensionErrorUtils::FormatErrorMessage( |
507 keys::kPermissionErrorMessage, pref_key); | 582 keys::kPermissionErrorMessage, pref_key); |
508 return false; | 583 return false; |
509 } | 584 } |
585 | |
586 // Prevent changing read-only preferences. | |
587 for (size_t i = 0; i < arraysize(kReadOnlyPrefs); ++i) { | |
588 if (kReadOnlyPrefs[i] == browser_pref) { | |
589 error_ = ExtensionErrorUtils::FormatErrorMessage( | |
590 keys::kCannotModifyReadOnlyMessage, pref_key); | |
591 return false; | |
592 } | |
593 } | |
594 | |
510 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); | 595 ExtensionPrefs* prefs = profile_->GetExtensionService()->extension_prefs(); |
511 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, scope); | 596 prefs->RemoveExtensionControlledPref(extension_id(), browser_pref, scope); |
512 return true; | 597 return true; |
513 } | 598 } |
OLD | NEW |