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. |
|
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 |