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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/extension_prefs.h" 6 7 #include "base/string_number_conversions.h" 8 #include "base/string_util.h" 9 #include "base/utf_string_conversions.h" 10 #include "chrome/browser/extensions/extension_pref_store.h" 11 #include "chrome/browser/prefs/pref_notifier.h" 12 #include "chrome/browser/prefs/scoped_user_pref_update.h" 13 #include "chrome/common/url_constants.h" 14 #include "chrome/common/extensions/extension.h" 15 #include "chrome/common/extensions/url_pattern.h" 16 #include "chrome/common/pref_names.h" 17 #include "content/common/notification_service.h" 18 19 using base::Time; 20 21 namespace { 22 23 // Additional preferences keys 24 25 // Where an extension was installed from. (see Extension::Location) 26 const char kPrefLocation[] = "location"; 27 28 // Enabled, disabled, killed, etc. (see Extension::State) 29 const char kPrefState[] = "state"; 30 31 // The path to the current version's manifest file. 32 const char kPrefPath[] = "path"; 33 34 // The dictionary containing the extension's manifest. 35 const char kPrefManifest[] = "manifest"; 36 37 // The version number. 38 const char kPrefVersion[] = "manifest.version"; 39 40 // Indicates if an extension is blacklisted: 41 const char kPrefBlacklist[] = "blacklist"; 42 43 // Indicates whether to show an install warning when the user enables. 44 const char kExtensionDidEscalatePermissions[] = "install_warning_on_enable"; 45 46 // A preference that tracks browser action toolbar configuration. This is a list 47 // object stored in the Preferences file. The extensions are stored by ID. 48 const char kExtensionToolbar[] = "extensions.toolbar"; 49 50 // The key for a serialized Time value indicating the start of the day (from the 51 // server's perspective) an extension last included a "ping" parameter during 52 // its update check. 53 const char kLastPingDay[] = "lastpingday"; 54 55 // Similar to kLastPingDay, but for "active" instead of "rollcall" pings. 56 const char kLastActivePingDay[] = "last_active_pingday"; 57 58 // A bit we use to keep track of whether we need to do an "active" ping. 59 const char kActiveBit[] = "active_bit"; 60 61 // Path for settings specific to blacklist update. 62 const char kExtensionsBlacklistUpdate[] = "extensions.blacklistupdate"; 63 64 // Path and sub-keys for the idle install info dictionary preference. 65 const char kIdleInstallInfo[] = "idle_install_info"; 66 const char kIdleInstallInfoCrxPath[] = "crx_path"; 67 const char kIdleInstallInfoVersion[] = "version"; 68 const char kIdleInstallInfoFetchTime[] = "fetch_time"; 69 70 71 // A preference that, if true, will allow this extension to run in incognito 72 // mode. 73 const char kPrefIncognitoEnabled[] = "incognito"; 74 75 // A preference to control whether an extension is allowed to inject script in 76 // pages with file URLs. 77 const char kPrefAllowFileAccess[] = "allowFileAccess"; 78 79 // A preference set by the web store to indicate login information for 80 // purchased apps. 81 const char kWebStoreLogin[] = "extensions.webstore_login"; 82 83 // A preference set by the the NTP to persist the desired launch container type 84 // used for apps. 85 const char kPrefLaunchType[] = "launchType"; 86 87 // A preference determining the order of which the apps appear on the NTP. 88 const char kPrefAppLaunchIndex[] = "app_launcher_index"; 89 90 // A preference determining the page on which an app appears in the NTP. 91 const char kPrefPageIndex[] = "page_index"; 92 93 // A preference specifying if the user dragged the app on the NTP. 94 const char kPrefUserDraggedApp[] = "user_dragged_app_ntp"; 95 96 // A preference for storing extra data sent in update checks for an extension. 97 const char kUpdateUrlData[] = "update_url_data"; 98 99 // Whether the browser action is visible in the toolbar. 100 const char kBrowserActionVisible[] = "browser_action_visible"; 101 102 // Preferences that hold which permissions the user has granted the extension. 103 // We explicitly keep track of these so that extensions can contain unknown 104 // permissions, for backwards compatibility reasons, and we can still prompt 105 // the user to accept them once recognized. 106 const char kPrefGrantedPermissionsAPI[] = "granted_permissions.api"; 107 const char kPrefGrantedPermissionsHost[] = "granted_permissions.host"; 108 const char kPrefGrantedPermissionsAll[] = "granted_permissions.full"; 109 110 // A preference that indicates when an extension was installed. 111 const char kPrefInstallTime[] = "install_time"; 112 113 // A preference that contains any extension-controlled preferences. 114 const char kPrefPreferences[] = "preferences"; 115 116 // Provider of write access to a dictionary storing extension prefs. 117 class ScopedExtensionPrefUpdate : public DictionaryPrefUpdate { 118 public: 119 ScopedExtensionPrefUpdate(PrefService* service, 120 const std::string& extension_id) : 121 DictionaryPrefUpdate(service, ExtensionPrefs::kExtensionsPref), 122 extension_id_(extension_id) {} 123 virtual ~ScopedExtensionPrefUpdate() {} 124 virtual DictionaryValue* Get() { 125 DictionaryValue* dict = DictionaryPrefUpdate::Get(); 126 DictionaryValue* extension = NULL; 127 if (!dict->GetDictionary(extension_id_, &extension)) { 128 // Extension pref does not exist, create it. 129 extension = new DictionaryValue(); 130 dict->Set(extension_id_, extension); 131 } 132 return extension; 133 } 134 135 private: 136 const std::string extension_id_; 137 138 DISALLOW_COPY_AND_ASSIGN(ScopedExtensionPrefUpdate); 139 }; 140 141 // Provider of write access to a dictionary storing extension controlled prefs. 142 class ScopedExtensionControlledPrefUpdate : public DictionaryPrefUpdate { 143 public: 144 ScopedExtensionControlledPrefUpdate(PrefService* service, 145 const std::string& extension_id) : 146 DictionaryPrefUpdate(service, ExtensionPrefs::kExtensionsPref), 147 extension_id_(extension_id) {} 148 virtual ~ScopedExtensionControlledPrefUpdate() {} 149 virtual DictionaryValue* Get() { 150 DictionaryValue* dict = DictionaryPrefUpdate::Get(); 151 DictionaryValue* preferences = NULL; 152 std::string key = extension_id_ + std::string(".") + kPrefPreferences; 153 if (!dict->GetDictionary(key, &preferences)) { 154 preferences = new DictionaryValue; 155 dict->Set(key, preferences); 156 } 157 return preferences; 158 } 159 160 private: 161 const std::string extension_id_; 162 163 DISALLOW_COPY_AND_ASSIGN(ScopedExtensionControlledPrefUpdate); 164 }; 165 166 // TODO(mihaip): This is cleanup code for keys for unpacked extensions (which 167 // are derived from paths). As part of the wstring removal, we changed the way 168 // we hash paths, so we need to move prefs from their old synthesized IDs to 169 // their new ones. We can remove this by July 2011. (See http://crbug.com/75945 170 // for more details). 171 static void CleanupBadExtensionKeys(const FilePath& root_dir, 172 PrefService* prefs) { 173 const DictionaryValue* dictionary = 174 prefs->GetDictionary(ExtensionPrefs::kExtensionsPref); 175 std::map<std::string, std::string> remapped_keys; 176 for (DictionaryValue::key_iterator i = dictionary->begin_keys(); 177 i != dictionary->end_keys(); ++i) { 178 DictionaryValue* ext; 179 if (!dictionary->GetDictionaryWithoutPathExpansion(*i, &ext)) 180 continue; 181 182 int location; 183 FilePath::StringType path_str; 184 if (!ext->GetInteger(kPrefLocation, &location) || 185 !ext->GetString(kPrefPath, &path_str)) { 186 continue; 187 } 188 189 // Only unpacked extensions have generated IDs. 190 if (location != Extension::LOAD) 191 continue; 192 193 const std::string& prefs_id(*i); 194 FilePath path(path_str); 195 // The persisted path can be relative to the root dir (see 196 // MakePath(s)Relative), but the ID is generated before that, using the 197 // absolute path, so we need to undo that. 198 if (!path.IsAbsolute()) { 199 path = root_dir.Append(path); 200 } 201 std::string computed_id = Extension::GenerateIdForPath(path); 202 203 if (prefs_id != computed_id) { 204 remapped_keys[prefs_id] = computed_id; 205 } 206 } 207 208 if (!remapped_keys.empty()) { 209 DictionaryPrefUpdate update(prefs, ExtensionPrefs::kExtensionsPref); 210 DictionaryValue* update_dictionary = update.Get(); 211 for (std::map<std::string, std::string>::const_iterator i = 212 remapped_keys.begin(); 213 i != remapped_keys.end(); 214 ++i) { 215 // Don't clobber prefs under the correct ID if they already exist. 216 if (update_dictionary->HasKey(i->second)) { 217 CHECK(update_dictionary->RemoveWithoutPathExpansion(i->first, NULL)); 218 continue; 219 } 220 Value* extension_prefs = NULL; 221 CHECK(update_dictionary->RemoveWithoutPathExpansion( 222 i->first, &extension_prefs)); 223 update_dictionary->SetWithoutPathExpansion(i->second, extension_prefs); 224 } 225 226 prefs->ScheduleSavePersistentPrefs(); 227 } 228 } 229 230 static void ExtentToStringSet(const ExtensionExtent& host_extent, 231 std::set<std::string>* result) { 232 ExtensionExtent::PatternList patterns = host_extent.patterns(); 233 ExtensionExtent::PatternList::const_iterator i; 234 235 for (i = patterns.begin(); i != patterns.end(); ++i) 236 result->insert(i->GetAsString()); 237 } 238 239 } // namespace 240 241 ExtensionPrefs::ExtensionPrefs( 242 PrefService* prefs, 243 const FilePath& root_dir, 244 ExtensionPrefValueMap* extension_pref_value_map) 245 : prefs_(prefs), 246 install_directory_(root_dir), 247 extension_pref_value_map_(extension_pref_value_map) { 248 // TODO(mihaip): Remove this by July 2011 (see comment above). 249 CleanupBadExtensionKeys(root_dir, prefs_); 250 251 MakePathsRelative(); 252 253 InitPrefStore(); 254 } 255 256 ExtensionPrefs::~ExtensionPrefs() {} 257 258 // static 259 const char ExtensionPrefs::kExtensionsPref[] = "extensions.settings"; 260 261 static FilePath::StringType MakePathRelative(const FilePath& parent, 262 const FilePath& child) { 263 if (!parent.IsParent(child)) 264 return child.value(); 265 266 FilePath::StringType retval = child.value().substr( 267 parent.value().length()); 268 if (FilePath::IsSeparator(retval[0])) 269 return retval.substr(1); 270 else 271 return retval; 272 } 273 274 void ExtensionPrefs::MakePathsRelative() { 275 const DictionaryValue* dict = prefs_->GetDictionary(kExtensionsPref); 276 if (!dict || dict->empty()) 277 return; 278 279 // Collect all extensions ids with absolute paths in |absolute_keys|. 280 std::set<std::string> absolute_keys; 281 for (DictionaryValue::key_iterator i = dict->begin_keys(); 282 i != dict->end_keys(); ++i) { 283 DictionaryValue* extension_dict = NULL; 284 if (!dict->GetDictionaryWithoutPathExpansion(*i, &extension_dict)) 285 continue; 286 int location_value; 287 if (extension_dict->GetInteger(kPrefLocation, &location_value) && 288 location_value == Extension::LOAD) { 289 // Unpacked extensions can have absolute paths. 290 continue; 291 } 292 FilePath::StringType path_string; 293 if (!extension_dict->GetString(kPrefPath, &path_string)) 294 continue; 295 FilePath path(path_string); 296 if (path.IsAbsolute()) 297 absolute_keys.insert(*i); 298 } 299 if (absolute_keys.empty()) 300 return; 301 302 // Fix these paths. 303 DictionaryPrefUpdate update(prefs_, kExtensionsPref); 304 const DictionaryValue* update_dict = update.Get(); 305 for (std::set<std::string>::iterator i = absolute_keys.begin(); 306 i != absolute_keys.end(); ++i) { 307 DictionaryValue* extension_dict = NULL; 308 update_dict->GetDictionaryWithoutPathExpansion(*i, &extension_dict); 309 FilePath::StringType path_string; 310 extension_dict->GetString(kPrefPath, &path_string); 311 FilePath path(path_string); 312 extension_dict->SetString(kPrefPath, 313 MakePathRelative(install_directory_, path)); 314 } 315 SavePrefs(); 316 } 317 318 void ExtensionPrefs::MakePathsAbsolute(DictionaryValue* dict) { 319 if (!dict || dict->empty()) 320 return; 321 322 for (DictionaryValue::key_iterator i = dict->begin_keys(); 323 i != dict->end_keys(); ++i) { 324 DictionaryValue* extension_dict = NULL; 325 if (!dict->GetDictionaryWithoutPathExpansion(*i, &extension_dict)) { 326 NOTREACHED(); 327 continue; 328 } 329 330 int location_value; 331 if (extension_dict->GetInteger(kPrefLocation, &location_value) && 332 location_value == Extension::LOAD) { 333 // Unpacked extensions will already have absolute paths. 334 continue; 335 } 336 337 FilePath::StringType path_string; 338 if (!extension_dict->GetString(kPrefPath, &path_string)) 339 continue; 340 341 DCHECK(!FilePath(path_string).IsAbsolute()); 342 extension_dict->SetString( 343 kPrefPath, install_directory_.Append(path_string).value()); 344 } 345 } 346 347 DictionaryValue* ExtensionPrefs::CopyCurrentExtensions() { 348 const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref); 349 if (extensions) { 350 DictionaryValue* copy = extensions->DeepCopy(); 351 MakePathsAbsolute(copy); 352 return copy; 353 } 354 return new DictionaryValue; 355 } 356 357 bool ExtensionPrefs::ReadBooleanFromPref( 358 const DictionaryValue* ext, const std::string& pref_key) { 359 bool bool_value = false; 360 if (!ext->GetBoolean(pref_key, &bool_value)) 361 return false; 362 363 return bool_value; 364 } 365 366 bool ExtensionPrefs::ReadExtensionPrefBoolean( 367 const std::string& extension_id, const std::string& pref_key) { 368 const DictionaryValue* ext = GetExtensionPref(extension_id); 369 if (!ext) { 370 // No such extension yet. 371 return false; 372 } 373 return ReadBooleanFromPref(ext, pref_key); 374 } 375 376 bool ExtensionPrefs::ReadIntegerFromPref( 377 const DictionaryValue* ext, const std::string& pref_key, int* out_value) { 378 if (!ext->GetInteger(pref_key, out_value)) 379 return false; 380 381 return out_value != NULL; 382 } 383 384 bool ExtensionPrefs::ReadExtensionPrefInteger( 385 const std::string& extension_id, const std::string& pref_key, 386 int* out_value) { 387 const DictionaryValue* ext = GetExtensionPref(extension_id); 388 if (!ext) { 389 // No such extension yet. 390 return false; 391 } 392 return ReadIntegerFromPref(ext, pref_key, out_value); 393 } 394 395 bool ExtensionPrefs::ReadExtensionPrefList( 396 const std::string& extension_id, const std::string& pref_key, 397 const ListValue** out_value) { 398 const DictionaryValue* ext = GetExtensionPref(extension_id); 399 ListValue* out = NULL; 400 if (!ext || !ext->GetList(pref_key, &out)) 401 return false; 402 *out_value = out; 403 404 return out_value != NULL; 405 } 406 407 bool ExtensionPrefs::ReadExtensionPrefStringSet( 408 const std::string& extension_id, 409 const std::string& pref_key, 410 std::set<std::string>* result) { 411 const ListValue* value = NULL; 412 if (!ReadExtensionPrefList(extension_id, pref_key, &value)) 413 return false; 414 415 result->clear(); 416 417 for (size_t i = 0; i < value->GetSize(); ++i) { 418 std::string item; 419 if (!value->GetString(i, &item)) 420 return false; 421 result->insert(item); 422 } 423 424 return true; 425 } 426 427 void ExtensionPrefs::AddToExtensionPrefStringSet( 428 const std::string& extension_id, 429 const std::string& pref_key, 430 const std::set<std::string>& added_value) { 431 std::set<std::string> old_value; 432 std::set<std::string> new_value; 433 ReadExtensionPrefStringSet(extension_id, pref_key, &old_value); 434 435 std::set_union(old_value.begin(), old_value.end(), 436 added_value.begin(), added_value.end(), 437 std::inserter(new_value, new_value.begin())); 438 439 ListValue* value = new ListValue(); 440 for (std::set<std::string>::const_iterator iter = new_value.begin(); 441 iter != new_value.end(); ++iter) 442 value->Append(Value::CreateStringValue(*iter)); 443 444 UpdateExtensionPref(extension_id, pref_key, value); 445 prefs_->ScheduleSavePersistentPrefs(); 446 } 447 448 void ExtensionPrefs::SavePrefs() { 449 prefs_->ScheduleSavePersistentPrefs(); 450 } 451 452 bool ExtensionPrefs::IsBlacklistBitSet(DictionaryValue* ext) { 453 return ReadBooleanFromPref(ext, kPrefBlacklist); 454 } 455 456 bool ExtensionPrefs::IsExtensionBlacklisted(const std::string& extension_id) { 457 return ReadExtensionPrefBoolean(extension_id, kPrefBlacklist); 458 } 459 460 bool ExtensionPrefs::IsExtensionAllowedByPolicy( 461 const std::string& extension_id) { 462 std::string string_value; 463 464 const ListValue* blacklist = 465 prefs_->GetList(prefs::kExtensionInstallDenyList); 466 if (!blacklist || blacklist->empty()) 467 return true; 468 469 // Check the whitelist first. 470 const ListValue* whitelist = 471 prefs_->GetList(prefs::kExtensionInstallAllowList); 472 if (whitelist) { 473 for (ListValue::const_iterator it = whitelist->begin(); 474 it != whitelist->end(); ++it) { 475 if (!(*it)->GetAsString(&string_value)) 476 LOG(WARNING) << "Failed to read whitelist string."; 477 else if (string_value == extension_id) 478 return true; 479 } 480 } 481 482 // Then check the blacklist (the admin blacklist, not the Google blacklist). 483 if (blacklist) { 484 for (ListValue::const_iterator it = blacklist->begin(); 485 it != blacklist->end(); ++it) { 486 if (!(*it)->GetAsString(&string_value)) { 487 LOG(WARNING) << "Failed to read blacklist string."; 488 } else { 489 if (string_value == "*") 490 return false; // Only whitelisted extensions are allowed. 491 if (string_value == extension_id) 492 return false; 493 } 494 } 495 } 496 497 return true; 498 } 499 500 bool ExtensionPrefs::DidExtensionEscalatePermissions( 501 const std::string& extension_id) { 502 return ReadExtensionPrefBoolean(extension_id, 503 kExtensionDidEscalatePermissions); 504 } 505 506 void ExtensionPrefs::SetDidExtensionEscalatePermissions( 507 const Extension* extension, bool did_escalate) { 508 UpdateExtensionPref(extension->id(), kExtensionDidEscalatePermissions, 509 Value::CreateBooleanValue(did_escalate)); 510 prefs_->ScheduleSavePersistentPrefs(); 511 } 512 513 void ExtensionPrefs::UpdateBlacklist( 514 const std::set<std::string>& blacklist_set) { 515 std::vector<std::string> remove_pref_ids; 516 std::set<std::string> used_id_set; 517 const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref); 518 519 if (extensions) { 520 for (DictionaryValue::key_iterator extension_id = extensions->begin_keys(); 521 extension_id != extensions->end_keys(); ++extension_id) { 522 DictionaryValue* ext; 523 if (!extensions->GetDictionaryWithoutPathExpansion(*extension_id, &ext)) { 524 NOTREACHED() << "Invalid pref for extension " << *extension_id; 525 continue; 526 } 527 const std::string& id(*extension_id); 528 if (blacklist_set.find(id) == blacklist_set.end()) { 529 if (!IsBlacklistBitSet(ext)) { 530 // This extension is not in blacklist. And it was not blacklisted 531 // before. 532 continue; 533 } else { 534 if (ext->size() == 1) { 535 // We should remove the entry if the only flag here is blacklist. 536 remove_pref_ids.push_back(id); 537 } else { 538 // Remove the blacklist bit. 539 ext->Remove(kPrefBlacklist, NULL); 540 } 541 } 542 } else { 543 if (!IsBlacklistBitSet(ext)) { 544 // Only set the blacklist if it was not set. 545 ext->SetBoolean(kPrefBlacklist, true); 546 } 547 // Keep the record if this extension is already processed. 548 used_id_set.insert(id); 549 } 550 } 551 } 552 553 // Iterate the leftovers to set blacklist in pref 554 std::set<std::string>::const_iterator set_itr = blacklist_set.begin(); 555 for (; set_itr != blacklist_set.end(); ++set_itr) { 556 if (used_id_set.find(*set_itr) == used_id_set.end()) { 557 UpdateExtensionPref(*set_itr, kPrefBlacklist, 558 Value::CreateBooleanValue(true)); 559 } 560 } 561 for (unsigned int i = 0; i < remove_pref_ids.size(); ++i) { 562 DeleteExtensionPrefs(remove_pref_ids[i]); 563 } 564 SavePrefs(); 565 return; 566 } 567 568 namespace { 569 570 // Serializes |time| as a string value mapped to |key| in |dictionary|. 571 void SaveTime(DictionaryValue* dictionary, const char* key, const Time& time) { 572 if (!dictionary) 573 return; 574 std::string string_value = base::Int64ToString(time.ToInternalValue()); 575 dictionary->SetString(key, string_value); 576 } 577 578 // The opposite of SaveTime. If |key| is not found, this returns an empty Time 579 // (is_null() will return true). 580 Time ReadTime(const DictionaryValue* dictionary, const char* key) { 581 if (!dictionary) 582 return Time(); 583 std::string string_value; 584 int64 value; 585 if (dictionary->GetString(key, &string_value)) { 586 if (base::StringToInt64(string_value, &value)) { 587 return Time::FromInternalValue(value); 588 } 589 } 590 return Time(); 591 } 592 593 } // namespace 594 595 Time ExtensionPrefs::LastPingDay(const std::string& extension_id) const { 596 DCHECK(Extension::IdIsValid(extension_id)); 597 return ReadTime(GetExtensionPref(extension_id), kLastPingDay); 598 } 599 600 void ExtensionPrefs::SetLastPingDay(const std::string& extension_id, 601 const Time& time) { 602 DCHECK(Extension::IdIsValid(extension_id)); 603 ScopedExtensionPrefUpdate update(prefs_, extension_id); 604 SaveTime(update.Get(), kLastPingDay, time); 605 } 606 607 Time ExtensionPrefs::BlacklistLastPingDay() const { 608 return ReadTime(prefs_->GetDictionary(kExtensionsBlacklistUpdate), 609 kLastPingDay); 610 } 611 612 void ExtensionPrefs::SetBlacklistLastPingDay(const Time& time) { 613 DictionaryPrefUpdate update(prefs_, kExtensionsBlacklistUpdate); 614 SaveTime(update.Get(), kLastPingDay, time); 615 } 616 617 Time ExtensionPrefs::LastActivePingDay(const std::string& extension_id) { 618 DCHECK(Extension::IdIsValid(extension_id)); 619 return ReadTime(GetExtensionPref(extension_id), kLastActivePingDay); 620 } 621 622 void ExtensionPrefs::SetLastActivePingDay(const std::string& extension_id, 623 const base::Time& time) { 624 DCHECK(Extension::IdIsValid(extension_id)); 625 ScopedExtensionPrefUpdate update(prefs_, extension_id); 626 SaveTime(update.Get(), kLastActivePingDay, time); 627 } 628 629 bool ExtensionPrefs::GetActiveBit(const std::string& extension_id) { 630 const DictionaryValue* dictionary = GetExtensionPref(extension_id); 631 bool result = false; 632 if (dictionary && dictionary->GetBoolean(kActiveBit, &result)) 633 return result; 634 return false; 635 } 636 637 void ExtensionPrefs::SetActiveBit(const std::string& extension_id, 638 bool active) { 639 ScopedExtensionPrefUpdate update(prefs_, extension_id); 640 update.Get()->SetBoolean(kActiveBit, active); 641 } 642 643 bool ExtensionPrefs::GetGrantedPermissions( 644 const std::string& extension_id, 645 bool* full_access, 646 std::set<std::string>* api_permissions, 647 ExtensionExtent* host_extent) { 648 CHECK(Extension::IdIsValid(extension_id)); 649 650 const DictionaryValue* ext = GetExtensionPref(extension_id); 651 if (!ext || !ext->GetBoolean(kPrefGrantedPermissionsAll, full_access)) 652 return false; 653 654 ReadExtensionPrefStringSet( 655 extension_id, kPrefGrantedPermissionsAPI, api_permissions); 656 657 std::set<std::string> host_permissions; 658 ReadExtensionPrefStringSet( 659 extension_id, kPrefGrantedPermissionsHost, &host_permissions); 660 bool allow_file_access = AllowFileAccess(extension_id); 661 662 // The granted host permissions contain hosts from the manifest's 663 // "permissions" array and from the content script "matches" arrays, 664 // so the URLPattern needs to accept valid schemes from both types. 665 for (std::set<std::string>::iterator i = host_permissions.begin(); 666 i != host_permissions.end(); ++i) { 667 URLPattern pattern( 668 Extension::kValidHostPermissionSchemes | 669 UserScript::kValidUserScriptSchemes); 670 671 // Parse without strict checks, so that new strict checks do not 672 // fail on a pattern in an installed extension. 673 if (URLPattern::PARSE_SUCCESS != pattern.Parse( 674 *i, URLPattern::PARSE_LENIENT)) { 675 NOTREACHED(); // Corrupt prefs? Hand editing? 676 } else { 677 if (!allow_file_access && pattern.MatchesScheme(chrome::kFileScheme)) { 678 pattern.set_valid_schemes( 679 pattern.valid_schemes() & ~URLPattern::SCHEME_FILE); 680 } 681 host_extent->AddPattern(pattern); 682 } 683 } 684 685 return true; 686 } 687 688 void ExtensionPrefs::AddGrantedPermissions( 689 const std::string& extension_id, 690 const bool full_access, 691 const std::set<std::string>& api_permissions, 692 const ExtensionExtent& host_extent) { 693 CHECK(Extension::IdIsValid(extension_id)); 694 695 UpdateExtensionPref(extension_id, kPrefGrantedPermissionsAll, 696 Value::CreateBooleanValue(full_access)); 697 698 if (!api_permissions.empty()) { 699 AddToExtensionPrefStringSet( 700 extension_id, kPrefGrantedPermissionsAPI, api_permissions); 701 } 702 703 if (!host_extent.is_empty()) { 704 std::set<std::string> host_permissions; 705 ExtentToStringSet(host_extent, &host_permissions); 706 707 AddToExtensionPrefStringSet( 708 extension_id, kPrefGrantedPermissionsHost, host_permissions); 709 } 710 711 SavePrefs(); 712 } 713 714 bool ExtensionPrefs::IsIncognitoEnabled(const std::string& extension_id) { 715 return ReadExtensionPrefBoolean(extension_id, kPrefIncognitoEnabled); 716 } 717 718 void ExtensionPrefs::SetIsIncognitoEnabled(const std::string& extension_id, 719 bool enabled) { 720 UpdateExtensionPref(extension_id, kPrefIncognitoEnabled, 721 Value::CreateBooleanValue(enabled)); 722 SavePrefs(); 723 } 724 725 bool ExtensionPrefs::AllowFileAccess(const std::string& extension_id) { 726 return ReadExtensionPrefBoolean(extension_id, kPrefAllowFileAccess); 727 } 728 729 void ExtensionPrefs::SetAllowFileAccess(const std::string& extension_id, 730 bool allow) { 731 UpdateExtensionPref(extension_id, kPrefAllowFileAccess, 732 Value::CreateBooleanValue(allow)); 733 SavePrefs(); 734 } 735 736 bool ExtensionPrefs::HasAllowFileAccessSetting( 737 const std::string& extension_id) const { 738 const DictionaryValue* ext = GetExtensionPref(extension_id); 739 return ext && ext->HasKey(kPrefAllowFileAccess); 740 } 741 742 ExtensionPrefs::LaunchType ExtensionPrefs::GetLaunchType( 743 const std::string& extension_id, 744 ExtensionPrefs::LaunchType default_pref_value) { 745 int value = -1; 746 LaunchType result = LAUNCH_REGULAR; 747 748 if (ReadExtensionPrefInteger(extension_id, kPrefLaunchType, &value) && 749 (value == LAUNCH_PINNED || 750 value == LAUNCH_REGULAR || 751 value == LAUNCH_FULLSCREEN || 752 value == LAUNCH_WINDOW)) { 753 result = static_cast<LaunchType>(value); 754 } else { 755 result = default_pref_value; 756 } 757 #if defined(OS_MACOSX) 758 // App windows are not yet supported on mac. Pref sync could make 759 // the launch type LAUNCH_WINDOW, even if there is no UI to set it 760 // on mac. 761 if (result == LAUNCH_WINDOW) 762 result = LAUNCH_REGULAR; 763 #endif 764 765 return result; 766 } 767 768 extension_misc::LaunchContainer ExtensionPrefs::GetLaunchContainer( 769 const Extension* extension, 770 ExtensionPrefs::LaunchType default_pref_value) { 771 extension_misc::LaunchContainer manifest_launch_container = 772 extension->launch_container(); 773 774 const extension_misc::LaunchContainer kInvalidLaunchContainer = 775 static_cast<extension_misc::LaunchContainer>(-1); 776 777 extension_misc::LaunchContainer result = kInvalidLaunchContainer; 778 779 if (manifest_launch_container == extension_misc::LAUNCH_PANEL) { 780 // Apps with app.launch.container = 'panel' should always 781 // open in a panel. 782 result = extension_misc::LAUNCH_PANEL; 783 784 } else if (manifest_launch_container == extension_misc::LAUNCH_TAB) { 785 // Look for prefs that indicate the user's choice of launch 786 // container. The app's menu on the NTP provides a UI to set 787 // this preference. If no preference is set, |default_pref_value| 788 // is used. 789 ExtensionPrefs::LaunchType prefs_launch_type = 790 GetLaunchType(extension->id(), default_pref_value); 791 792 if (prefs_launch_type == ExtensionPrefs::LAUNCH_WINDOW) { 793 // If the pref is set to launch a window (or no pref is set, and 794 // window opening is the default), make the container a window. 795 result = extension_misc::LAUNCH_WINDOW; 796 797 } else { 798 // All other launch types (tab, pinned, fullscreen) are 799 // implemented as tabs in a window. 800 result = extension_misc::LAUNCH_TAB; 801 } 802 } else { 803 // If a new value for app.launch.container is added, logic 804 // for it should be added here. extension_misc::LAUNCH_WINDOW 805 // is not present because there is no way to set it in a manifest. 806 NOTREACHED() << manifest_launch_container; 807 } 808 809 // All paths should set |result|. 810 if (result == kInvalidLaunchContainer) { 811 DLOG(FATAL) << "Failed to set a launch container."; 812 result = extension_misc::LAUNCH_TAB; 813 } 814 815 return result; 816 } 817 818 void ExtensionPrefs::SetLaunchType(const std::string& extension_id, 819 LaunchType launch_type) { 820 UpdateExtensionPref(extension_id, kPrefLaunchType, 821 Value::CreateIntegerValue(static_cast<int>(launch_type))); 822 SavePrefs(); 823 } 824 825 bool ExtensionPrefs::IsExternalExtensionUninstalled( 826 const std::string& id) const { 827 const DictionaryValue* extension = GetExtensionPref(id); 828 if (!extension) 829 return false; 830 int state = 0; 831 return extension->GetInteger(kPrefState, &state) && 832 state == static_cast<int>(Extension::EXTERNAL_EXTENSION_UNINSTALLED); 833 } 834 835 std::vector<std::string> ExtensionPrefs::GetToolbarOrder() { 836 ExtensionPrefs::ExtensionIdSet extension_ids; 837 const ListValue* toolbar_order = prefs_->GetList(kExtensionToolbar); 838 if (toolbar_order) { 839 for (size_t i = 0; i < toolbar_order->GetSize(); ++i) { 840 std::string extension_id; 841 if (toolbar_order->GetString(i, &extension_id)) 842 extension_ids.push_back(extension_id); 843 } 844 } 845 return extension_ids; 846 } 847 848 void ExtensionPrefs::SetToolbarOrder( 849 const std::vector<std::string>& extension_ids) { 850 ListPrefUpdate update(prefs_, kExtensionToolbar); 851 ListValue* toolbar_order = update.Get(); 852 toolbar_order->Clear(); 853 for (std::vector<std::string>::const_iterator iter = extension_ids.begin(); 854 iter != extension_ids.end(); ++iter) { 855 toolbar_order->Append(new StringValue(*iter)); 856 } 857 SavePrefs(); 858 } 859 860 void ExtensionPrefs::OnExtensionInstalled( 861 const Extension* extension, Extension::State initial_state, 862 bool initial_incognito_enabled) { 863 const std::string& id = extension->id(); 864 CHECK(Extension::IdIsValid(id)); 865 ScopedExtensionPrefUpdate update(prefs_, id); 866 DictionaryValue* extension_dict = update.Get(); 867 const base::Time install_time = GetCurrentTime(); 868 extension_dict->Set(kPrefState, Value::CreateIntegerValue(initial_state)); 869 extension_dict->Set(kPrefIncognitoEnabled, 870 Value::CreateBooleanValue(initial_incognito_enabled)); 871 extension_dict->Set(kPrefLocation, 872 Value::CreateIntegerValue(extension->location())); 873 extension_dict->Set(kPrefInstallTime, 874 Value::CreateStringValue( 875 base::Int64ToString(install_time.ToInternalValue()))); 876 extension_dict->Set(kPrefPreferences, new DictionaryValue()); 877 878 FilePath::StringType path = MakePathRelative(install_directory_, 879 extension->path()); 880 extension_dict->Set(kPrefPath, Value::CreateStringValue(path)); 881 // We store prefs about LOAD extensions, but don't cache their manifest 882 // since it may change on disk. 883 if (extension->location() != Extension::LOAD) { 884 extension_dict->Set(kPrefManifest, 885 extension->manifest_value()->DeepCopy()); 886 } 887 extension_dict->Set(kPrefAppLaunchIndex, 888 Value::CreateIntegerValue(GetNextAppLaunchIndex())); 889 extension_pref_value_map_->RegisterExtension( 890 id, install_time, initial_state == Extension::ENABLED); 891 SavePrefs(); 892 } 893 894 void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id, 895 const Extension::Location& location, 896 bool external_uninstall) { 897 // For external extensions, we save a preference reminding ourself not to try 898 // and install the extension anymore (except when |external_uninstall| is 899 // true, which signifies that the registry key was deleted or the pref file 900 // no longer lists the extension). 901 if (!external_uninstall && Extension::IsExternalLocation(location)) { 902 UpdateExtensionPref(extension_id, kPrefState, 903 Value::CreateIntegerValue( 904 Extension::EXTERNAL_EXTENSION_UNINSTALLED)); 905 SavePrefs(); 906 extension_pref_value_map_->SetExtensionState(extension_id, false); 907 } else { 908 DeleteExtensionPrefs(extension_id); 909 } 910 } 911 912 Extension::State ExtensionPrefs::GetExtensionState( 913 const std::string& extension_id) const { 914 const DictionaryValue* extension = GetExtensionPref(extension_id); 915 916 // If the extension doesn't have a pref, it's a --load-extension. 917 if (!extension) 918 return Extension::ENABLED; 919 920 int state = -1; 921 if (!extension->GetInteger(kPrefState, &state) || 922 state < 0 || state >= Extension::NUM_STATES) { 923 LOG(ERROR) << "Bad or missing pref 'state' for extension '" 924 << extension_id << "'"; 925 return Extension::ENABLED; 926 } 927 return static_cast<Extension::State>(state); 928 } 929 930 void ExtensionPrefs::SetExtensionState(const Extension* extension, 931 Extension::State state) { 932 UpdateExtensionPref(extension->id(), kPrefState, 933 Value::CreateIntegerValue(state)); 934 SavePrefs(); 935 936 bool enabled = (state == Extension::ENABLED); 937 extension_pref_value_map_->SetExtensionState(extension->id(), enabled); 938 } 939 940 bool ExtensionPrefs::GetBrowserActionVisibility(const Extension* extension) { 941 const DictionaryValue* extension_prefs = GetExtensionPref(extension->id()); 942 if (!extension_prefs) 943 return true; 944 bool visible = false; 945 if (!extension_prefs->GetBoolean(kBrowserActionVisible, &visible) || visible) 946 return true; 947 948 return false; 949 } 950 951 void ExtensionPrefs::SetBrowserActionVisibility(const Extension* extension, 952 bool visible) { 953 if (GetBrowserActionVisibility(extension) == visible) 954 return; 955 956 UpdateExtensionPref(extension->id(), kBrowserActionVisible, 957 Value::CreateBooleanValue(visible)); 958 SavePrefs(); 959 960 NotificationService::current()->Notify( 961 NotificationType::EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED, 962 Source<ExtensionPrefs>(this), 963 Details<const Extension>(extension)); 964 } 965 966 std::string ExtensionPrefs::GetVersionString(const std::string& extension_id) { 967 const DictionaryValue* extension = GetExtensionPref(extension_id); 968 if (!extension) 969 return std::string(); 970 971 std::string version; 972 if (!extension->GetString(kPrefVersion, &version)) { 973 LOG(ERROR) << "Bad or missing pref 'version' for extension '" 974 << extension_id << "'"; 975 } 976 977 return version; 978 } 979 980 void ExtensionPrefs::UpdateManifest(const Extension* extension) { 981 if (extension->location() != Extension::LOAD) { 982 const DictionaryValue* extension_dict = GetExtensionPref(extension->id()); 983 if (!extension_dict) 984 return; 985 DictionaryValue* old_manifest = NULL; 986 bool update_required = 987 !extension_dict->GetDictionary(kPrefManifest, &old_manifest) || 988 !extension->manifest_value()->Equals(old_manifest); 989 if (update_required) { 990 UpdateExtensionPref(extension->id(), kPrefManifest, 991 extension->manifest_value()->DeepCopy()); 992 } 993 SavePrefs(); 994 } 995 } 996 997 FilePath ExtensionPrefs::GetExtensionPath(const std::string& extension_id) { 998 const DictionaryValue* dict = prefs_->GetDictionary(kExtensionsPref); 999 if (!dict || dict->empty()) 1000 return FilePath(); 1001 1002 std::string path; 1003 if (!dict->GetString(extension_id + "." + kPrefPath, &path)) 1004 return FilePath(); 1005 1006 return install_directory_.Append(FilePath::FromWStringHack(UTF8ToWide(path))); 1007 } 1008 1009 void ExtensionPrefs::UpdateExtensionPref(const std::string& extension_id, 1010 const std::string& key, 1011 Value* data_value) { 1012 if (!Extension::IdIsValid(extension_id)) { 1013 NOTREACHED() << "Invalid extension_id " << extension_id; 1014 return; 1015 } 1016 ScopedExtensionPrefUpdate update(prefs_, extension_id); 1017 DictionaryValue* extension = update.Get(); 1018 extension->Set(key, data_value); 1019 } 1020 1021 void ExtensionPrefs::DeleteExtensionPrefs(const std::string& extension_id) { 1022 DictionaryPrefUpdate update(prefs_, kExtensionsPref); 1023 DictionaryValue* dict = update.Get(); 1024 if (dict->HasKey(extension_id)) { 1025 dict->Remove(extension_id, NULL); 1026 SavePrefs(); 1027 } 1028 extension_pref_value_map_->UnregisterExtension(extension_id); 1029 } 1030 1031 const DictionaryValue* ExtensionPrefs::GetExtensionPref( 1032 const std::string& extension_id) const { 1033 const DictionaryValue* dict = prefs_->GetDictionary(kExtensionsPref); 1034 if (!dict) 1035 return NULL; 1036 DictionaryValue* extension = NULL; 1037 dict->GetDictionary(extension_id, &extension); 1038 return extension; 1039 } 1040 1041 // Helper function for GetInstalledExtensionsInfo. 1042 static ExtensionInfo* GetInstalledExtensionInfoImpl( 1043 DictionaryValue* extension_data, 1044 DictionaryValue::key_iterator extension_id) { 1045 DictionaryValue* ext; 1046 if (!extension_data->GetDictionaryWithoutPathExpansion(*extension_id, &ext)) { 1047 LOG(WARNING) << "Invalid pref for extension " << *extension_id; 1048 NOTREACHED(); 1049 return NULL; 1050 } 1051 if (ext->HasKey(kPrefBlacklist)) { 1052 bool is_blacklisted = false; 1053 if (!ext->GetBoolean(kPrefBlacklist, &is_blacklisted)) { 1054 NOTREACHED() << "Invalid blacklist pref:" << *extension_id; 1055 return NULL; 1056 } 1057 if (is_blacklisted) { 1058 return NULL; 1059 } 1060 } 1061 int state_value; 1062 if (!ext->GetInteger(kPrefState, &state_value)) { 1063 // This can legitimately happen if we store preferences for component 1064 // extensions. 1065 return NULL; 1066 } 1067 if (state_value == Extension::EXTERNAL_EXTENSION_UNINSTALLED) { 1068 LOG(WARNING) << "External extension with id " << *extension_id 1069 << " has been uninstalled by the user"; 1070 return NULL; 1071 } 1072 FilePath::StringType path; 1073 if (!ext->GetString(kPrefPath, &path)) { 1074 return NULL; 1075 } 1076 int location_value; 1077 if (!ext->GetInteger(kPrefLocation, &location_value)) { 1078 return NULL; 1079 } 1080 1081 // Only the following extension types can be installed permanently in the 1082 // preferences. 1083 Extension::Location location = 1084 static_cast<Extension::Location>(location_value); 1085 if (location != Extension::INTERNAL && 1086 location != Extension::LOAD && 1087 !Extension::IsExternalLocation(location)) { 1088 NOTREACHED(); 1089 return NULL; 1090 } 1091 1092 DictionaryValue* manifest = NULL; 1093 if (location != Extension::LOAD && 1094 !ext->GetDictionary(kPrefManifest, &manifest)) { 1095 LOG(WARNING) << "Missing manifest for extension " << *extension_id; 1096 // Just a warning for now. 1097 } 1098 1099 return new ExtensionInfo(manifest, *extension_id, FilePath(path), location); 1100 } 1101 1102 ExtensionPrefs::ExtensionsInfo* ExtensionPrefs::GetInstalledExtensionsInfo() { 1103 scoped_ptr<DictionaryValue> extension_data(CopyCurrentExtensions()); 1104 1105 ExtensionsInfo* extensions_info = new ExtensionsInfo; 1106 1107 for (DictionaryValue::key_iterator extension_id( 1108 extension_data->begin_keys()); 1109 extension_id != extension_data->end_keys(); ++extension_id) { 1110 if (!Extension::IdIsValid(*extension_id)) 1111 continue; 1112 1113 ExtensionInfo* info = GetInstalledExtensionInfoImpl(extension_data.get(), 1114 extension_id); 1115 if (info) 1116 extensions_info->push_back(linked_ptr<ExtensionInfo>(info)); 1117 } 1118 1119 return extensions_info; 1120 } 1121 1122 ExtensionInfo* ExtensionPrefs::GetInstalledExtensionInfo( 1123 const std::string& extension_id) { 1124 scoped_ptr<DictionaryValue> extension_data(CopyCurrentExtensions()); 1125 1126 for (DictionaryValue::key_iterator extension_iter( 1127 extension_data->begin_keys()); 1128 extension_iter != extension_data->end_keys(); ++extension_iter) { 1129 if (*extension_iter == extension_id) { 1130 return GetInstalledExtensionInfoImpl(extension_data.get(), 1131 extension_iter); 1132 } 1133 } 1134 1135 return NULL; 1136 } 1137 1138 void ExtensionPrefs::SetIdleInstallInfo(const std::string& extension_id, 1139 const FilePath& crx_path, 1140 const std::string& version, 1141 const base::Time& fetch_time) { 1142 ScopedExtensionPrefUpdate update(prefs_, extension_id); 1143 DictionaryValue* extension_prefs = update.Get(); 1144 if (!extension_prefs) { 1145 NOTREACHED(); 1146 return; 1147 } 1148 extension_prefs->Remove(kIdleInstallInfo, NULL); 1149 DictionaryValue* info = new DictionaryValue(); 1150 info->SetString(kIdleInstallInfoCrxPath, crx_path.value()); 1151 info->SetString(kIdleInstallInfoVersion, version); 1152 info->SetString(kIdleInstallInfoFetchTime, 1153 base::Int64ToString(fetch_time.ToInternalValue())); 1154 extension_prefs->Set(kIdleInstallInfo, info); 1155 SavePrefs(); 1156 } 1157 1158 bool ExtensionPrefs::RemoveIdleInstallInfo(const std::string& extension_id) { 1159 if (!GetExtensionPref(extension_id)) 1160 return false; 1161 ScopedExtensionPrefUpdate update(prefs_, extension_id); 1162 DictionaryValue* extension_prefs = update.Get(); 1163 bool result = extension_prefs->Remove(kIdleInstallInfo, NULL); 1164 SavePrefs(); 1165 return result; 1166 } 1167 1168 bool ExtensionPrefs::GetIdleInstallInfo(const std::string& extension_id, 1169 FilePath* crx_path, 1170 std::string* version, 1171 base::Time* fetch_time) { 1172 const DictionaryValue* extension_prefs = GetExtensionPref(extension_id); 1173 if (!extension_prefs) 1174 return false; 1175 1176 // Do all the reads from the prefs together, and don't do any assignment 1177 // to the out parameters unless all the reads succeed. 1178 DictionaryValue* info = NULL; 1179 if (!extension_prefs->GetDictionary(kIdleInstallInfo, &info)) 1180 return false; 1181 1182 FilePath::StringType path_string; 1183 if (!info->GetString(kIdleInstallInfoCrxPath, &path_string)) 1184 return false; 1185 1186 std::string tmp_version; 1187 if (!info->GetString(kIdleInstallInfoVersion, &tmp_version)) 1188 return false; 1189 1190 std::string fetch_time_string; 1191 if (!info->GetString(kIdleInstallInfoFetchTime, &fetch_time_string)) 1192 return false; 1193 1194 int64 fetch_time_value; 1195 if (!base::StringToInt64(fetch_time_string, &fetch_time_value)) 1196 return false; 1197 1198 if (crx_path) 1199 *crx_path = FilePath(path_string); 1200 1201 if (version) 1202 *version = tmp_version; 1203 1204 if (fetch_time) 1205 *fetch_time = base::Time::FromInternalValue(fetch_time_value); 1206 1207 return true; 1208 } 1209 1210 std::set<std::string> ExtensionPrefs::GetIdleInstallInfoIds() { 1211 std::set<std::string> result; 1212 1213 const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref); 1214 if (!extensions) 1215 return result; 1216 1217 for (DictionaryValue::key_iterator iter = extensions->begin_keys(); 1218 iter != extensions->end_keys(); ++iter) { 1219 const std::string& id(*iter); 1220 if (!Extension::IdIsValid(id)) { 1221 NOTREACHED(); 1222 continue; 1223 } 1224 1225 const DictionaryValue* extension_prefs = GetExtensionPref(id); 1226 if (!extension_prefs) 1227 continue; 1228 1229 if (extension_prefs->GetDictionary(kIdleInstallInfo, NULL)) 1230 result.insert(id); 1231 } 1232 return result; 1233 } 1234 1235 bool ExtensionPrefs::GetWebStoreLogin(std::string* result) { 1236 if (prefs_->HasPrefPath(kWebStoreLogin)) { 1237 *result = prefs_->GetString(kWebStoreLogin); 1238 return true; 1239 } 1240 return false; 1241 } 1242 1243 void ExtensionPrefs::SetWebStoreLogin(const std::string& login) { 1244 prefs_->SetString(kWebStoreLogin, login); 1245 SavePrefs(); 1246 } 1247 1248 int ExtensionPrefs::GetAppLaunchIndex(const std::string& extension_id) { 1249 int value; 1250 if (ReadExtensionPrefInteger(extension_id, kPrefAppLaunchIndex, &value)) 1251 return value; 1252 1253 return -1; 1254 } 1255 1256 void ExtensionPrefs::SetAppLaunchIndex(const std::string& extension_id, 1257 int index) { 1258 DCHECK_GE(index, 0); 1259 UpdateExtensionPref(extension_id, kPrefAppLaunchIndex, 1260 Value::CreateIntegerValue(index)); 1261 SavePrefs(); 1262 } 1263 1264 int ExtensionPrefs::GetNextAppLaunchIndex() { 1265 const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref); 1266 if (!extensions) 1267 return 0; 1268 1269 int max_value = -1; 1270 for (DictionaryValue::key_iterator extension_id = extensions->begin_keys(); 1271 extension_id != extensions->end_keys(); ++extension_id) { 1272 int value = GetAppLaunchIndex(*extension_id); 1273 if (value > max_value) 1274 max_value = value; 1275 } 1276 return max_value + 1; 1277 } 1278 1279 void ExtensionPrefs::SetAppLauncherOrder( 1280 const std::vector<std::string>& extension_ids) { 1281 for (size_t i = 0; i < extension_ids.size(); ++i) 1282 SetAppLaunchIndex(extension_ids.at(i), i); 1283 1284 NotificationService::current()->Notify( 1285 NotificationType::EXTENSION_LAUNCHER_REORDERED, 1286 Source<ExtensionPrefs>(this), 1287 NotificationService::NoDetails()); 1288 } 1289 1290 int ExtensionPrefs::GetPageIndex(const std::string& extension_id) { 1291 int value; 1292 if (ReadExtensionPrefInteger(extension_id, kPrefPageIndex, &value)) 1293 return value; 1294 1295 return -1; 1296 } 1297 1298 void ExtensionPrefs::SetPageIndex(const std::string& extension_id, int index) { 1299 CHECK_GE(index, 0); 1300 UpdateExtensionPref(extension_id, kPrefPageIndex, 1301 Value::CreateIntegerValue(index)); 1302 SavePrefs(); 1303 } 1304 1305 bool ExtensionPrefs::WasAppDraggedByUser(const std::string& extension_id) { 1306 const DictionaryValue* dictionary = GetExtensionPref(extension_id); 1307 if (!dictionary) { 1308 NOTREACHED(); 1309 return false; 1310 } 1311 1312 return ReadBooleanFromPref(dictionary, kPrefUserDraggedApp); 1313 } 1314 1315 void ExtensionPrefs::SetAppDraggedByUser(const std::string& extension_id) { 1316 if (!GetExtensionPref(extension_id)) { 1317 NOTREACHED(); 1318 return; 1319 } 1320 1321 ScopedExtensionPrefUpdate update(prefs_, extension_id); 1322 DictionaryValue* dictionary = update.Get(); 1323 dictionary->SetBoolean(kPrefUserDraggedApp, true); 1324 SavePrefs(); 1325 } 1326 1327 void ExtensionPrefs::SetUpdateUrlData(const std::string& extension_id, 1328 const std::string& data) { 1329 if (!GetExtensionPref(extension_id)) { 1330 NOTREACHED(); 1331 return; 1332 } 1333 1334 ScopedExtensionPrefUpdate update(prefs_, extension_id); 1335 DictionaryValue* dictionary = update.Get(); 1336 dictionary->SetString(kUpdateUrlData, data); 1337 SavePrefs(); 1338 } 1339 1340 std::string ExtensionPrefs::GetUpdateUrlData(const std::string& extension_id) { 1341 const DictionaryValue* dictionary = GetExtensionPref(extension_id); 1342 if (!dictionary) 1343 return std::string(); 1344 1345 std::string data; 1346 dictionary->GetString(kUpdateUrlData, &data); 1347 return data; 1348 } 1349 1350 base::Time ExtensionPrefs::GetCurrentTime() const { 1351 return base::Time::Now(); 1352 } 1353 1354 base::Time ExtensionPrefs::GetInstallTime( 1355 const std::string& extension_id) const { 1356 const DictionaryValue* extension = GetExtensionPref(extension_id); 1357 if (!extension) { 1358 NOTREACHED(); 1359 return base::Time(); 1360 } 1361 std::string install_time_str; 1362 if (!extension->GetString(kPrefInstallTime, &install_time_str)) 1363 return base::Time(); 1364 int64 install_time_i64 = 0; 1365 if (!base::StringToInt64(install_time_str, &install_time_i64)) 1366 return base::Time(); 1367 return base::Time::FromInternalValue(install_time_i64); 1368 } 1369 1370 void ExtensionPrefs::GetExtensions(ExtensionIdSet* out) { 1371 CHECK(out); 1372 1373 scoped_ptr<ExtensionsInfo> extensions_info(GetInstalledExtensionsInfo()); 1374 1375 for (size_t i = 0; i < extensions_info->size(); ++i) { 1376 ExtensionInfo* info = extensions_info->at(i).get(); 1377 out->push_back(info->extension_id); 1378 } 1379 } 1380 1381 void ExtensionPrefs::FixMissingPrefs(const ExtensionIdSet& extension_ids) { 1382 // Fix old entries that did not get an installation time entry when they 1383 // were installed or don't have a preferences field. 1384 bool persist_required = false; 1385 for (ExtensionIdSet::const_iterator ext_id = extension_ids.begin(); 1386 ext_id != extension_ids.end(); ++ext_id) { 1387 if (GetInstallTime(*ext_id) == base::Time()) { 1388 LOG(INFO) << "Could not parse installation time of extension " 1389 << *ext_id << ". It was probably installed before setting " 1390 << kPrefInstallTime << " was introduced. Updating " 1391 << kPrefInstallTime << " to the current time."; 1392 const base::Time install_time = GetCurrentTime(); 1393 ScopedExtensionPrefUpdate update(prefs_, *ext_id); 1394 DictionaryValue* extension = update.Get(); 1395 extension->Set(kPrefInstallTime, 1396 Value::CreateStringValue( 1397 base::Int64ToString(install_time.ToInternalValue()))); 1398 persist_required = true; 1399 } 1400 } 1401 if (persist_required) 1402 SavePrefs(); 1403 } 1404 1405 const DictionaryValue* ExtensionPrefs::GetExtensionControlledPrefs( 1406 const std::string& extension_id) const { 1407 std::string key = extension_id + std::string(".") + kPrefPreferences; 1408 DictionaryValue* preferences = NULL; 1409 // First try the regular lookup. 1410 { 1411 const DictionaryValue* source_dict = prefs_->GetDictionary(kExtensionsPref); 1412 if (source_dict->GetDictionary(key, &preferences)) 1413 return preferences; 1414 } 1415 // And then create a dictionary if it did not exist before. 1416 { 1417 DictionaryPrefUpdate update(prefs_, kExtensionsPref); 1418 update.Get()->Set(key, new DictionaryValue); 1419 } 1420 const DictionaryValue* source_dict = prefs_->GetDictionary(kExtensionsPref); 1421 source_dict->GetDictionary(key, &preferences); 1422 return preferences; 1423 } 1424 1425 void ExtensionPrefs::InitPrefStore() { 1426 // When this is called, the PrefService is initialized and provides access 1427 // to the user preferences stored in a JSON file. 1428 ExtensionIdSet extension_ids; 1429 GetExtensions(&extension_ids); 1430 // Create empty preferences dictionary for each extension (these dictionaries 1431 // are pruned when persisting the preferneces to disk). 1432 { 1433 DictionaryPrefUpdate update(prefs_, kExtensionsPref); 1434 const DictionaryValue* source_dict = prefs_->GetDictionary(kExtensionsPref); 1435 for (ExtensionIdSet::iterator ext_id = extension_ids.begin(); 1436 ext_id != extension_ids.end(); ++ext_id) { 1437 std::string key = *ext_id + std::string(".") + kPrefPreferences; 1438 if (!source_dict->GetDictionary(key, NULL)) 1439 update.Get()->Set(key, new DictionaryValue); 1440 } 1441 } 1442 1443 FixMissingPrefs(extension_ids); 1444 // Store extension controlled preference values in the 1445 // |extension_pref_value_map_|, which then informs the subscribers 1446 // (ExtensionPrefStores) about the winning values. 1447 for (ExtensionIdSet::iterator ext_id = extension_ids.begin(); 1448 ext_id != extension_ids.end(); ++ext_id) { 1449 extension_pref_value_map_->RegisterExtension( 1450 *ext_id, 1451 GetInstallTime(*ext_id), 1452 GetExtensionState(*ext_id) == Extension::ENABLED); 1453 1454 const DictionaryValue* prefs = GetExtensionControlledPrefs(*ext_id); 1455 for (DictionaryValue::key_iterator i = prefs->begin_keys(); 1456 i != prefs->end_keys(); ++i) { 1457 Value* value; 1458 if (!prefs->GetWithoutPathExpansion(*i, &value)) 1459 continue; 1460 extension_pref_value_map_->SetExtensionPref( 1461 *ext_id, *i, false, value->DeepCopy()); 1462 } 1463 } 1464 1465 extension_pref_value_map_->NotifyInitializationCompleted(); 1466 } 1467 1468 1469 void ExtensionPrefs::SetExtensionControlledPref(const std::string& extension_id, 1470 const std::string& pref_key, 1471 bool incognito, 1472 Value* value) { 1473 #ifndef NDEBUG 1474 const PrefService::Preference* pref = 1475 pref_service()->FindPreference(pref_key.c_str()); 1476 DCHECK(pref) << "Extension controlled preference key " << pref_key 1477 << " not registered."; 1478 DCHECK_EQ(pref->GetType(), value->GetType()) 1479 << "Extension controlled preference " << pref_key << " has wrong type."; 1480 #endif 1481 1482 if (!incognito) { 1483 // Also store in persisted Preferences file to recover after a 1484 // browser restart. 1485 ScopedExtensionControlledPrefUpdate update(prefs_, extension_id); 1486 DictionaryValue* dict = update.Get(); 1487 dict->SetWithoutPathExpansion(pref_key, value->DeepCopy()); 1488 pref_service()->ScheduleSavePersistentPrefs(); 1489 } 1490 1491 extension_pref_value_map_->SetExtensionPref( 1492 extension_id, pref_key, incognito, value); 1493 } 1494 1495 void ExtensionPrefs::RemoveExtensionControlledPref( 1496 const std::string& extension_id, 1497 const std::string& pref_key, 1498 bool incognito) { 1499 DCHECK(pref_service()->FindPreference(pref_key.c_str())) 1500 << "Extension controlled preference key " << pref_key 1501 << " not registered."; 1502 1503 if (!incognito) { 1504 // Also store in persisted Preferences file to recover after a 1505 // browser restart. 1506 ScopedExtensionControlledPrefUpdate update(prefs_, extension_id); 1507 DictionaryValue* dict = update.Get(); 1508 dict->RemoveWithoutPathExpansion(pref_key, NULL); 1509 pref_service()->ScheduleSavePersistentPrefs(); 1510 } 1511 1512 extension_pref_value_map_->RemoveExtensionPref( 1513 extension_id, pref_key, incognito); 1514 } 1515 1516 bool ExtensionPrefs::CanExtensionControlPref(const std::string& extension_id, 1517 const std::string& pref_key, 1518 bool incognito) { 1519 DCHECK(pref_service()->FindPreference(pref_key.c_str())) 1520 << "Extension controlled preference key " << pref_key 1521 << " not registered."; 1522 1523 return extension_pref_value_map_->CanExtensionControlPref(extension_id, 1524 pref_key, 1525 incognito); 1526 } 1527 1528 bool ExtensionPrefs::DoesExtensionControlPref(const std::string& extension_id, 1529 const std::string& pref_key, 1530 bool incognito) { 1531 DCHECK(pref_service()->FindPreference(pref_key.c_str())) 1532 << "Extension controlled preference key " << pref_key 1533 << " not registered."; 1534 1535 return extension_pref_value_map_->DoesExtensionControlPref(extension_id, 1536 pref_key, 1537 incognito); 1538 } 1539 1540 bool ExtensionPrefs::HasIncognitoPrefValue(const std::string& pref_key) { 1541 bool has_incognito_pref_value = false; 1542 extension_pref_value_map_->GetEffectivePrefValue(pref_key, 1543 true, 1544 &has_incognito_pref_value); 1545 return has_incognito_pref_value; 1546 } 1547 1548 // static 1549 void ExtensionPrefs::RegisterUserPrefs(PrefService* prefs) { 1550 prefs->RegisterDictionaryPref(kExtensionsPref); 1551 prefs->RegisterListPref(kExtensionToolbar); 1552 prefs->RegisterIntegerPref(prefs::kExtensionToolbarSize, -1); 1553 prefs->RegisterDictionaryPref(kExtensionsBlacklistUpdate); 1554 prefs->RegisterListPref(prefs::kExtensionInstallAllowList); 1555 prefs->RegisterListPref(prefs::kExtensionInstallDenyList); 1556 prefs->RegisterListPref(prefs::kExtensionInstallForceList); 1557 prefs->RegisterStringPref(kWebStoreLogin, std::string() /* default_value */); 1558 } 1559