Chromium Code Reviews| 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 |