Home | History | Annotate | Download | only in extensions
      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