Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/extensions/extension_prefs.h"
      6 
      7 #include "base/prefs/pref_notifier.h"
      8 #include "base/prefs/pref_service.h"
      9 #include "base/strings/string_number_conversions.h"
     10 #include "base/strings/string_util.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "base/value_conversions.h"
     13 #include "chrome/browser/chrome_notification_types.h"
     14 #include "chrome/browser/extensions/admin_policy.h"
     15 #include "chrome/browser/extensions/api/content_settings/content_settings_store.h"
     16 #include "chrome/browser/extensions/api/preference/preference_api.h"
     17 #include "chrome/browser/extensions/event_router.h"
     18 #include "chrome/browser/extensions/extension_pref_store.h"
     19 #include "chrome/browser/extensions/extension_prefs_factory.h"
     20 #include "chrome/browser/extensions/extension_sorting.h"
     21 #include "chrome/browser/profiles/profile.h"
     22 #include "chrome/browser/ui/host_desktop.h"
     23 #include "chrome/common/chrome_switches.h"
     24 #include "chrome/common/extensions/feature_switch.h"
     25 #include "chrome/common/extensions/manifest.h"
     26 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
     27 #include "chrome/common/extensions/permissions/permission_set.h"
     28 #include "chrome/common/extensions/permissions/permissions_info.h"
     29 #include "chrome/common/pref_names.h"
     30 #include "chrome/common/url_constants.h"
     31 #include "components/user_prefs/pref_registry_syncable.h"
     32 #include "content/public/browser/notification_service.h"
     33 #include "extensions/browser/pref_names.h"
     34 #include "extensions/common/url_pattern.h"
     35 #include "extensions/common/user_script.h"
     36 #include "grit/generated_resources.h"
     37 #include "ui/base/l10n/l10n_util.h"
     38 
     39 #if defined(USE_ASH)
     40 #include "ash/shell.h"
     41 #endif
     42 #if defined(OS_WIN)
     43 #include "win8/util/win8_util.h"
     44 #endif  // OS_WIN
     45 
     46 using base::Value;
     47 using base::DictionaryValue;
     48 using base::ListValue;
     49 
     50 namespace extensions {
     51 
     52 namespace {
     53 
     54 // Additional preferences keys, which are not needed by external clients.
     55 
     56 // True if this extension is running. Note this preference stops getting updated
     57 // during Chrome shutdown (and won't be updated on a browser crash) and so can
     58 // be used at startup to determine whether the extension was running when Chrome
     59 // was last terminated.
     60 const char kPrefRunning[] = "running";
     61 
     62 // Whether this extension had windows when it was last running.
     63 const char kIsActive[] = "is_active";
     64 
     65 // Where an extension was installed from. (see Manifest::Location)
     66 const char kPrefLocation[] = "location";
     67 
     68 // Enabled, disabled, killed, etc. (see Extension::State)
     69 const char kPrefState[] = "state";
     70 
     71 // The path to the current version's manifest file.
     72 const char kPrefPath[] = "path";
     73 
     74 // The dictionary containing the extension's manifest.
     75 const char kPrefManifest[] = "manifest";
     76 
     77 // The version number.
     78 const char kPrefVersion[] = "manifest.version";
     79 
     80 // Indicates whether an extension is blacklisted.
     81 const char kPrefBlacklist[] = "blacklist";
     82 
     83 // The count of how many times we prompted the user to acknowledge an
     84 // extension.
     85 const char kPrefAcknowledgePromptCount[] = "ack_prompt_count";
     86 
     87 // Indicates whether the user has acknowledged various types of extensions.
     88 const char kPrefExternalAcknowledged[] = "ack_external";
     89 const char kPrefBlacklistAcknowledged[] = "ack_blacklist";
     90 
     91 // Indicates whether the external extension was installed during the first
     92 // run of this profile.
     93 const char kPrefExternalInstallFirstRun[] = "external_first_run";
     94 
     95 // Indicates whether to show an install warning when the user enables.
     96 const char kExtensionDidEscalatePermissions[] = "install_warning_on_enable";
     97 
     98 // DO NOT USE, use kPrefDisableReasons instead.
     99 // Indicates whether the extension was updated while it was disabled.
    100 const char kDeprecatedPrefDisableReason[] = "disable_reason";
    101 
    102 // A bitmask of all the reasons an extension is disabled.
    103 const char kPrefDisableReasons[] = "disable_reasons";
    104 
    105 // The key for a serialized Time value indicating the start of the day (from the
    106 // server's perspective) an extension last included a "ping" parameter during
    107 // its update check.
    108 const char kLastPingDay[] = "lastpingday";
    109 
    110 // Similar to kLastPingDay, but for "active" instead of "rollcall" pings.
    111 const char kLastActivePingDay[] = "last_active_pingday";
    112 
    113 // A bit we use to keep track of whether we need to do an "active" ping.
    114 const char kActiveBit[] = "active_bit";
    115 
    116 // Path for settings specific to blacklist update.
    117 const char kExtensionsBlacklistUpdate[] = "extensions.blacklistupdate";
    118 
    119 // Path for the delayed install info dictionary preference. The actual string
    120 // value is a legacy artifact for when delayed installs only pertained to
    121 // updates that were waiting for idle.
    122 const char kDelayedInstallInfo[] = "idle_install_info";
    123 
    124 // Reason why the extension's install was delayed.
    125 const char kDelayedInstallReason[] = "delay_install_reason";
    126 
    127 // Path for the suggested page ordinal of a delayed extension install.
    128 const char kPrefSuggestedPageOrdinal[] = "suggested_page_ordinal";
    129 
    130 // A preference that, if true, will allow this extension to run in incognito
    131 // mode.
    132 const char kPrefIncognitoEnabled[] = "incognito";
    133 
    134 // A preference to control whether an extension is allowed to inject script in
    135 // pages with file URLs.
    136 const char kPrefAllowFileAccess[] = "newAllowFileAccess";
    137 // TODO(jstritar): As part of fixing http://crbug.com/91577, we revoked all
    138 // extension file access by renaming the pref. We should eventually clean up
    139 // the old flag and possibly go back to that name.
    140 // const char kPrefAllowFileAccessOld[] = "allowFileAccess";
    141 
    142 // A preference set by the the NTP to persist the desired launch container type
    143 // used for apps.
    144 const char kPrefLaunchType[] = "launchType";
    145 
    146 // A preference specifying if the user dragged the app on the NTP.
    147 const char kPrefUserDraggedApp[] = "user_dragged_app_ntp";
    148 
    149 // Preferences that hold which permissions the user has granted the extension.
    150 // We explicitly keep track of these so that extensions can contain unknown
    151 // permissions, for backwards compatibility reasons, and we can still prompt
    152 // the user to accept them once recognized. We store the active permission
    153 // permissions because they may differ from those defined in the manifest.
    154 const char kPrefActivePermissions[] = "active_permissions";
    155 const char kPrefGrantedPermissions[] = "granted_permissions";
    156 
    157 // The preference names for PermissionSet values.
    158 const char kPrefAPIs[] = "api";
    159 const char kPrefExplicitHosts[] = "explicit_host";
    160 const char kPrefScriptableHosts[] = "scriptable_host";
    161 
    162 // The preference names for the old granted permissions scheme.
    163 const char kPrefOldGrantedFullAccess[] = "granted_permissions.full";
    164 const char kPrefOldGrantedHosts[] = "granted_permissions.host";
    165 const char kPrefOldGrantedAPIs[] = "granted_permissions.api";
    166 
    167 // A preference that indicates when an extension was installed.
    168 const char kPrefInstallTime[] = "install_time";
    169 
    170 // A preference which saves the creation flags for extensions.
    171 const char kPrefCreationFlags[] = "creation_flags";
    172 
    173 // A preference that indicates whether the extension was installed from the
    174 // Chrome Web Store.
    175 const char kPrefFromWebStore[] = "from_webstore";
    176 
    177 // A preference that indicates whether the extension was installed from a
    178 // mock App created from a bookmark.
    179 const char kPrefFromBookmark[] = "from_bookmark";
    180 
    181 // A preference that indicates whether the extension was installed as
    182 // default apps.
    183 const char kPrefWasInstalledByDefault[] = "was_installed_by_default";
    184 
    185 // Key for Geometry Cache preference.
    186 const char kPrefGeometryCache[] = "geometry_cache";
    187 
    188 // Provider of write access to a dictionary storing extension prefs.
    189 class ScopedExtensionPrefUpdate : public DictionaryPrefUpdate {
    190  public:
    191   ScopedExtensionPrefUpdate(PrefService* service,
    192                             const std::string& extension_id) :
    193     DictionaryPrefUpdate(service, ExtensionPrefs::kExtensionsPref),
    194     extension_id_(extension_id) {}
    195 
    196   virtual ~ScopedExtensionPrefUpdate() {
    197   }
    198 
    199   // DictionaryPrefUpdate overrides:
    200   virtual DictionaryValue* Get() OVERRIDE {
    201     DictionaryValue* dict = DictionaryPrefUpdate::Get();
    202     DictionaryValue* extension = NULL;
    203     if (!dict->GetDictionary(extension_id_, &extension)) {
    204       // Extension pref does not exist, create it.
    205       extension = new DictionaryValue();
    206       dict->SetWithoutPathExpansion(extension_id_, extension);
    207     }
    208     return extension;
    209   }
    210 
    211  private:
    212   const std::string extension_id_;
    213 
    214   DISALLOW_COPY_AND_ASSIGN(ScopedExtensionPrefUpdate);
    215 };
    216 
    217 std::string JoinPrefs(const std::string& parent, const char* child) {
    218   return parent + "." + child;
    219 }
    220 
    221 // Checks if kPrefBlacklist is set to true in the DictionaryValue.
    222 // Return false if the value is false or kPrefBlacklist does not exist.
    223 // This is used to decide if an extension is blacklisted.
    224 bool IsBlacklistBitSet(const DictionaryValue* ext) {
    225   bool bool_value;
    226   return ext->GetBoolean(kPrefBlacklist, &bool_value) && bool_value;
    227 }
    228 
    229 }  // namespace
    230 
    231 //
    232 // TimeProvider
    233 //
    234 
    235 ExtensionPrefs::TimeProvider::TimeProvider() {
    236 }
    237 
    238 ExtensionPrefs::TimeProvider::~TimeProvider() {
    239 }
    240 
    241 base::Time ExtensionPrefs::TimeProvider::GetCurrentTime() const {
    242   return base::Time::Now();
    243 }
    244 
    245 //
    246 // ScopedUpdate
    247 //
    248 template <typename T, base::Value::Type type_enum_value>
    249 ExtensionPrefs::ScopedUpdate<T, type_enum_value>::ScopedUpdate(
    250     ExtensionPrefs* prefs,
    251     const std::string& extension_id,
    252     const std::string& key)
    253     : update_(prefs->pref_service(), kExtensionsPref),
    254       extension_id_(extension_id),
    255       key_(key) {
    256   DCHECK(Extension::IdIsValid(extension_id_));
    257 }
    258 
    259 template <typename T, base::Value::Type type_enum_value>
    260 ExtensionPrefs::ScopedUpdate<T, type_enum_value>::~ScopedUpdate() {
    261 }
    262 
    263 template <typename T, base::Value::Type type_enum_value>
    264 T* ExtensionPrefs::ScopedUpdate<T, type_enum_value>::Get() {
    265   DictionaryValue* dict = update_.Get();
    266   DictionaryValue* extension = NULL;
    267   Value* key_value = NULL;
    268   if (!dict->GetDictionary(extension_id_, &extension) ||
    269       !extension->Get(key_, &key_value)) {
    270     return NULL;
    271   }
    272   return key_value->GetType() == type_enum_value ?
    273       static_cast<T*>(key_value) :
    274       NULL;
    275 }
    276 
    277 template <typename T, base::Value::Type type_enum_value>
    278 T* ExtensionPrefs::ScopedUpdate<T, type_enum_value>::Create() {
    279   DictionaryValue* dict = update_.Get();
    280   DictionaryValue* extension = NULL;
    281   Value* key_value = NULL;
    282   T* value_as_t = NULL;
    283   if (!dict->GetDictionary(extension_id_, &extension)) {
    284     extension = new base::DictionaryValue;
    285     dict->SetWithoutPathExpansion(extension_id_, extension);
    286   }
    287   if (!extension->Get(key_, &key_value)) {
    288     value_as_t = new T;
    289     extension->SetWithoutPathExpansion(key_, value_as_t);
    290   } else {
    291     CHECK(key_value->GetType() == type_enum_value);
    292     value_as_t = static_cast<T*>(key_value);
    293   }
    294   return value_as_t;
    295 }
    296 
    297 // Explicit instantiations for Dictionary and List value types.
    298 template class ExtensionPrefs::ScopedUpdate<DictionaryValue,
    299                                             Value::TYPE_DICTIONARY>;
    300 template class ExtensionPrefs::ScopedUpdate<ListValue, Value::TYPE_LIST>;
    301 
    302 //
    303 // ExtensionPrefs
    304 //
    305 
    306 // static
    307 ExtensionPrefs* ExtensionPrefs::Create(
    308     PrefService* prefs,
    309     const base::FilePath& root_dir,
    310     ExtensionPrefValueMap* extension_pref_value_map,
    311     bool extensions_disabled) {
    312   return ExtensionPrefs::Create(prefs,
    313                                 root_dir,
    314                                 extension_pref_value_map,
    315                                 extensions_disabled,
    316                                 make_scoped_ptr(new TimeProvider()));
    317 }
    318 
    319 // static
    320 ExtensionPrefs* ExtensionPrefs::Create(
    321     PrefService* pref_service,
    322     const base::FilePath& root_dir,
    323     ExtensionPrefValueMap* extension_pref_value_map,
    324     bool extensions_disabled,
    325     scoped_ptr<TimeProvider> time_provider) {
    326   scoped_ptr<ExtensionPrefs> prefs(
    327       new ExtensionPrefs(pref_service,
    328                          root_dir,
    329                          extension_pref_value_map,
    330                          time_provider.Pass(),
    331                          extensions_disabled));
    332   return prefs.release();
    333 }
    334 
    335 ExtensionPrefs::~ExtensionPrefs() {
    336 }
    337 
    338 // static
    339 ExtensionPrefs* ExtensionPrefs::Get(Profile* profile) {
    340   return ExtensionPrefsFactory::GetInstance()->GetForProfile(profile);
    341 }
    342 
    343 // static
    344 const char ExtensionPrefs::kExtensionsPref[] = "extensions.settings";
    345 // static
    346 const char ExtensionPrefs::kExtensionsLastChromeVersion[] =
    347     "extensions.last_chrome_version";
    348 
    349 static base::FilePath::StringType MakePathRelative(const base::FilePath& parent,
    350                                              const base::FilePath& child) {
    351   if (!parent.IsParent(child))
    352     return child.value();
    353 
    354   base::FilePath::StringType retval = child.value().substr(
    355       parent.value().length());
    356   if (base::FilePath::IsSeparator(retval[0]))
    357     return retval.substr(1);
    358   else
    359     return retval;
    360 }
    361 
    362 void ExtensionPrefs::MakePathsRelative() {
    363   const DictionaryValue* dict = prefs_->GetDictionary(kExtensionsPref);
    364   if (!dict || dict->empty())
    365     return;
    366 
    367   // Collect all extensions ids with absolute paths in |absolute_keys|.
    368   std::set<std::string> absolute_keys;
    369   for (DictionaryValue::Iterator i(*dict); !i.IsAtEnd(); i.Advance()) {
    370     const DictionaryValue* extension_dict = NULL;
    371     if (!i.value().GetAsDictionary(&extension_dict))
    372       continue;
    373     int location_value;
    374     if (extension_dict->GetInteger(kPrefLocation, &location_value) &&
    375         Manifest::IsUnpackedLocation(
    376             static_cast<Manifest::Location>(location_value))) {
    377       // Unpacked extensions can have absolute paths.
    378       continue;
    379     }
    380     base::FilePath::StringType path_string;
    381     if (!extension_dict->GetString(kPrefPath, &path_string))
    382       continue;
    383     base::FilePath path(path_string);
    384     if (path.IsAbsolute())
    385       absolute_keys.insert(i.key());
    386   }
    387   if (absolute_keys.empty())
    388     return;
    389 
    390   // Fix these paths.
    391   DictionaryPrefUpdate update(prefs_, kExtensionsPref);
    392   DictionaryValue* update_dict = update.Get();
    393   for (std::set<std::string>::iterator i = absolute_keys.begin();
    394        i != absolute_keys.end(); ++i) {
    395     DictionaryValue* extension_dict = NULL;
    396     if (!update_dict->GetDictionaryWithoutPathExpansion(*i, &extension_dict)) {
    397       NOTREACHED() << "Control should never reach here for extension " << *i;
    398       continue;
    399     }
    400     base::FilePath::StringType path_string;
    401     extension_dict->GetString(kPrefPath, &path_string);
    402     base::FilePath path(path_string);
    403     extension_dict->SetString(kPrefPath,
    404         MakePathRelative(install_directory_, path));
    405   }
    406 }
    407 
    408 const DictionaryValue* ExtensionPrefs::GetExtensionPref(
    409     const std::string& extension_id) const {
    410   const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
    411   const DictionaryValue* extension_dict = NULL;
    412   if (!extensions ||
    413       !extensions->GetDictionary(extension_id, &extension_dict)) {
    414     return NULL;
    415   }
    416   return extension_dict;
    417 }
    418 
    419 void ExtensionPrefs::UpdateExtensionPref(const std::string& extension_id,
    420                                          const std::string& key,
    421                                          Value* data_value) {
    422   if (!Extension::IdIsValid(extension_id)) {
    423     NOTREACHED() << "Invalid extension_id " << extension_id;
    424     return;
    425   }
    426   ScopedExtensionPrefUpdate update(prefs_, extension_id);
    427   if (data_value)
    428     update->Set(key, data_value);
    429   else
    430     update->Remove(key, NULL);
    431 }
    432 
    433 void ExtensionPrefs::DeleteExtensionPrefs(const std::string& extension_id) {
    434   extension_pref_value_map_->UnregisterExtension(extension_id);
    435   content_settings_store_->UnregisterExtension(extension_id);
    436   DictionaryPrefUpdate update(prefs_, kExtensionsPref);
    437   DictionaryValue* dict = update.Get();
    438   dict->Remove(extension_id, NULL);
    439 }
    440 
    441 bool ExtensionPrefs::ReadPrefAsBoolean(const std::string& extension_id,
    442                                        const std::string& pref_key,
    443                                        bool* out_value) const {
    444   const DictionaryValue* ext = GetExtensionPref(extension_id);
    445   if (!ext || !ext->GetBoolean(pref_key, out_value))
    446     return false;
    447 
    448   return true;
    449 }
    450 
    451 bool ExtensionPrefs::ReadPrefAsInteger(const std::string& extension_id,
    452                                        const std::string& pref_key,
    453                                        int* out_value) const {
    454   const DictionaryValue* ext = GetExtensionPref(extension_id);
    455   if (!ext || !ext->GetInteger(pref_key, out_value))
    456     return false;
    457 
    458   return true;
    459 }
    460 
    461 bool ExtensionPrefs::ReadPrefAsString(const std::string& extension_id,
    462                                       const std::string& pref_key,
    463                                       std::string* out_value) const {
    464   const DictionaryValue* ext = GetExtensionPref(extension_id);
    465   if (!ext || !ext->GetString(pref_key, out_value))
    466     return false;
    467 
    468   return true;
    469 }
    470 
    471 bool ExtensionPrefs::ReadPrefAsList(const std::string& extension_id,
    472                                     const std::string& pref_key,
    473                                     const ListValue** out_value) const {
    474   const DictionaryValue* ext = GetExtensionPref(extension_id);
    475   const ListValue* out = NULL;
    476   if (!ext || !ext->GetList(pref_key, &out))
    477     return false;
    478   if (out_value)
    479     *out_value = out;
    480 
    481   return true;
    482 }
    483 
    484 bool ExtensionPrefs::ReadPrefAsDictionary(
    485     const std::string& extension_id,
    486     const std::string& pref_key,
    487     const DictionaryValue** out_value) const {
    488   const DictionaryValue* ext = GetExtensionPref(extension_id);
    489   const DictionaryValue* out = NULL;
    490   if (!ext || !ext->GetDictionary(pref_key, &out))
    491     return false;
    492   if (out_value)
    493     *out_value = out;
    494 
    495   return true;
    496 }
    497 
    498 bool ExtensionPrefs::HasPrefForExtension(
    499     const std::string& extension_id) const {
    500   return GetExtensionPref(extension_id) != NULL;
    501 }
    502 
    503 bool ExtensionPrefs::ReadPrefAsURLPatternSet(const std::string& extension_id,
    504                                              const std::string& pref_key,
    505                                              URLPatternSet* result,
    506                                              int valid_schemes) {
    507   const ListValue* value = NULL;
    508   if (!ReadPrefAsList(extension_id, pref_key, &value))
    509     return false;
    510 
    511   bool allow_file_access = AllowFileAccess(extension_id);
    512   return result->Populate(*value, valid_schemes, allow_file_access, NULL);
    513 }
    514 
    515 void ExtensionPrefs::SetExtensionPrefURLPatternSet(
    516     const std::string& extension_id,
    517     const std::string& pref_key,
    518     const URLPatternSet& new_value) {
    519   UpdateExtensionPref(extension_id, pref_key, new_value.ToValue().release());
    520 }
    521 
    522 bool ExtensionPrefs::ReadPrefAsBooleanAndReturn(
    523     const std::string& extension_id,
    524     const std::string& pref_key) const {
    525   bool out_value = false;
    526   return ReadPrefAsBoolean(extension_id, pref_key, &out_value) && out_value;
    527 }
    528 
    529 PermissionSet* ExtensionPrefs::ReadPrefAsPermissionSet(
    530     const std::string& extension_id,
    531     const std::string& pref_key) {
    532   if (!GetExtensionPref(extension_id))
    533     return NULL;
    534 
    535   // Retrieve the API permissions. Please refer SetExtensionPrefPermissionSet()
    536   // for api_values format.
    537   APIPermissionSet apis;
    538   const ListValue* api_values = NULL;
    539   std::string api_pref = JoinPrefs(pref_key, kPrefAPIs);
    540   if (ReadPrefAsList(extension_id, api_pref, &api_values)) {
    541     APIPermissionSet::ParseFromJSON(api_values,
    542                                     APIPermissionSet::kAllowInternalPermissions,
    543                                     &apis, NULL, NULL);
    544   }
    545 
    546   // Retrieve the explicit host permissions.
    547   URLPatternSet explicit_hosts;
    548   ReadPrefAsURLPatternSet(
    549       extension_id, JoinPrefs(pref_key, kPrefExplicitHosts),
    550       &explicit_hosts, Extension::kValidHostPermissionSchemes);
    551 
    552   // Retrieve the scriptable host permissions.
    553   URLPatternSet scriptable_hosts;
    554   ReadPrefAsURLPatternSet(
    555       extension_id, JoinPrefs(pref_key, kPrefScriptableHosts),
    556       &scriptable_hosts, UserScript::ValidUserScriptSchemes());
    557 
    558   return new PermissionSet(apis, explicit_hosts, scriptable_hosts);
    559 }
    560 
    561 void ExtensionPrefs::SetExtensionPrefPermissionSet(
    562     const std::string& extension_id,
    563     const std::string& pref_key,
    564     const PermissionSet* new_value) {
    565   // Set the API permissions.
    566   // The format of api_values is:
    567   // [ "permission_name1",   // permissions do not support detail.
    568   //   "permission_name2",
    569   //   {"permission_name3": value },
    570   //   // permission supports detail, permission detail will be stored in value.
    571   //   ...
    572   // ]
    573   ListValue* api_values = new ListValue();
    574   APIPermissionSet apis = new_value->apis();
    575   std::string api_pref = JoinPrefs(pref_key, kPrefAPIs);
    576   for (APIPermissionSet::const_iterator i = apis.begin();
    577        i != apis.end(); ++i) {
    578     scoped_ptr<Value> detail(i->ToValue());
    579     if (detail) {
    580       DictionaryValue* tmp = new DictionaryValue();
    581       tmp->Set(i->name(), detail.release());
    582       api_values->Append(tmp);
    583     } else {
    584       api_values->Append(Value::CreateStringValue(i->name()));
    585     }
    586   }
    587   UpdateExtensionPref(extension_id, api_pref, api_values);
    588 
    589   // Set the explicit host permissions.
    590   if (!new_value->explicit_hosts().is_empty()) {
    591     SetExtensionPrefURLPatternSet(extension_id,
    592                                   JoinPrefs(pref_key, kPrefExplicitHosts),
    593                                   new_value->explicit_hosts());
    594   }
    595 
    596   // Set the scriptable host permissions.
    597   if (!new_value->scriptable_hosts().is_empty()) {
    598     SetExtensionPrefURLPatternSet(extension_id,
    599                                   JoinPrefs(pref_key, kPrefScriptableHosts),
    600                                   new_value->scriptable_hosts());
    601   }
    602 }
    603 
    604 int ExtensionPrefs::IncrementAcknowledgePromptCount(
    605     const std::string& extension_id) {
    606   int count = 0;
    607   ReadPrefAsInteger(extension_id, kPrefAcknowledgePromptCount, &count);
    608   ++count;
    609   UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount,
    610                       Value::CreateIntegerValue(count));
    611   return count;
    612 }
    613 
    614 bool ExtensionPrefs::IsExternalExtensionAcknowledged(
    615     const std::string& extension_id) {
    616   return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalAcknowledged);
    617 }
    618 
    619 void ExtensionPrefs::AcknowledgeExternalExtension(
    620     const std::string& extension_id) {
    621   DCHECK(Extension::IdIsValid(extension_id));
    622   UpdateExtensionPref(extension_id, kPrefExternalAcknowledged,
    623                       Value::CreateBooleanValue(true));
    624   UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, NULL);
    625 }
    626 
    627 bool ExtensionPrefs::IsBlacklistedExtensionAcknowledged(
    628     const std::string& extension_id) {
    629   return ReadPrefAsBooleanAndReturn(extension_id, kPrefBlacklistAcknowledged);
    630 }
    631 
    632 void ExtensionPrefs::AcknowledgeBlacklistedExtension(
    633     const std::string& extension_id) {
    634   DCHECK(Extension::IdIsValid(extension_id));
    635   UpdateExtensionPref(extension_id, kPrefBlacklistAcknowledged,
    636                       Value::CreateBooleanValue(true));
    637   UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, NULL);
    638 }
    639 
    640 bool ExtensionPrefs::IsExternalInstallFirstRun(
    641     const std::string& extension_id) {
    642   return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalInstallFirstRun);
    643 }
    644 
    645 void ExtensionPrefs::SetExternalInstallFirstRun(
    646     const std::string& extension_id) {
    647   DCHECK(Extension::IdIsValid(extension_id));
    648   UpdateExtensionPref(extension_id, kPrefExternalInstallFirstRun,
    649                       Value::CreateBooleanValue(true));
    650 }
    651 
    652 bool ExtensionPrefs::SetAlertSystemFirstRun() {
    653   if (prefs_->GetBoolean(prefs::kExtensionAlertsInitializedPref)) {
    654     return true;
    655   }
    656   prefs_->SetBoolean(prefs::kExtensionAlertsInitializedPref, true);
    657   return false;
    658 }
    659 
    660 bool ExtensionPrefs::ExtensionsBlacklistedByDefault() const {
    661   return admin_policy::BlacklistedByDefault(
    662       prefs_->GetList(prefs::kExtensionInstallDenyList));
    663 }
    664 
    665 bool ExtensionPrefs::DidExtensionEscalatePermissions(
    666     const std::string& extension_id) {
    667   return ReadPrefAsBooleanAndReturn(extension_id,
    668                                     kExtensionDidEscalatePermissions);
    669 }
    670 
    671 void ExtensionPrefs::SetDidExtensionEscalatePermissions(
    672     const Extension* extension, bool did_escalate) {
    673   UpdateExtensionPref(extension->id(), kExtensionDidEscalatePermissions,
    674                       Value::CreateBooleanValue(did_escalate));
    675 }
    676 
    677 int ExtensionPrefs::GetDisableReasons(const std::string& extension_id) {
    678   int value = -1;
    679   if (ReadPrefAsInteger(extension_id, kPrefDisableReasons, &value) &&
    680       value >= 0) {
    681     return value;
    682   }
    683   return Extension::DISABLE_NONE;
    684 }
    685 
    686 void ExtensionPrefs::AddDisableReason(const std::string& extension_id,
    687                                       Extension::DisableReason disable_reason) {
    688   int new_value = GetDisableReasons(extension_id) |
    689       static_cast<int>(disable_reason);
    690   UpdateExtensionPref(extension_id, kPrefDisableReasons,
    691                       Value::CreateIntegerValue(new_value));
    692 }
    693 
    694 void ExtensionPrefs::RemoveDisableReason(
    695     const std::string& extension_id,
    696     Extension::DisableReason disable_reason) {
    697   int new_value = GetDisableReasons(extension_id) &
    698       ~static_cast<int>(disable_reason);
    699   if (new_value == Extension::DISABLE_NONE) {
    700     UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL);
    701   } else {
    702     UpdateExtensionPref(extension_id, kPrefDisableReasons,
    703                         Value::CreateIntegerValue(new_value));
    704   }
    705 }
    706 
    707 void ExtensionPrefs::ClearDisableReasons(const std::string& extension_id) {
    708   UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL);
    709 }
    710 
    711 std::set<std::string> ExtensionPrefs::GetBlacklistedExtensions() {
    712   std::set<std::string> ids;
    713 
    714   const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
    715   if (!extensions)
    716     return ids;
    717 
    718   for (DictionaryValue::Iterator it(*extensions); !it.IsAtEnd(); it.Advance()) {
    719     if (!it.value().IsType(Value::TYPE_DICTIONARY)) {
    720       NOTREACHED() << "Invalid pref for extension " << it.key();
    721       continue;
    722     }
    723     if (IsBlacklistBitSet(static_cast<const DictionaryValue*>(&it.value())))
    724       ids.insert(it.key());
    725   }
    726 
    727   return ids;
    728 }
    729 
    730 void ExtensionPrefs::SetExtensionBlacklisted(const std::string& extension_id,
    731                                              bool is_blacklisted) {
    732   bool currently_blacklisted = IsExtensionBlacklisted(extension_id);
    733   if (is_blacklisted == currently_blacklisted) {
    734     NOTREACHED() << extension_id << " is " <<
    735                     (currently_blacklisted ? "already" : "not") <<
    736                     " blacklisted";
    737     return;
    738   }
    739 
    740   // Always make sure the "acknowledged" bit is cleared since the blacklist bit
    741   // is changing.
    742   UpdateExtensionPref(extension_id, kPrefBlacklistAcknowledged, NULL);
    743 
    744   if (is_blacklisted) {
    745     UpdateExtensionPref(extension_id,
    746                         kPrefBlacklist,
    747                         new base::FundamentalValue(true));
    748   } else {
    749     UpdateExtensionPref(extension_id, kPrefBlacklist, NULL);
    750     const DictionaryValue* dict = GetExtensionPref(extension_id);
    751     if (dict && dict->empty())
    752       DeleteExtensionPrefs(extension_id);
    753   }
    754 }
    755 
    756 bool ExtensionPrefs::IsExtensionBlacklisted(const std::string& id) const {
    757   const DictionaryValue* ext_prefs = GetExtensionPref(id);
    758   return ext_prefs && IsBlacklistBitSet(ext_prefs);
    759 }
    760 
    761 namespace {
    762 
    763 // Serializes |time| as a string value mapped to |key| in |dictionary|.
    764 void SaveTime(DictionaryValue* dictionary,
    765               const char* key,
    766               const base::Time& time) {
    767   if (!dictionary)
    768     return;
    769   std::string string_value = base::Int64ToString(time.ToInternalValue());
    770   dictionary->SetString(key, string_value);
    771 }
    772 
    773 // The opposite of SaveTime. If |key| is not found, this returns an empty Time
    774 // (is_null() will return true).
    775 base::Time ReadTime(const DictionaryValue* dictionary, const char* key) {
    776   if (!dictionary)
    777     return base::Time();
    778   std::string string_value;
    779   int64 value;
    780   if (dictionary->GetString(key, &string_value)) {
    781     if (base::StringToInt64(string_value, &value)) {
    782       return base::Time::FromInternalValue(value);
    783     }
    784   }
    785   return base::Time();
    786 }
    787 
    788 }  // namespace
    789 
    790 base::Time ExtensionPrefs::LastPingDay(const std::string& extension_id) const {
    791   DCHECK(Extension::IdIsValid(extension_id));
    792   return ReadTime(GetExtensionPref(extension_id), kLastPingDay);
    793 }
    794 
    795 void ExtensionPrefs::SetLastPingDay(const std::string& extension_id,
    796                                     const base::Time& time) {
    797   DCHECK(Extension::IdIsValid(extension_id));
    798   ScopedExtensionPrefUpdate update(prefs_, extension_id);
    799   SaveTime(update.Get(), kLastPingDay, time);
    800 }
    801 
    802 base::Time ExtensionPrefs::BlacklistLastPingDay() const {
    803   return ReadTime(prefs_->GetDictionary(kExtensionsBlacklistUpdate),
    804                   kLastPingDay);
    805 }
    806 
    807 void ExtensionPrefs::SetBlacklistLastPingDay(const base::Time& time) {
    808   DictionaryPrefUpdate update(prefs_, kExtensionsBlacklistUpdate);
    809   SaveTime(update.Get(), kLastPingDay, time);
    810 }
    811 
    812 base::Time ExtensionPrefs::LastActivePingDay(const std::string& extension_id) {
    813   DCHECK(Extension::IdIsValid(extension_id));
    814   return ReadTime(GetExtensionPref(extension_id), kLastActivePingDay);
    815 }
    816 
    817 void ExtensionPrefs::SetLastActivePingDay(const std::string& extension_id,
    818                                           const base::Time& time) {
    819   DCHECK(Extension::IdIsValid(extension_id));
    820   ScopedExtensionPrefUpdate update(prefs_, extension_id);
    821   SaveTime(update.Get(), kLastActivePingDay, time);
    822 }
    823 
    824 bool ExtensionPrefs::GetActiveBit(const std::string& extension_id) {
    825   const DictionaryValue* dictionary = GetExtensionPref(extension_id);
    826   bool result = false;
    827   if (dictionary && dictionary->GetBoolean(kActiveBit, &result))
    828     return result;
    829   return false;
    830 }
    831 
    832 void ExtensionPrefs::SetActiveBit(const std::string& extension_id,
    833                                   bool active) {
    834   UpdateExtensionPref(extension_id, kActiveBit,
    835                       Value::CreateBooleanValue(active));
    836 }
    837 
    838 void ExtensionPrefs::MigratePermissions(const ExtensionIdList& extension_ids) {
    839   PermissionsInfo* info = PermissionsInfo::GetInstance();
    840   for (ExtensionIdList::const_iterator ext_id =
    841        extension_ids.begin(); ext_id != extension_ids.end(); ++ext_id) {
    842 
    843     // An extension's granted permissions need to be migrated if the
    844     // full_access bit is present. This bit was always present in the previous
    845     // scheme and is never present now.
    846     bool full_access;
    847     const DictionaryValue* ext = GetExtensionPref(*ext_id);
    848     if (!ext || !ext->GetBoolean(kPrefOldGrantedFullAccess, &full_access))
    849       continue;
    850 
    851     // Remove the full access bit (empty list will get trimmed).
    852     UpdateExtensionPref(
    853         *ext_id, kPrefOldGrantedFullAccess, new ListValue());
    854 
    855     // Add the plugin permission if the full access bit was set.
    856     if (full_access) {
    857       const ListValue* apis = NULL;
    858       ListValue* new_apis = NULL;
    859 
    860       std::string granted_apis =
    861           JoinPrefs(kPrefGrantedPermissions, kPrefAPIs);
    862       if (ext->GetList(kPrefOldGrantedAPIs, &apis))
    863         new_apis = apis->DeepCopy();
    864       else
    865         new_apis = new ListValue();
    866 
    867       std::string plugin_name = info->GetByID(
    868           APIPermission::kPlugin)->name();
    869       new_apis->Append(Value::CreateStringValue(plugin_name));
    870       UpdateExtensionPref(*ext_id, granted_apis, new_apis);
    871     }
    872 
    873     // The granted permissions originally only held the effective hosts,
    874     // which are a combination of host and user script host permissions.
    875     // We now maintain these lists separately. For migration purposes, it
    876     // does not matter how we treat the old effective hosts as long as the
    877     // new effective hosts will be the same, so we move them to explicit
    878     // host permissions.
    879     const ListValue* hosts = NULL;
    880     std::string explicit_hosts =
    881         JoinPrefs(kPrefGrantedPermissions, kPrefExplicitHosts);
    882     if (ext->GetList(kPrefOldGrantedHosts, &hosts)) {
    883       UpdateExtensionPref(
    884           *ext_id, explicit_hosts, hosts->DeepCopy());
    885 
    886       // We can get rid of the old one by setting it to an empty list.
    887       UpdateExtensionPref(*ext_id, kPrefOldGrantedHosts, new ListValue());
    888     }
    889   }
    890 }
    891 
    892 void ExtensionPrefs::MigrateDisableReasons(
    893     const ExtensionIdList& extension_ids) {
    894   for (ExtensionIdList::const_iterator ext_id =
    895        extension_ids.begin(); ext_id != extension_ids.end(); ++ext_id) {
    896     int value = -1;
    897     if (ReadPrefAsInteger(*ext_id, kDeprecatedPrefDisableReason, &value)) {
    898       int new_value = Extension::DISABLE_NONE;
    899       switch (value) {
    900         case Extension::DEPRECATED_DISABLE_USER_ACTION:
    901           new_value = Extension::DISABLE_USER_ACTION;
    902           break;
    903         case Extension::DEPRECATED_DISABLE_PERMISSIONS_INCREASE:
    904           new_value = Extension::DISABLE_PERMISSIONS_INCREASE;
    905           break;
    906         case Extension::DEPRECATED_DISABLE_RELOAD:
    907           new_value = Extension::DISABLE_RELOAD;
    908           break;
    909       }
    910 
    911       UpdateExtensionPref(*ext_id, kPrefDisableReasons,
    912                           Value::CreateIntegerValue(new_value));
    913       // Remove the old disable reason.
    914       UpdateExtensionPref(*ext_id, kDeprecatedPrefDisableReason, NULL);
    915     }
    916   }
    917 }
    918 
    919 PermissionSet* ExtensionPrefs::GetGrantedPermissions(
    920     const std::string& extension_id) {
    921   CHECK(Extension::IdIsValid(extension_id));
    922   return ReadPrefAsPermissionSet(extension_id, kPrefGrantedPermissions);
    923 }
    924 
    925 void ExtensionPrefs::AddGrantedPermissions(
    926     const std::string& extension_id,
    927     const PermissionSet* permissions) {
    928   CHECK(Extension::IdIsValid(extension_id));
    929 
    930   scoped_refptr<PermissionSet> granted_permissions(
    931       GetGrantedPermissions(extension_id));
    932 
    933   // The new granted permissions are the union of the already granted
    934   // permissions and the newly granted permissions.
    935   scoped_refptr<PermissionSet> new_perms(
    936       PermissionSet::CreateUnion(
    937           permissions, granted_permissions.get()));
    938 
    939   SetExtensionPrefPermissionSet(
    940       extension_id, kPrefGrantedPermissions, new_perms.get());
    941 }
    942 
    943 void ExtensionPrefs::RemoveGrantedPermissions(
    944     const std::string& extension_id,
    945     const PermissionSet* permissions) {
    946   CHECK(Extension::IdIsValid(extension_id));
    947 
    948   scoped_refptr<PermissionSet> granted_permissions(
    949       GetGrantedPermissions(extension_id));
    950 
    951   // The new granted permissions are the difference of the already granted
    952   // permissions and the newly ungranted permissions.
    953   scoped_refptr<PermissionSet> new_perms(
    954       PermissionSet::CreateDifference(
    955           granted_permissions.get(), permissions));
    956 
    957   SetExtensionPrefPermissionSet(
    958       extension_id, kPrefGrantedPermissions, new_perms.get());
    959 }
    960 
    961 PermissionSet* ExtensionPrefs::GetActivePermissions(
    962     const std::string& extension_id) {
    963   CHECK(Extension::IdIsValid(extension_id));
    964   return ReadPrefAsPermissionSet(extension_id, kPrefActivePermissions);
    965 }
    966 
    967 void ExtensionPrefs::SetActivePermissions(
    968     const std::string& extension_id,
    969     const PermissionSet* permissions) {
    970   SetExtensionPrefPermissionSet(
    971       extension_id, kPrefActivePermissions, permissions);
    972 }
    973 
    974 void ExtensionPrefs::SetExtensionRunning(const std::string& extension_id,
    975     bool is_running) {
    976   Value* value = Value::CreateBooleanValue(is_running);
    977   UpdateExtensionPref(extension_id, kPrefRunning, value);
    978 }
    979 
    980 bool ExtensionPrefs::IsExtensionRunning(const std::string& extension_id) {
    981   const DictionaryValue* extension = GetExtensionPref(extension_id);
    982   if (!extension)
    983     return false;
    984   bool running = false;
    985   extension->GetBoolean(kPrefRunning, &running);
    986   return running;
    987 }
    988 
    989 void ExtensionPrefs::SetIsActive(const std::string& extension_id,
    990                                  bool is_active) {
    991   Value* value = Value::CreateBooleanValue(is_active);
    992   UpdateExtensionPref(extension_id, kIsActive, value);
    993 }
    994 
    995 bool ExtensionPrefs::IsActive(const std::string& extension_id) {
    996   const DictionaryValue* extension = GetExtensionPref(extension_id);
    997   if (!extension)
    998     return false;
    999   bool is_active = false;
   1000   extension->GetBoolean(kIsActive, &is_active);
   1001   return is_active;
   1002 }
   1003 
   1004 bool ExtensionPrefs::IsIncognitoEnabled(const std::string& extension_id) {
   1005   return ReadPrefAsBooleanAndReturn(extension_id, kPrefIncognitoEnabled);
   1006 }
   1007 
   1008 void ExtensionPrefs::SetIsIncognitoEnabled(const std::string& extension_id,
   1009                                            bool enabled) {
   1010   UpdateExtensionPref(extension_id, kPrefIncognitoEnabled,
   1011                       Value::CreateBooleanValue(enabled));
   1012 }
   1013 
   1014 bool ExtensionPrefs::AllowFileAccess(const std::string& extension_id) {
   1015   return ReadPrefAsBooleanAndReturn(extension_id, kPrefAllowFileAccess);
   1016 }
   1017 
   1018 void ExtensionPrefs::SetAllowFileAccess(const std::string& extension_id,
   1019                                         bool allow) {
   1020   UpdateExtensionPref(extension_id, kPrefAllowFileAccess,
   1021                       Value::CreateBooleanValue(allow));
   1022 }
   1023 
   1024 bool ExtensionPrefs::HasAllowFileAccessSetting(
   1025     const std::string& extension_id) const {
   1026   const DictionaryValue* ext = GetExtensionPref(extension_id);
   1027   return ext && ext->HasKey(kPrefAllowFileAccess);
   1028 }
   1029 
   1030 ExtensionPrefs::LaunchType ExtensionPrefs::GetLaunchType(
   1031     const Extension* extension,
   1032     ExtensionPrefs::LaunchType default_pref_value) {
   1033   int value = -1;
   1034   LaunchType result = LAUNCH_REGULAR;
   1035 
   1036   if (ReadPrefAsInteger(extension->id(), kPrefLaunchType, &value) &&
   1037       (value == LAUNCH_PINNED ||
   1038        value == LAUNCH_REGULAR ||
   1039        value == LAUNCH_FULLSCREEN ||
   1040        value == LAUNCH_WINDOW)) {
   1041     result = static_cast<LaunchType>(value);
   1042   } else {
   1043     result = default_pref_value;
   1044   }
   1045 #if (USE_ASH)
   1046   if (ash::Shell::IsForcedMaximizeMode() &&
   1047       (result == LAUNCH_FULLSCREEN || result == LAUNCH_WINDOW))
   1048     result = LAUNCH_REGULAR;
   1049 #endif
   1050 #if defined(OS_MACOSX)
   1051     // App windows are not yet supported on mac.  Pref sync could make
   1052     // the launch type LAUNCH_WINDOW, even if there is no UI to set it
   1053     // on mac.
   1054     if (!extension->is_platform_app() && result == LAUNCH_WINDOW)
   1055       result = LAUNCH_REGULAR;
   1056 #endif
   1057 
   1058 #if defined(OS_WIN)
   1059     // We don't support app windows in Windows 8 single window Metro mode.
   1060     if (win8::IsSingleWindowMetroMode() && result == LAUNCH_WINDOW)
   1061       result = LAUNCH_REGULAR;
   1062 #endif  // OS_WIN
   1063 
   1064   return result;
   1065 }
   1066 
   1067 extension_misc::LaunchContainer ExtensionPrefs::GetLaunchContainer(
   1068     const Extension* extension,
   1069     ExtensionPrefs::LaunchType default_pref_value) {
   1070   extension_misc::LaunchContainer manifest_launch_container =
   1071       AppLaunchInfo::GetLaunchContainer(extension);
   1072 
   1073   const extension_misc::LaunchContainer kInvalidLaunchContainer =
   1074       static_cast<extension_misc::LaunchContainer>(-1);
   1075 
   1076   extension_misc::LaunchContainer result = kInvalidLaunchContainer;
   1077 
   1078   if (manifest_launch_container == extension_misc::LAUNCH_PANEL) {
   1079     // Apps with app.launch.container = 'panel' should always respect the
   1080     // manifest setting.
   1081     result = manifest_launch_container;
   1082   } else if (manifest_launch_container == extension_misc::LAUNCH_TAB) {
   1083     // Look for prefs that indicate the user's choice of launch
   1084     // container.  The app's menu on the NTP provides a UI to set
   1085     // this preference.  If no preference is set, |default_pref_value|
   1086     // is used.
   1087     ExtensionPrefs::LaunchType prefs_launch_type =
   1088         GetLaunchType(extension, default_pref_value);
   1089 
   1090     if (prefs_launch_type == ExtensionPrefs::LAUNCH_WINDOW) {
   1091       // If the pref is set to launch a window (or no pref is set, and
   1092       // window opening is the default), make the container a window.
   1093       result = extension_misc::LAUNCH_WINDOW;
   1094 #if defined(USE_ASH)
   1095     } else if (prefs_launch_type == ExtensionPrefs::LAUNCH_FULLSCREEN &&
   1096                chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH) {
   1097       // LAUNCH_FULLSCREEN launches in a maximized app window in ash.
   1098       // For desktop chrome AURA on all platforms we should open the
   1099       // application in full screen mode in the current tab, on the same
   1100       // lines as non AURA chrome.
   1101       result = extension_misc::LAUNCH_WINDOW;
   1102 #endif
   1103     } else {
   1104       // All other launch types (tab, pinned, fullscreen) are
   1105       // implemented as tabs in a window.
   1106       result = extension_misc::LAUNCH_TAB;
   1107     }
   1108   } else {
   1109     // If a new value for app.launch.container is added, logic
   1110     // for it should be added here.  extension_misc::LAUNCH_WINDOW
   1111     // is not present because there is no way to set it in a manifest.
   1112     NOTREACHED() << manifest_launch_container;
   1113   }
   1114 
   1115   // All paths should set |result|.
   1116   if (result == kInvalidLaunchContainer) {
   1117     DLOG(FATAL) << "Failed to set a launch container.";
   1118     result = extension_misc::LAUNCH_TAB;
   1119   }
   1120 
   1121   return result;
   1122 }
   1123 
   1124 void ExtensionPrefs::SetLaunchType(const std::string& extension_id,
   1125                                    LaunchType launch_type) {
   1126   UpdateExtensionPref(extension_id, kPrefLaunchType,
   1127       Value::CreateIntegerValue(static_cast<int>(launch_type)));
   1128 }
   1129 
   1130 bool ExtensionPrefs::DoesExtensionHaveState(
   1131     const std::string& id, Extension::State check_state) const {
   1132   const DictionaryValue* extension = GetExtensionPref(id);
   1133   int state = -1;
   1134   if (!extension || !extension->GetInteger(kPrefState, &state))
   1135     return false;
   1136 
   1137   if (state < 0 || state >= Extension::NUM_STATES) {
   1138     LOG(ERROR) << "Bad pref 'state' for extension '" << id << "'";
   1139     return false;
   1140   }
   1141 
   1142   return state == check_state;
   1143 }
   1144 
   1145 bool ExtensionPrefs::IsExternalExtensionUninstalled(
   1146     const std::string& id) const {
   1147   return DoesExtensionHaveState(id, Extension::EXTERNAL_EXTENSION_UNINSTALLED);
   1148 }
   1149 
   1150 bool ExtensionPrefs::IsExtensionDisabled(
   1151     const std::string& id) const {
   1152   return DoesExtensionHaveState(id, Extension::DISABLED);
   1153 }
   1154 
   1155 ExtensionIdList ExtensionPrefs::GetToolbarOrder() {
   1156   return GetExtensionPrefAsVector(prefs::kExtensionToolbar);
   1157 }
   1158 
   1159 void ExtensionPrefs::SetToolbarOrder(const ExtensionIdList& extension_ids) {
   1160   SetExtensionPrefFromVector(prefs::kExtensionToolbar, extension_ids);
   1161 }
   1162 
   1163 void ExtensionPrefs::OnExtensionInstalled(
   1164     const Extension* extension,
   1165     Extension::State initial_state,
   1166     Blacklist::BlacklistState blacklist_state,
   1167     const syncer::StringOrdinal& page_ordinal) {
   1168   ScopedExtensionPrefUpdate update(prefs_, extension->id());
   1169   DictionaryValue* extension_dict = update.Get();
   1170   const base::Time install_time = time_provider_->GetCurrentTime();
   1171   PopulateExtensionInfoPrefs(extension, install_time, initial_state,
   1172                              blacklist_state, extension_dict);
   1173   FinishExtensionInfoPrefs(extension->id(), install_time,
   1174                            extension->RequiresSortOrdinal(),
   1175                            page_ordinal, extension_dict);
   1176 }
   1177 
   1178 void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id,
   1179                                             const Manifest::Location& location,
   1180                                             bool external_uninstall) {
   1181   extension_sorting_->ClearOrdinals(extension_id);
   1182 
   1183   // For external extensions, we save a preference reminding ourself not to try
   1184   // and install the extension anymore (except when |external_uninstall| is
   1185   // true, which signifies that the registry key was deleted or the pref file
   1186   // no longer lists the extension).
   1187   if (!external_uninstall && Manifest::IsExternalLocation(location)) {
   1188     UpdateExtensionPref(extension_id, kPrefState,
   1189                         Value::CreateIntegerValue(
   1190                             Extension::EXTERNAL_EXTENSION_UNINSTALLED));
   1191     extension_pref_value_map_->SetExtensionState(extension_id, false);
   1192     content_settings_store_->SetExtensionState(extension_id, false);
   1193   } else {
   1194     DeleteExtensionPrefs(extension_id);
   1195   }
   1196 }
   1197 
   1198 void ExtensionPrefs::SetExtensionState(const std::string& extension_id,
   1199                                        Extension::State state) {
   1200   UpdateExtensionPref(extension_id, kPrefState,
   1201                       Value::CreateIntegerValue(state));
   1202   bool enabled = (state == Extension::ENABLED);
   1203   extension_pref_value_map_->SetExtensionState(extension_id, enabled);
   1204   content_settings_store_->SetExtensionState(extension_id, enabled);
   1205 }
   1206 
   1207 std::string ExtensionPrefs::GetVersionString(const std::string& extension_id) {
   1208   const DictionaryValue* extension = GetExtensionPref(extension_id);
   1209   if (!extension)
   1210     return std::string();
   1211 
   1212   std::string version;
   1213   extension->GetString(kPrefVersion, &version);
   1214 
   1215   return version;
   1216 }
   1217 
   1218 void ExtensionPrefs::UpdateManifest(const Extension* extension) {
   1219   if (!Manifest::IsUnpackedLocation(extension->location())) {
   1220     const DictionaryValue* extension_dict =
   1221         GetExtensionPref(extension->id());
   1222     if (!extension_dict)
   1223       return;
   1224     const DictionaryValue* old_manifest = NULL;
   1225     bool update_required =
   1226         !extension_dict->GetDictionary(kPrefManifest, &old_manifest) ||
   1227         !extension->manifest()->value()->Equals(old_manifest);
   1228     if (update_required) {
   1229       UpdateExtensionPref(extension->id(), kPrefManifest,
   1230                           extension->manifest()->value()->DeepCopy());
   1231     }
   1232   }
   1233 }
   1234 
   1235 base::FilePath ExtensionPrefs::GetExtensionPath(
   1236     const std::string& extension_id) {
   1237   const DictionaryValue* dict = GetExtensionPref(extension_id);
   1238   if (!dict)
   1239     return base::FilePath();
   1240 
   1241   std::string path;
   1242   if (!dict->GetString(kPrefPath, &path))
   1243     return base::FilePath();
   1244 
   1245   return install_directory_.Append(
   1246       base::FilePath::FromWStringHack(UTF8ToWide(path)));
   1247 }
   1248 
   1249 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetInstalledInfoHelper(
   1250     const std::string& extension_id,
   1251     const DictionaryValue* extension) const {
   1252   int location_value;
   1253   if (!extension->GetInteger(kPrefLocation, &location_value))
   1254     return scoped_ptr<ExtensionInfo>();
   1255 
   1256   base::FilePath::StringType path;
   1257   if (!extension->GetString(kPrefPath, &path))
   1258     return scoped_ptr<ExtensionInfo>();
   1259 
   1260   // Make path absolute. Unpacked extensions will already have absolute paths,
   1261   // otherwise make it so.
   1262   Manifest::Location location = static_cast<Manifest::Location>(location_value);
   1263   if (!Manifest::IsUnpackedLocation(location)) {
   1264     DCHECK(location == Manifest::COMPONENT ||
   1265            !base::FilePath(path).IsAbsolute());
   1266     path = install_directory_.Append(path).value();
   1267   }
   1268 
   1269   // Only the following extension types have data saved in the preferences.
   1270   if (location != Manifest::INTERNAL &&
   1271       !Manifest::IsUnpackedLocation(location) &&
   1272       !Manifest::IsExternalLocation(location)) {
   1273     NOTREACHED();
   1274     return scoped_ptr<ExtensionInfo>();
   1275   }
   1276 
   1277   const DictionaryValue* manifest = NULL;
   1278   if (!Manifest::IsUnpackedLocation(location) &&
   1279       !extension->GetDictionary(kPrefManifest, &manifest)) {
   1280     LOG(WARNING) << "Missing manifest for extension " << extension_id;
   1281     // Just a warning for now.
   1282   }
   1283 
   1284   return scoped_ptr<ExtensionInfo>(new ExtensionInfo(
   1285       manifest, extension_id, base::FilePath(path), location));
   1286 }
   1287 
   1288 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetInstalledExtensionInfo(
   1289     const std::string& extension_id) const {
   1290   const DictionaryValue* ext = NULL;
   1291   const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
   1292   if (!extensions ||
   1293       !extensions->GetDictionaryWithoutPathExpansion(extension_id, &ext))
   1294     return scoped_ptr<ExtensionInfo>();
   1295   int state_value;
   1296   if (!ext->GetInteger(kPrefState, &state_value) ||
   1297       state_value == Extension::ENABLED_COMPONENT) {
   1298     // Old preferences files may not have kPrefState for component extensions.
   1299     return scoped_ptr<ExtensionInfo>();
   1300   }
   1301 
   1302   if (state_value == Extension::EXTERNAL_EXTENSION_UNINSTALLED) {
   1303     LOG(WARNING) << "External extension with id " << extension_id
   1304                  << " has been uninstalled by the user";
   1305     return scoped_ptr<ExtensionInfo>();
   1306   }
   1307 
   1308   return GetInstalledInfoHelper(extension_id, ext);
   1309 }
   1310 
   1311 scoped_ptr<ExtensionPrefs::ExtensionsInfo>
   1312 ExtensionPrefs::GetInstalledExtensionsInfo() const {
   1313   scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
   1314 
   1315   const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
   1316   for (DictionaryValue::Iterator extension_id(*extensions);
   1317        !extension_id.IsAtEnd(); extension_id.Advance()) {
   1318     if (!Extension::IdIsValid(extension_id.key()))
   1319       continue;
   1320 
   1321     scoped_ptr<ExtensionInfo> info =
   1322         GetInstalledExtensionInfo(extension_id.key());
   1323     if (info)
   1324       extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
   1325   }
   1326 
   1327   return extensions_info.Pass();
   1328 }
   1329 
   1330 void ExtensionPrefs::SetDelayedInstallInfo(
   1331     const Extension* extension,
   1332     Extension::State initial_state,
   1333     Blacklist::BlacklistState blacklist_state,
   1334     DelayReason delay_reason,
   1335     const syncer::StringOrdinal& page_ordinal) {
   1336   DictionaryValue* extension_dict = new DictionaryValue();
   1337   PopulateExtensionInfoPrefs(extension, time_provider_->GetCurrentTime(),
   1338                              initial_state, blacklist_state, extension_dict);
   1339 
   1340   // Add transient data that is needed by FinishDelayedInstallInfo(), but
   1341   // should not be in the final extension prefs. All entries here should have
   1342   // a corresponding Remove() call in FinishDelayedInstallInfo().
   1343   if (extension->RequiresSortOrdinal()) {
   1344     extension_dict->SetString(
   1345         kPrefSuggestedPageOrdinal,
   1346         page_ordinal.IsValid() ? page_ordinal.ToInternalValue()
   1347                                : std::string());
   1348   }
   1349   extension_dict->SetInteger(kDelayedInstallReason,
   1350                              static_cast<int>(delay_reason));
   1351 
   1352   UpdateExtensionPref(extension->id(), kDelayedInstallInfo, extension_dict);
   1353 }
   1354 
   1355 bool ExtensionPrefs::RemoveDelayedInstallInfo(
   1356     const std::string& extension_id) {
   1357   if (!GetExtensionPref(extension_id))
   1358     return false;
   1359   ScopedExtensionPrefUpdate update(prefs_, extension_id);
   1360   bool result = update->Remove(kDelayedInstallInfo, NULL);
   1361   return result;
   1362 }
   1363 
   1364 bool ExtensionPrefs::FinishDelayedInstallInfo(
   1365     const std::string& extension_id) {
   1366   CHECK(Extension::IdIsValid(extension_id));
   1367   ScopedExtensionPrefUpdate update(prefs_, extension_id);
   1368   DictionaryValue* extension_dict = update.Get();
   1369   DictionaryValue* pending_install_dict = NULL;
   1370   if (!extension_dict->GetDictionary(kDelayedInstallInfo,
   1371                                      &pending_install_dict)) {
   1372     return false;
   1373   }
   1374 
   1375   // Retrieve and clear transient values populated by SetDelayedInstallInfo().
   1376   // Also do any other data cleanup that makes sense.
   1377   std::string serialized_ordinal;
   1378   syncer::StringOrdinal suggested_page_ordinal;
   1379   bool needs_sort_ordinal = false;
   1380   if (pending_install_dict->GetString(kPrefSuggestedPageOrdinal,
   1381                                       &serialized_ordinal)) {
   1382     suggested_page_ordinal = syncer::StringOrdinal(serialized_ordinal);
   1383     needs_sort_ordinal = true;
   1384     pending_install_dict->Remove(kPrefSuggestedPageOrdinal, NULL);
   1385   }
   1386   pending_install_dict->Remove(kDelayedInstallReason, NULL);
   1387 
   1388   const base::Time install_time = time_provider_->GetCurrentTime();
   1389   pending_install_dict->Set(
   1390       kPrefInstallTime,
   1391       Value::CreateStringValue(
   1392           base::Int64ToString(install_time.ToInternalValue())));
   1393 
   1394   // Commit the delayed install data.
   1395   for (DictionaryValue::Iterator it(*pending_install_dict); !it.IsAtEnd();
   1396        it.Advance()) {
   1397     extension_dict->Set(it.key(), it.value().DeepCopy());
   1398   }
   1399   FinishExtensionInfoPrefs(extension_id, install_time, needs_sort_ordinal,
   1400                            suggested_page_ordinal, extension_dict);
   1401   return true;
   1402 }
   1403 
   1404 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetDelayedInstallInfo(
   1405     const std::string& extension_id) const {
   1406   const DictionaryValue* extension_prefs =
   1407       GetExtensionPref(extension_id);
   1408   if (!extension_prefs)
   1409     return scoped_ptr<ExtensionInfo>();
   1410 
   1411   const DictionaryValue* ext = NULL;
   1412   if (!extension_prefs->GetDictionary(kDelayedInstallInfo, &ext))
   1413     return scoped_ptr<ExtensionInfo>();
   1414 
   1415   return GetInstalledInfoHelper(extension_id, ext);
   1416 }
   1417 
   1418 ExtensionPrefs::DelayReason ExtensionPrefs::GetDelayedInstallReason(
   1419     const std::string& extension_id) const {
   1420   const DictionaryValue* extension_prefs =
   1421       GetExtensionPref(extension_id);
   1422   if (!extension_prefs)
   1423     return DELAY_REASON_NONE;
   1424 
   1425   const DictionaryValue* ext = NULL;
   1426   if (!extension_prefs->GetDictionary(kDelayedInstallInfo, &ext))
   1427     return DELAY_REASON_NONE;
   1428 
   1429   int delay_reason;
   1430   if (!ext->GetInteger(kDelayedInstallReason, &delay_reason))
   1431     return DELAY_REASON_NONE;
   1432 
   1433   return static_cast<DelayReason>(delay_reason);
   1434 }
   1435 
   1436 scoped_ptr<ExtensionPrefs::ExtensionsInfo> ExtensionPrefs::
   1437     GetAllDelayedInstallInfo() const {
   1438   scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
   1439 
   1440   const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
   1441   for (DictionaryValue::Iterator extension_id(*extensions);
   1442        !extension_id.IsAtEnd(); extension_id.Advance()) {
   1443     if (!Extension::IdIsValid(extension_id.key()))
   1444       continue;
   1445 
   1446     scoped_ptr<ExtensionInfo> info = GetDelayedInstallInfo(extension_id.key());
   1447     if (info)
   1448       extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
   1449   }
   1450 
   1451   return extensions_info.Pass();
   1452 }
   1453 
   1454 bool ExtensionPrefs::WasAppDraggedByUser(const std::string& extension_id) {
   1455   return ReadPrefAsBooleanAndReturn(extension_id, kPrefUserDraggedApp);
   1456 }
   1457 
   1458 void ExtensionPrefs::SetAppDraggedByUser(const std::string& extension_id) {
   1459   UpdateExtensionPref(extension_id, kPrefUserDraggedApp,
   1460                       Value::CreateBooleanValue(true));
   1461 }
   1462 
   1463 bool ExtensionPrefs::IsFromWebStore(
   1464     const std::string& extension_id) const {
   1465   const DictionaryValue* dictionary = GetExtensionPref(extension_id);
   1466   bool result = false;
   1467   if (dictionary && dictionary->GetBoolean(kPrefFromWebStore, &result))
   1468     return result;
   1469   return false;
   1470 }
   1471 
   1472 bool ExtensionPrefs::IsFromBookmark(
   1473     const std::string& extension_id) const {
   1474   const DictionaryValue* dictionary = GetExtensionPref(extension_id);
   1475   bool result = false;
   1476   if (dictionary && dictionary->GetBoolean(kPrefFromBookmark, &result))
   1477     return result;
   1478   return false;
   1479 }
   1480 
   1481 int ExtensionPrefs::GetCreationFlags(const std::string& extension_id) const {
   1482   int creation_flags = Extension::NO_FLAGS;
   1483   if (!ReadPrefAsInteger(extension_id, kPrefCreationFlags, &creation_flags)) {
   1484     // Since kPrefCreationFlags was added later, it will be missing for
   1485     // previously installed extensions.
   1486     if (IsFromBookmark(extension_id))
   1487       creation_flags |= Extension::FROM_BOOKMARK;
   1488     if (IsFromWebStore(extension_id))
   1489       creation_flags |= Extension::FROM_WEBSTORE;
   1490     if (WasInstalledByDefault(extension_id))
   1491       creation_flags |= Extension::WAS_INSTALLED_BY_DEFAULT;
   1492   }
   1493   return creation_flags;
   1494 }
   1495 
   1496 int ExtensionPrefs::GetDelayedInstallCreationFlags(
   1497     const std::string& extension_id) const {
   1498   int creation_flags = Extension::NO_FLAGS;
   1499   const DictionaryValue* delayed_info = NULL;
   1500   if (ReadPrefAsDictionary(extension_id, kDelayedInstallInfo, &delayed_info)) {
   1501     delayed_info->GetInteger(kPrefCreationFlags, &creation_flags);
   1502   }
   1503   return creation_flags;
   1504 }
   1505 
   1506 bool ExtensionPrefs::WasInstalledByDefault(
   1507     const std::string& extension_id) const {
   1508   const DictionaryValue* dictionary = GetExtensionPref(extension_id);
   1509   bool result = false;
   1510   if (dictionary &&
   1511       dictionary->GetBoolean(kPrefWasInstalledByDefault, &result))
   1512     return result;
   1513   return false;
   1514 }
   1515 
   1516 base::Time ExtensionPrefs::GetInstallTime(
   1517     const std::string& extension_id) const {
   1518   const DictionaryValue* extension = GetExtensionPref(extension_id);
   1519   if (!extension) {
   1520     NOTREACHED();
   1521     return base::Time();
   1522   }
   1523   std::string install_time_str;
   1524   if (!extension->GetString(kPrefInstallTime, &install_time_str))
   1525     return base::Time();
   1526   int64 install_time_i64 = 0;
   1527   if (!base::StringToInt64(install_time_str, &install_time_i64))
   1528     return base::Time();
   1529   return base::Time::FromInternalValue(install_time_i64);
   1530 }
   1531 
   1532 void ExtensionPrefs::GetExtensions(ExtensionIdList* out) {
   1533   CHECK(out);
   1534 
   1535   scoped_ptr<ExtensionsInfo> extensions_info(GetInstalledExtensionsInfo());
   1536 
   1537   for (size_t i = 0; i < extensions_info->size(); ++i) {
   1538     ExtensionInfo* info = extensions_info->at(i).get();
   1539     out->push_back(info->extension_id);
   1540   }
   1541 }
   1542 
   1543 // static
   1544 ExtensionIdList ExtensionPrefs::GetExtensionsFrom(
   1545     const PrefService* pref_service) {
   1546   ExtensionIdList result;
   1547 
   1548   const DictionaryValue* extension_prefs = NULL;
   1549   const Value* extension_prefs_value =
   1550       pref_service->GetUserPrefValue(kExtensionsPref);
   1551   if (!extension_prefs_value ||
   1552       !extension_prefs_value->GetAsDictionary(&extension_prefs)) {
   1553     return result;  // Empty set
   1554   }
   1555 
   1556   for (DictionaryValue::Iterator it(*extension_prefs); !it.IsAtEnd();
   1557        it.Advance()) {
   1558     const DictionaryValue* ext = NULL;
   1559     if (!it.value().GetAsDictionary(&ext)) {
   1560       NOTREACHED() << "Invalid pref for extension " << it.key();
   1561       continue;
   1562     }
   1563     if (!IsBlacklistBitSet(ext))
   1564       result.push_back(it.key());
   1565   }
   1566   return result;
   1567 }
   1568 
   1569 void ExtensionPrefs::FixMissingPrefs(const ExtensionIdList& extension_ids) {
   1570   // Fix old entries that did not get an installation time entry when they
   1571   // were installed or don't have a preferences field.
   1572   for (ExtensionIdList::const_iterator ext_id = extension_ids.begin();
   1573        ext_id != extension_ids.end(); ++ext_id) {
   1574     if (GetInstallTime(*ext_id) == base::Time()) {
   1575       LOG(INFO) << "Could not parse installation time of extension "
   1576                 << *ext_id << ". It was probably installed before setting "
   1577                 << kPrefInstallTime << " was introduced. Updating "
   1578                 << kPrefInstallTime << " to the current time.";
   1579       const base::Time install_time = time_provider_->GetCurrentTime();
   1580       UpdateExtensionPref(*ext_id,
   1581                           kPrefInstallTime,
   1582                           Value::CreateStringValue(base::Int64ToString(
   1583                               install_time.ToInternalValue())));
   1584     }
   1585   }
   1586 }
   1587 
   1588 void ExtensionPrefs::InitPrefStore() {
   1589   if (extensions_disabled_) {
   1590     extension_pref_value_map_->NotifyInitializationCompleted();
   1591     return;
   1592   }
   1593 
   1594   // When this is called, the PrefService is initialized and provides access
   1595   // to the user preferences stored in a JSON file.
   1596   ExtensionIdList extension_ids;
   1597   GetExtensions(&extension_ids);
   1598   // Create empty preferences dictionary for each extension (these dictionaries
   1599   // are pruned when persisting the preferences to disk).
   1600   for (ExtensionIdList::iterator ext_id = extension_ids.begin();
   1601        ext_id != extension_ids.end(); ++ext_id) {
   1602     ScopedExtensionPrefUpdate update(prefs_, *ext_id);
   1603     // This creates an empty dictionary if none is stored.
   1604     update.Get();
   1605   }
   1606 
   1607   FixMissingPrefs(extension_ids);
   1608   MigratePermissions(extension_ids);
   1609   MigrateDisableReasons(extension_ids);
   1610   extension_sorting_->Initialize(extension_ids);
   1611 
   1612   PreferenceAPI::InitExtensionControlledPrefs(this, extension_pref_value_map_);
   1613 
   1614   extension_pref_value_map_->NotifyInitializationCompleted();
   1615 }
   1616 
   1617 bool ExtensionPrefs::HasIncognitoPrefValue(const std::string& pref_key) {
   1618   bool has_incognito_pref_value = false;
   1619   extension_pref_value_map_->GetEffectivePrefValue(pref_key,
   1620                                                    true,
   1621                                                    &has_incognito_pref_value);
   1622   return has_incognito_pref_value;
   1623 }
   1624 
   1625 URLPatternSet ExtensionPrefs::GetAllowedInstallSites() {
   1626   URLPatternSet result;
   1627   const ListValue* list = prefs_->GetList(prefs::kExtensionAllowedInstallSites);
   1628   CHECK(list);
   1629 
   1630   for (size_t i = 0; i < list->GetSize(); ++i) {
   1631     std::string entry_string;
   1632     URLPattern entry(URLPattern::SCHEME_ALL);
   1633     if (!list->GetString(i, &entry_string) ||
   1634         entry.Parse(entry_string) != URLPattern::PARSE_SUCCESS) {
   1635       LOG(ERROR) << "Invalid value for preference: "
   1636                  << prefs::kExtensionAllowedInstallSites
   1637                  << "." << i;
   1638       continue;
   1639     }
   1640     result.AddPattern(entry);
   1641   }
   1642 
   1643   return result;
   1644 }
   1645 
   1646 const DictionaryValue* ExtensionPrefs::GetGeometryCache(
   1647     const std::string& extension_id) const {
   1648   const DictionaryValue* extension_prefs = GetExtensionPref(extension_id);
   1649   if (!extension_prefs)
   1650     return NULL;
   1651 
   1652   const DictionaryValue* ext = NULL;
   1653   if (!extension_prefs->GetDictionary(kPrefGeometryCache, &ext))
   1654     return NULL;
   1655 
   1656   return ext;
   1657 }
   1658 
   1659 void ExtensionPrefs::SetGeometryCache(
   1660     const std::string& extension_id,
   1661     scoped_ptr<DictionaryValue> cache) {
   1662   UpdateExtensionPref(extension_id, kPrefGeometryCache, cache.release());
   1663 }
   1664 
   1665 ExtensionPrefs::ExtensionPrefs(
   1666     PrefService* prefs,
   1667     const base::FilePath& root_dir,
   1668     ExtensionPrefValueMap* extension_pref_value_map,
   1669     scoped_ptr<TimeProvider> time_provider,
   1670     bool extensions_disabled)
   1671     : prefs_(prefs),
   1672       install_directory_(root_dir),
   1673       extension_pref_value_map_(extension_pref_value_map),
   1674       extension_sorting_(new ExtensionSorting(this)),
   1675       content_settings_store_(new ContentSettingsStore()),
   1676       time_provider_(time_provider.Pass()),
   1677       extensions_disabled_(extensions_disabled) {
   1678   MakePathsRelative();
   1679   InitPrefStore();
   1680 }
   1681 
   1682 void ExtensionPrefs::SetNeedsStorageGarbageCollection(bool value) {
   1683   prefs_->SetBoolean(prefs::kExtensionStorageGarbageCollect, value);
   1684 }
   1685 
   1686 bool ExtensionPrefs::NeedsStorageGarbageCollection() {
   1687   return prefs_->GetBoolean(prefs::kExtensionStorageGarbageCollect);
   1688 }
   1689 
   1690 // static
   1691 void ExtensionPrefs::RegisterProfilePrefs(
   1692     user_prefs::PrefRegistrySyncable* registry) {
   1693   registry->RegisterDictionaryPref(
   1694       kExtensionsPref, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1695   registry->RegisterListPref(prefs::kExtensionToolbar,
   1696                              user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
   1697   registry->RegisterIntegerPref(
   1698       prefs::kExtensionToolbarSize,
   1699       -1,  // default value
   1700       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1701   registry->RegisterDictionaryPref(
   1702       kExtensionsBlacklistUpdate,
   1703       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1704   registry->RegisterListPref(prefs::kExtensionInstallAllowList,
   1705                              user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1706   registry->RegisterListPref(prefs::kExtensionInstallDenyList,
   1707                              user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1708   registry->RegisterDictionaryPref(
   1709       prefs::kExtensionInstallForceList,
   1710       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1711   registry->RegisterListPref(prefs::kExtensionAllowedTypes,
   1712                              user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1713   registry->RegisterStringPref(
   1714       prefs::kExtensionBlacklistUpdateVersion,
   1715       "0",  // default value
   1716       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1717   registry->RegisterBooleanPref(
   1718       prefs::kExtensionStorageGarbageCollect,
   1719       false,  // default value
   1720       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1721   registry->RegisterInt64Pref(
   1722       prefs::kLastExtensionsUpdateCheck,
   1723       0,  // default value
   1724       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1725   registry->RegisterInt64Pref(
   1726       prefs::kNextExtensionsUpdateCheck,
   1727       0,  // default value
   1728       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1729   registry->RegisterListPref(prefs::kExtensionAllowedInstallSites,
   1730                              user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1731   registry->RegisterStringPref(
   1732       kExtensionsLastChromeVersion,
   1733       std::string(),  // default value
   1734       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1735 
   1736 #if defined(TOOLKIT_VIEWS)
   1737   registry->RegisterIntegerPref(
   1738       prefs::kBrowserActionContainerWidth,
   1739       0,
   1740       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   1741 #endif
   1742 }
   1743 
   1744 ExtensionIdList ExtensionPrefs::GetExtensionPrefAsVector(
   1745     const char* pref) {
   1746   ExtensionIdList extension_ids;
   1747   const ListValue* list_of_values = prefs_->GetList(pref);
   1748   if (!list_of_values)
   1749     return extension_ids;
   1750 
   1751   std::string extension_id;
   1752   for (size_t i = 0; i < list_of_values->GetSize(); ++i) {
   1753     if (list_of_values->GetString(i, &extension_id))
   1754       extension_ids.push_back(extension_id);
   1755   }
   1756   return extension_ids;
   1757 }
   1758 
   1759 void ExtensionPrefs::SetExtensionPrefFromVector(
   1760     const char* pref,
   1761     const ExtensionIdList& strings) {
   1762   ListPrefUpdate update(prefs_, pref);
   1763   ListValue* list_of_values = update.Get();
   1764   list_of_values->Clear();
   1765   for (ExtensionIdList::const_iterator iter = strings.begin();
   1766        iter != strings.end(); ++iter)
   1767     list_of_values->Append(new StringValue(*iter));
   1768 }
   1769 
   1770 void ExtensionPrefs::PopulateExtensionInfoPrefs(
   1771     const Extension* extension,
   1772     const base::Time install_time,
   1773     Extension::State initial_state,
   1774     Blacklist::BlacklistState blacklist_state,
   1775     DictionaryValue* extension_dict) {
   1776   // Leave the state blank for component extensions so that old chrome versions
   1777   // loading new profiles do not fail in GetInstalledExtensionInfo. Older
   1778   // Chrome versions would only check for an omitted state.
   1779   if (initial_state != Extension::ENABLED_COMPONENT)
   1780     extension_dict->Set(kPrefState, Value::CreateIntegerValue(initial_state));
   1781 
   1782   extension_dict->Set(kPrefLocation,
   1783                       Value::CreateIntegerValue(extension->location()));
   1784   extension_dict->Set(kPrefCreationFlags,
   1785                       Value::CreateIntegerValue(extension->creation_flags()));
   1786   extension_dict->Set(kPrefFromWebStore,
   1787                       Value::CreateBooleanValue(extension->from_webstore()));
   1788   extension_dict->Set(kPrefFromBookmark,
   1789                       Value::CreateBooleanValue(extension->from_bookmark()));
   1790   extension_dict->Set(
   1791       kPrefWasInstalledByDefault,
   1792       Value::CreateBooleanValue(extension->was_installed_by_default()));
   1793   extension_dict->Set(kPrefInstallTime,
   1794                       Value::CreateStringValue(
   1795                           base::Int64ToString(install_time.ToInternalValue())));
   1796   if (blacklist_state == Blacklist::BLACKLISTED)
   1797     extension_dict->Set(kPrefBlacklist, Value::CreateBooleanValue(true));
   1798 
   1799   base::FilePath::StringType path = MakePathRelative(install_directory_,
   1800                                                      extension->path());
   1801   extension_dict->Set(kPrefPath, Value::CreateStringValue(path));
   1802   // We store prefs about LOAD extensions, but don't cache their manifest
   1803   // since it may change on disk.
   1804   if (!Manifest::IsUnpackedLocation(extension->location())) {
   1805     extension_dict->Set(kPrefManifest,
   1806                         extension->manifest()->value()->DeepCopy());
   1807   }
   1808 }
   1809 
   1810 void ExtensionPrefs::FinishExtensionInfoPrefs(
   1811     const std::string& extension_id,
   1812     const base::Time install_time,
   1813     bool needs_sort_ordinal,
   1814     const syncer::StringOrdinal& suggested_page_ordinal,
   1815     DictionaryValue* extension_dict) {
   1816   // Reinitializes various preferences with empty dictionaries.
   1817   extension_dict->Set(pref_names::kPrefPreferences, new DictionaryValue);
   1818   extension_dict->Set(pref_names::kPrefIncognitoPreferences,
   1819                       new DictionaryValue);
   1820   extension_dict->Set(pref_names::kPrefRegularOnlyPreferences,
   1821                       new DictionaryValue);
   1822   extension_dict->Set(pref_names::kPrefContentSettings, new ListValue);
   1823   extension_dict->Set(pref_names::kPrefIncognitoContentSettings, new ListValue);
   1824 
   1825   // If this point has been reached, any pending installs should be considered
   1826   // out of date.
   1827   extension_dict->Remove(kDelayedInstallInfo, NULL);
   1828 
   1829   // Clear state that may be registered from a previous install.
   1830   extension_dict->Remove(EventRouter::kRegisteredEvents, NULL);
   1831 
   1832   // FYI, all code below here races on sudden shutdown because
   1833   // |extension_dict|, |extension_sorting_|, |extension_pref_value_map_|,
   1834   // and |content_settings_store_| are updated non-transactionally. This is
   1835   // probably not fixable without nested transactional updates to pref
   1836   // dictionaries.
   1837   if (needs_sort_ordinal) {
   1838     extension_sorting_->EnsureValidOrdinals(extension_id,
   1839                                             suggested_page_ordinal);
   1840   }
   1841 
   1842   bool is_enabled = false;
   1843   int initial_state;
   1844   if (extension_dict->GetInteger(kPrefState, &initial_state)) {
   1845     is_enabled = initial_state == Extension::ENABLED;
   1846   }
   1847 
   1848   extension_pref_value_map_->RegisterExtension(extension_id, install_time,
   1849                                                is_enabled);
   1850   content_settings_store_->RegisterExtension(extension_id, install_time,
   1851                                              is_enabled);
   1852 }
   1853 
   1854 }  // namespace extensions
   1855