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