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