1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/api/preference/preference_api.h" 6 7 #include <map> 8 #include <utility> 9 10 #include "base/lazy_instance.h" 11 #include "base/memory/singleton.h" 12 #include "base/prefs/pref_service.h" 13 #include "base/stl_util.h" 14 #include "base/strings/stringprintf.h" 15 #include "base/values.h" 16 #include "chrome/browser/chrome_notification_types.h" 17 #include "chrome/browser/extensions/api/preference/preference_api_constants.h" 18 #include "chrome/browser/extensions/api/preference/preference_helpers.h" 19 #include "chrome/browser/extensions/api/proxy/proxy_api.h" 20 #include "chrome/browser/extensions/extension_pref_value_map.h" 21 #include "chrome/browser/extensions/extension_pref_value_map_factory.h" 22 #include "chrome/browser/extensions/extension_prefs.h" 23 #include "chrome/browser/extensions/extension_prefs_factory.h" 24 #include "chrome/browser/extensions/extension_service.h" 25 #include "chrome/browser/extensions/extension_system.h" 26 #include "chrome/browser/profiles/profile.h" 27 #include "chrome/common/extensions/permissions/api_permission.h" 28 #include "chrome/common/pref_names.h" 29 #include "content/public/browser/notification_details.h" 30 #include "content/public/browser/notification_source.h" 31 #include "extensions/browser/pref_names.h" 32 #include "extensions/common/error_utils.h" 33 34 namespace keys = extensions::preference_api_constants; 35 namespace helpers = extensions::preference_helpers; 36 37 using base::DictionaryValue; 38 39 namespace extensions { 40 41 namespace { 42 43 struct PrefMappingEntry { 44 // Name of the preference referenced by the extension API JSON. 45 const char* extension_pref; 46 47 // Name of the preference in the PrefStores. 48 const char* browser_pref; 49 50 // Permission required to access this preference. 51 // Use APIPermission::kInvalid for |permission| to express that no 52 // permission is necessary. 53 APIPermission::ID permission; 54 }; 55 56 const char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange"; 57 const char kConversionErrorMessage[] = 58 "Internal error: Stored value for preference '*' cannot be converted " 59 "properly."; 60 61 PrefMappingEntry kPrefMapping[] = { 62 { "protectedContentEnabled", 63 prefs::kEnableDRM, 64 APIPermission::kPrivacy 65 }, 66 { "alternateErrorPagesEnabled", 67 prefs::kAlternateErrorPagesEnabled, 68 APIPermission::kPrivacy 69 }, 70 { "autofillEnabled", 71 autofill::prefs::kAutofillEnabled, 72 APIPermission::kPrivacy 73 }, 74 { "hyperlinkAuditingEnabled", 75 prefs::kEnableHyperlinkAuditing, 76 APIPermission::kPrivacy 77 }, 78 { "networkPredictionEnabled", 79 prefs::kNetworkPredictionEnabled, 80 APIPermission::kPrivacy 81 }, 82 { "proxy", 83 prefs::kProxy, 84 APIPermission::kProxy 85 }, 86 { "referrersEnabled", 87 prefs::kEnableReferrers, 88 APIPermission::kPrivacy 89 }, 90 { "safeBrowsingEnabled", 91 prefs::kSafeBrowsingEnabled, 92 APIPermission::kPrivacy 93 }, 94 { "searchSuggestEnabled", 95 prefs::kSearchSuggestEnabled, 96 APIPermission::kPrivacy 97 }, 98 { "spellingServiceEnabled", 99 prefs::kSpellCheckUseSpellingService, 100 APIPermission::kPrivacy 101 }, 102 { "thirdPartyCookiesAllowed", 103 prefs::kBlockThirdPartyCookies, 104 APIPermission::kPrivacy 105 }, 106 { "translationServiceEnabled", 107 prefs::kEnableTranslate, 108 APIPermission::kPrivacy 109 }, 110 }; 111 112 class IdentityPrefTransformer : public PrefTransformerInterface { 113 public: 114 virtual Value* ExtensionToBrowserPref(const Value* extension_pref, 115 std::string* error, 116 bool* bad_message) OVERRIDE { 117 return extension_pref->DeepCopy(); 118 } 119 120 virtual Value* BrowserToExtensionPref(const Value* browser_pref) OVERRIDE { 121 return browser_pref->DeepCopy(); 122 } 123 }; 124 125 class InvertBooleanTransformer : public PrefTransformerInterface { 126 public: 127 virtual Value* ExtensionToBrowserPref(const Value* extension_pref, 128 std::string* error, 129 bool* bad_message) OVERRIDE { 130 return InvertBooleanValue(extension_pref); 131 } 132 133 virtual Value* BrowserToExtensionPref(const Value* browser_pref) OVERRIDE { 134 return InvertBooleanValue(browser_pref); 135 } 136 137 private: 138 static Value* InvertBooleanValue(const Value* value) { 139 bool bool_value = false; 140 bool result = value->GetAsBoolean(&bool_value); 141 DCHECK(result); 142 return Value::CreateBooleanValue(!bool_value); 143 } 144 }; 145 146 class PrefMapping { 147 public: 148 static PrefMapping* GetInstance() { 149 return Singleton<PrefMapping>::get(); 150 } 151 152 bool FindBrowserPrefForExtensionPref(const std::string& extension_pref, 153 std::string* browser_pref, 154 APIPermission::ID* permission) { 155 PrefMap::iterator it = mapping_.find(extension_pref); 156 if (it != mapping_.end()) { 157 *browser_pref = it->second.first; 158 *permission = it->second.second; 159 return true; 160 } 161 return false; 162 } 163 164 bool FindEventForBrowserPref(const std::string& browser_pref, 165 std::string* event_name, 166 APIPermission::ID* permission) { 167 PrefMap::iterator it = event_mapping_.find(browser_pref); 168 if (it != event_mapping_.end()) { 169 *event_name = it->second.first; 170 *permission = it->second.second; 171 return true; 172 } 173 return false; 174 } 175 176 PrefTransformerInterface* FindTransformerForBrowserPref( 177 const std::string& browser_pref) { 178 std::map<std::string, PrefTransformerInterface*>::iterator it = 179 transformers_.find(browser_pref); 180 if (it != transformers_.end()) 181 return it->second; 182 else 183 return identity_transformer_.get(); 184 } 185 186 private: 187 friend struct DefaultSingletonTraits<PrefMapping>; 188 189 PrefMapping() { 190 identity_transformer_.reset(new IdentityPrefTransformer()); 191 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) { 192 mapping_[kPrefMapping[i].extension_pref] = 193 std::make_pair(kPrefMapping[i].browser_pref, 194 kPrefMapping[i].permission); 195 std::string event_name = 196 base::StringPrintf(kOnPrefChangeFormat, 197 kPrefMapping[i].extension_pref); 198 event_mapping_[kPrefMapping[i].browser_pref] = 199 std::make_pair(event_name, kPrefMapping[i].permission); 200 } 201 DCHECK_EQ(arraysize(kPrefMapping), mapping_.size()); 202 DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size()); 203 RegisterPrefTransformer(prefs::kProxy, new ProxyPrefTransformer()); 204 RegisterPrefTransformer(prefs::kBlockThirdPartyCookies, 205 new InvertBooleanTransformer()); 206 } 207 208 ~PrefMapping() { 209 STLDeleteContainerPairSecondPointers(transformers_.begin(), 210 transformers_.end()); 211 } 212 213 void RegisterPrefTransformer(const std::string& browser_pref, 214 PrefTransformerInterface* transformer) { 215 DCHECK_EQ(0u, transformers_.count(browser_pref)) << 216 "Trying to register pref transformer for " << browser_pref << " twice"; 217 transformers_[browser_pref] = transformer; 218 } 219 220 typedef std::map<std::string, 221 std::pair<std::string, APIPermission::ID> > 222 PrefMap; 223 224 // Mapping from extension pref keys to browser pref keys and permissions. 225 PrefMap mapping_; 226 227 // Mapping from browser pref keys to extension event names and permissions. 228 PrefMap event_mapping_; 229 230 // Mapping from browser pref keys to transformers. 231 std::map<std::string, PrefTransformerInterface*> transformers_; 232 233 scoped_ptr<PrefTransformerInterface> identity_transformer_; 234 235 DISALLOW_COPY_AND_ASSIGN(PrefMapping); 236 }; 237 238 } // namespace 239 240 PreferenceEventRouter::PreferenceEventRouter(Profile* profile) 241 : profile_(profile) { 242 registrar_.Init(profile_->GetPrefs()); 243 incognito_registrar_.Init(profile_->GetOffTheRecordPrefs()); 244 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) { 245 registrar_.Add(kPrefMapping[i].browser_pref, 246 base::Bind(&PreferenceEventRouter::OnPrefChanged, 247 base::Unretained(this), 248 registrar_.prefs())); 249 incognito_registrar_.Add(kPrefMapping[i].browser_pref, 250 base::Bind(&PreferenceEventRouter::OnPrefChanged, 251 base::Unretained(this), 252 incognito_registrar_.prefs())); 253 } 254 } 255 256 PreferenceEventRouter::~PreferenceEventRouter() { } 257 258 void PreferenceEventRouter::OnPrefChanged(PrefService* pref_service, 259 const std::string& browser_pref) { 260 bool incognito = (pref_service != profile_->GetPrefs()); 261 262 std::string event_name; 263 APIPermission::ID permission = APIPermission::kInvalid; 264 bool rv = PrefMapping::GetInstance()->FindEventForBrowserPref( 265 browser_pref, &event_name, &permission); 266 DCHECK(rv); 267 268 base::ListValue args; 269 DictionaryValue* dict = new DictionaryValue(); 270 args.Append(dict); 271 const PrefService::Preference* pref = 272 pref_service->FindPreference(browser_pref.c_str()); 273 CHECK(pref); 274 PrefTransformerInterface* transformer = 275 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); 276 Value* transformed_value = 277 transformer->BrowserToExtensionPref(pref->GetValue()); 278 if (!transformed_value) { 279 LOG(ERROR) << ErrorUtils::FormatErrorMessage(kConversionErrorMessage, 280 pref->name()); 281 return; 282 } 283 284 dict->Set(keys::kValue, transformed_value); 285 if (incognito) { 286 ExtensionPrefs* ep = ExtensionPrefs::Get(profile_); 287 dict->SetBoolean(keys::kIncognitoSpecific, 288 ep->HasIncognitoPrefValue(browser_pref)); 289 } 290 291 helpers::DispatchEventToExtensions(profile_, 292 event_name, 293 &args, 294 permission, 295 incognito, 296 browser_pref); 297 } 298 299 void PreferenceAPIBase::SetExtensionControlledPref( 300 const std::string& extension_id, 301 const std::string& pref_key, 302 ExtensionPrefsScope scope, 303 base::Value* value) { 304 #ifndef NDEBUG 305 const PrefService::Preference* pref = 306 extension_prefs()->pref_service()->FindPreference(pref_key.c_str()); 307 DCHECK(pref) << "Extension controlled preference key " << pref_key 308 << " not registered."; 309 DCHECK_EQ(pref->GetType(), value->GetType()) 310 << "Extension controlled preference " << pref_key << " has wrong type."; 311 #endif 312 313 std::string scope_string; 314 // ScopeToPrefName() returns false if the scope is not persisted. 315 if (pref_names::ScopeToPrefName(scope, &scope_string)) { 316 // Also store in persisted Preferences file to recover after a 317 // browser restart. 318 ExtensionPrefs::ScopedDictionaryUpdate update(extension_prefs(), 319 extension_id, 320 scope_string); 321 DictionaryValue* preference = update.Get(); 322 if (!preference) 323 preference = update.Create(); 324 preference->SetWithoutPathExpansion(pref_key, value->DeepCopy()); 325 } 326 extension_pref_value_map()->SetExtensionPref( 327 extension_id, pref_key, scope, value); 328 } 329 330 void PreferenceAPIBase::RemoveExtensionControlledPref( 331 const std::string& extension_id, 332 const std::string& pref_key, 333 ExtensionPrefsScope scope) { 334 DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key.c_str())) 335 << "Extension controlled preference key " << pref_key 336 << " not registered."; 337 338 std::string scope_string; 339 if (pref_names::ScopeToPrefName(scope, &scope_string)) { 340 ExtensionPrefs::ScopedDictionaryUpdate update(extension_prefs(), 341 extension_id, 342 scope_string); 343 DictionaryValue* preference = update.Get(); 344 if (preference) 345 preference->RemoveWithoutPathExpansion(pref_key, NULL); 346 } 347 extension_pref_value_map()->RemoveExtensionPref( 348 extension_id, pref_key, scope); 349 } 350 351 bool PreferenceAPIBase::CanExtensionControlPref( 352 const std::string& extension_id, 353 const std::string& pref_key, 354 bool incognito) { 355 DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key.c_str())) 356 << "Extension controlled preference key " << pref_key 357 << " not registered."; 358 359 return extension_pref_value_map()->CanExtensionControlPref( 360 extension_id, pref_key, incognito); 361 } 362 363 bool PreferenceAPIBase::DoesExtensionControlPref( 364 const std::string& extension_id, 365 const std::string& pref_key, 366 bool* from_incognito) { 367 DCHECK(extension_prefs()->pref_service()->FindPreference(pref_key.c_str())) 368 << "Extension controlled preference key " << pref_key 369 << " not registered."; 370 371 return extension_pref_value_map()->DoesExtensionControlPref( 372 extension_id, pref_key, from_incognito); 373 } 374 375 PreferenceAPI::PreferenceAPI(Profile* profile) : profile_(profile) { 376 for (size_t i = 0; i < arraysize(kPrefMapping); ++i) { 377 std::string event_name; 378 APIPermission::ID permission = APIPermission::kInvalid; 379 bool rv = PrefMapping::GetInstance()->FindEventForBrowserPref( 380 kPrefMapping[i].browser_pref, &event_name, &permission); 381 DCHECK(rv); 382 ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 383 this, event_name); 384 } 385 extension_prefs()->content_settings_store()->AddObserver(this); 386 } 387 388 PreferenceAPI::~PreferenceAPI() { 389 } 390 391 void PreferenceAPI::Shutdown() { 392 ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this); 393 if (!extension_prefs()->extensions_disabled()) 394 ClearIncognitoSessionOnlyContentSettings(); 395 extension_prefs()->content_settings_store()->RemoveObserver(this); 396 } 397 398 static base::LazyInstance<ProfileKeyedAPIFactory<PreferenceAPI> > 399 g_factory = LAZY_INSTANCE_INITIALIZER; 400 401 // static 402 ProfileKeyedAPIFactory<PreferenceAPI>* PreferenceAPI::GetFactoryInstance() { 403 return &g_factory.Get(); 404 } 405 406 // static 407 PreferenceAPI* PreferenceAPI::Get(Profile* profile) { 408 return ProfileKeyedAPIFactory<PreferenceAPI>::GetForProfile(profile); 409 } 410 411 void PreferenceAPI::OnListenerAdded(const EventListenerInfo& details) { 412 preference_event_router_.reset(new PreferenceEventRouter(profile_)); 413 ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this); 414 } 415 416 // static 417 void PreferenceAPI::LoadExtensionControlledPrefs( 418 ExtensionPrefs* prefs, 419 ExtensionPrefValueMap* value_map, 420 const std::string& extension_id, 421 ExtensionPrefsScope scope) { 422 std::string scope_string; 423 if (!pref_names::ScopeToPrefName(scope, &scope_string)) 424 return; 425 std::string key = extension_id + "." + scope_string; 426 427 const DictionaryValue* source_dict = prefs->pref_service()-> 428 GetDictionary(ExtensionPrefs::kExtensionsPref); 429 const DictionaryValue* preferences = NULL; 430 if (!source_dict->GetDictionary(key, &preferences)) 431 return; 432 433 for (DictionaryValue::Iterator iter(*preferences); 434 !iter.IsAtEnd(); iter.Advance()) { 435 value_map->SetExtensionPref( 436 extension_id, iter.key(), scope, iter.value().DeepCopy()); 437 } 438 } 439 440 // static 441 void PreferenceAPI::InitExtensionControlledPrefs( 442 ExtensionPrefs* prefs, 443 ExtensionPrefValueMap* value_map) { 444 ExtensionIdList extension_ids; 445 prefs->GetExtensions(&extension_ids); 446 447 for (ExtensionIdList::iterator extension_id = extension_ids.begin(); 448 extension_id != extension_ids.end(); ++extension_id) { 449 base::Time install_time = prefs->GetInstallTime(*extension_id); 450 bool is_enabled = !prefs->IsExtensionDisabled(*extension_id); 451 value_map->RegisterExtension(*extension_id, install_time, is_enabled); 452 prefs->content_settings_store()->RegisterExtension( 453 *extension_id, install_time, is_enabled); 454 455 // Set regular extension controlled prefs. 456 LoadExtensionControlledPrefs(prefs, 457 value_map, 458 *extension_id, 459 kExtensionPrefsScopeRegular); 460 // Set incognito extension controlled prefs. 461 LoadExtensionControlledPrefs(prefs, 462 value_map, 463 *extension_id, 464 kExtensionPrefsScopeIncognitoPersistent); 465 // Set regular-only extension controlled prefs. 466 LoadExtensionControlledPrefs(prefs, 467 value_map, 468 *extension_id, 469 kExtensionPrefsScopeRegularOnly); 470 471 // Set content settings. 472 const base::ListValue* content_settings = NULL; 473 if (prefs->ReadPrefAsList(*extension_id, 474 pref_names::kPrefContentSettings, 475 &content_settings)) { 476 prefs->content_settings_store()->SetExtensionContentSettingFromList( 477 *extension_id, content_settings, kExtensionPrefsScopeRegular); 478 } 479 if (prefs->ReadPrefAsList(*extension_id, 480 pref_names::kPrefIncognitoContentSettings, 481 &content_settings)) { 482 prefs->content_settings_store()->SetExtensionContentSettingFromList( 483 *extension_id, 484 content_settings, 485 kExtensionPrefsScopeIncognitoPersistent); 486 } 487 } 488 } 489 490 void PreferenceAPI::OnContentSettingChanged(const std::string& extension_id, 491 bool incognito) { 492 if (incognito) { 493 extension_prefs()->UpdateExtensionPref( 494 extension_id, 495 pref_names::kPrefIncognitoContentSettings, 496 extension_prefs()->content_settings_store()->GetSettingsForExtension( 497 extension_id, kExtensionPrefsScopeIncognitoPersistent)); 498 } else { 499 extension_prefs()->UpdateExtensionPref( 500 extension_id, 501 pref_names::kPrefContentSettings, 502 extension_prefs()->content_settings_store()->GetSettingsForExtension( 503 extension_id, kExtensionPrefsScopeRegular)); 504 } 505 } 506 507 void PreferenceAPI::ClearIncognitoSessionOnlyContentSettings() { 508 ExtensionIdList extension_ids; 509 extension_prefs()->GetExtensions(&extension_ids); 510 for (ExtensionIdList::iterator extension_id = extension_ids.begin(); 511 extension_id != extension_ids.end(); ++extension_id) { 512 extension_prefs()->content_settings_store()-> 513 ClearContentSettingsForExtension( 514 *extension_id, 515 kExtensionPrefsScopeIncognitoSessionOnly); 516 } 517 } 518 519 ExtensionPrefs* PreferenceAPI::extension_prefs() { 520 return ExtensionPrefs::Get(profile_); 521 } 522 523 ExtensionPrefValueMap* PreferenceAPI::extension_pref_value_map() { 524 return ExtensionPrefValueMapFactory::GetForProfile(profile_); 525 } 526 527 template <> 528 void ProfileKeyedAPIFactory<PreferenceAPI>::DeclareFactoryDependencies() { 529 DependsOn(ExtensionSystemFactory::GetInstance()); 530 DependsOn(ExtensionPrefsFactory::GetInstance()); 531 DependsOn(ExtensionPrefValueMapFactory::GetInstance()); 532 } 533 534 PreferenceFunction::~PreferenceFunction() { } 535 536 bool PreferenceFunction::ValidateBrowserPref( 537 const std::string& extension_pref_key, 538 std::string* browser_pref_key) { 539 APIPermission::ID permission = APIPermission::kInvalid; 540 EXTENSION_FUNCTION_VALIDATE( 541 PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref( 542 extension_pref_key, browser_pref_key, &permission)); 543 if (!GetExtension()->HasAPIPermission(permission)) { 544 error_ = ErrorUtils::FormatErrorMessage( 545 keys::kPermissionErrorMessage, extension_pref_key); 546 return false; 547 } 548 return true; 549 } 550 551 GetPreferenceFunction::~GetPreferenceFunction() { } 552 553 bool GetPreferenceFunction::RunImpl() { 554 std::string pref_key; 555 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key)); 556 DictionaryValue* details = NULL; 557 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details)); 558 559 bool incognito = false; 560 if (details->HasKey(keys::kIncognitoKey)) 561 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean(keys::kIncognitoKey, 562 &incognito)); 563 564 // Check incognito access. 565 if (incognito && !include_incognito()) { 566 error_ = keys::kIncognitoErrorMessage; 567 return false; 568 } 569 570 // Obtain pref. 571 std::string browser_pref; 572 if (!ValidateBrowserPref(pref_key, &browser_pref)) 573 return false; 574 PrefService* prefs = incognito ? profile_->GetOffTheRecordPrefs() 575 : profile_->GetPrefs(); 576 const PrefService::Preference* pref = 577 prefs->FindPreference(browser_pref.c_str()); 578 CHECK(pref); 579 580 scoped_ptr<DictionaryValue> result(new DictionaryValue); 581 582 // Retrieve level of control. 583 std::string level_of_control = 584 helpers::GetLevelOfControl(profile_, extension_id(), browser_pref, 585 incognito); 586 result->SetString(keys::kLevelOfControl, level_of_control); 587 588 // Retrieve pref value. 589 PrefTransformerInterface* transformer = 590 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); 591 Value* transformed_value = 592 transformer->BrowserToExtensionPref(pref->GetValue()); 593 if (!transformed_value) { 594 LOG(ERROR) << 595 ErrorUtils::FormatErrorMessage(kConversionErrorMessage, 596 pref->name()); 597 return false; 598 } 599 result->Set(keys::kValue, transformed_value); 600 601 // Retrieve incognito status. 602 if (incognito) { 603 ExtensionPrefs* ep = ExtensionPrefs::Get(profile_); 604 result->SetBoolean(keys::kIncognitoSpecific, 605 ep->HasIncognitoPrefValue(browser_pref)); 606 } 607 608 SetResult(result.release()); 609 return true; 610 } 611 612 SetPreferenceFunction::~SetPreferenceFunction() { } 613 614 bool SetPreferenceFunction::RunImpl() { 615 std::string pref_key; 616 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key)); 617 DictionaryValue* details = NULL; 618 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details)); 619 620 Value* value = NULL; 621 EXTENSION_FUNCTION_VALIDATE(details->Get(keys::kValue, &value)); 622 623 ExtensionPrefsScope scope = kExtensionPrefsScopeRegular; 624 if (details->HasKey(keys::kScopeKey)) { 625 std::string scope_str; 626 EXTENSION_FUNCTION_VALIDATE( 627 details->GetString(keys::kScopeKey, &scope_str)); 628 629 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope)); 630 } 631 632 // Check incognito scope. 633 bool incognito = 634 (scope == kExtensionPrefsScopeIncognitoPersistent || 635 scope == kExtensionPrefsScopeIncognitoSessionOnly); 636 if (incognito) { 637 // Regular profiles can't access incognito unless include_incognito is true. 638 if (!profile()->IsOffTheRecord() && !include_incognito()) { 639 error_ = keys::kIncognitoErrorMessage; 640 return false; 641 } 642 } else { 643 // Incognito profiles can't access regular mode ever, they only exist in 644 // split mode. 645 if (profile()->IsOffTheRecord()) { 646 error_ = "Can't modify regular settings from an incognito context."; 647 return false; 648 } 649 } 650 651 if (scope == kExtensionPrefsScopeIncognitoSessionOnly && 652 !profile_->HasOffTheRecordProfile()) { 653 error_ = keys::kIncognitoSessionOnlyErrorMessage; 654 return false; 655 } 656 657 // Obtain pref. 658 std::string browser_pref; 659 if (!ValidateBrowserPref(pref_key, &browser_pref)) 660 return false; 661 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_); 662 const PrefService::Preference* pref = 663 prefs->pref_service()->FindPreference(browser_pref.c_str()); 664 CHECK(pref); 665 666 // Validate new value. 667 EXTENSION_FUNCTION_VALIDATE(value->GetType() == pref->GetType()); 668 PrefTransformerInterface* transformer = 669 PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); 670 std::string error; 671 bool bad_message = false; 672 scoped_ptr<Value> browser_pref_value( 673 transformer->ExtensionToBrowserPref(value, &error, &bad_message)); 674 if (!browser_pref_value) { 675 error_ = error; 676 bad_message_ = bad_message; 677 return false; 678 } 679 680 // Validate also that the stored value can be converted back by the 681 // transformer. 682 scoped_ptr<Value> extensionPrefValue( 683 transformer->BrowserToExtensionPref(browser_pref_value.get())); 684 if (!extensionPrefValue) { 685 error_ = ErrorUtils::FormatErrorMessage(kConversionErrorMessage, 686 pref->name()); 687 bad_message_ = true; 688 return false; 689 } 690 691 PreferenceAPI::Get(profile())->SetExtensionControlledPref( 692 extension_id(), 693 browser_pref, 694 scope, 695 browser_pref_value.release()); 696 return true; 697 } 698 699 ClearPreferenceFunction::~ClearPreferenceFunction() { } 700 701 bool ClearPreferenceFunction::RunImpl() { 702 std::string pref_key; 703 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &pref_key)); 704 DictionaryValue* details = NULL; 705 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details)); 706 707 ExtensionPrefsScope scope = kExtensionPrefsScopeRegular; 708 if (details->HasKey(keys::kScopeKey)) { 709 std::string scope_str; 710 EXTENSION_FUNCTION_VALIDATE( 711 details->GetString(keys::kScopeKey, &scope_str)); 712 713 EXTENSION_FUNCTION_VALIDATE(helpers::StringToScope(scope_str, &scope)); 714 } 715 716 // Check incognito scope. 717 bool incognito = 718 (scope == kExtensionPrefsScopeIncognitoPersistent || 719 scope == kExtensionPrefsScopeIncognitoSessionOnly); 720 if (incognito) { 721 // We don't check incognito permissions here, as an extension should be 722 // always allowed to clear its own settings. 723 } else { 724 // Incognito profiles can't access regular mode ever, they only exist in 725 // split mode. 726 if (profile()->IsOffTheRecord()) { 727 error_ = "Can't modify regular settings from an incognito context."; 728 return false; 729 } 730 } 731 732 std::string browser_pref; 733 if (!ValidateBrowserPref(pref_key, &browser_pref)) 734 return false; 735 736 PreferenceAPI::Get(profile())->RemoveExtensionControlledPref( 737 extension_id(), browser_pref, scope); 738 return true; 739 } 740 741 } // namespace extensions 742