Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / extension_prefs.cc
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
31 using base::Value;
32 using base::DictionaryValue;
33 using base::ListValue;
34
35 namespace extensions {
36
37 namespace {
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.
45 const char kPrefRunning[] = "running";
46
47 // Whether this extension had windows when it was last running.
48 const char kIsActive[] = "is_active";
49
50 // Where an extension was installed from. (see Manifest::Location)
51 const char kPrefLocation[] = "location";
52
53 // Enabled, disabled, killed, etc. (see Extension::State)
54 const char kPrefState[] = "state";
55
56 // The path to the current version's manifest file.
57 const char kPrefPath[] = "path";
58
59 // The dictionary containing the extension's manifest.
60 const char kPrefManifest[] = "manifest";
61
62 // The version number.
63 const char kPrefVersion[] = "manifest.version";
64
65 // Indicates whether an extension is blacklisted.
66 const char kPrefBlacklist[] = "blacklist";
67
68 // If extension is greylisted.
69 const char kPrefBlacklistState[] = "blacklist_state";
70
71 // The count of how many times we prompted the user to acknowledge an
72 // extension.
73 const char kPrefAcknowledgePromptCount[] = "ack_prompt_count";
74
75 // Indicates whether the user has acknowledged various types of extensions.
76 const char kPrefExternalAcknowledged[] = "ack_external";
77 const char kPrefBlacklistAcknowledged[] = "ack_blacklist";
78 const char kPrefWipeoutAcknowledged[] = "ack_wiped";
79 const char kPrefSettingsBubbleAcknowledged[] = "ack_settings_bubble";
80 const char kPrefNtpBubbleAcknowledged[] = "ack_ntp_bubble";
81
82 // Indicates whether the external extension was installed during the first
83 // run of this profile.
84 const char kPrefExternalInstallFirstRun[] = "external_first_run";
85
86 // Indicates whether to show an install warning when the user enables.
87 const 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.
91 const char kDeprecatedPrefDisableReason[] = "disable_reason";
92
93 // A bitmask of all the reasons an extension is disabled.
94 const 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.
99 const char kLastPingDay[] = "lastpingday";
100
101 // Similar to kLastPingDay, but for "active" instead of "rollcall" pings.
102 const char kLastActivePingDay[] = "last_active_pingday";
103
104 // A bit we use to keep track of whether we need to do an "active" ping.
105 const char kActiveBit[] = "active_bit";
106
107 // Path for settings specific to blacklist update.
108 const 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.
113 const char kDelayedInstallInfo[] = "idle_install_info";
114
115 // Reason why the extension's install was delayed.
116 const char kDelayedInstallReason[] = "delay_install_reason";
117
118 // Path for the suggested page ordinal of a delayed extension install.
119 const char kPrefSuggestedPageOrdinal[] = "suggested_page_ordinal";
120
121 // A preference that, if true, will allow this extension to run in incognito
122 // mode.
123 const char kPrefIncognitoEnabled[] = "incognito";
124
125 // A preference to control whether an extension is allowed to inject script in
126 // pages with file URLs.
127 const 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.
134 const 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.
141 const char kPrefActivePermissions[] = "active_permissions";
142 const char kPrefGrantedPermissions[] = "granted_permissions";
143
144 // The preference names for PermissionSet values.
145 const char kPrefAPIs[] = "api";
146 const char kPrefManifestPermissions[] = "manifest_permissions";
147 const char kPrefExplicitHosts[] = "explicit_host";
148 const char kPrefScriptableHosts[] = "scriptable_host";
149
150 // The preference names for the old granted permissions scheme.
151 const char kPrefOldGrantedFullAccess[] = "granted_permissions.full";
152 const char kPrefOldGrantedHosts[] = "granted_permissions.host";
153 const char kPrefOldGrantedAPIs[] = "granted_permissions.api";
154
155 // A preference that indicates when an extension was installed.
156 const char kPrefInstallTime[] = "install_time";
157
158 // A preference which saves the creation flags for extensions.
159 const char kPrefCreationFlags[] = "creation_flags";
160
161 // A preference that indicates whether the extension was installed from the
162 // Chrome Web Store.
163 const char kPrefFromWebStore[] = "from_webstore";
164
165 // A preference that indicates whether the extension was installed from a
166 // mock App created from a bookmark.
167 const char kPrefFromBookmark[] = "from_bookmark";
168
169 // A preference that indicates whether the extension was installed as a
170 // default app.
171 const char kPrefWasInstalledByDefault[] = "was_installed_by_default";
172
173 // A preference that indicates whether the extension was installed as an
174 // OEM app.
175 const char kPrefWasInstalledByOem[] = "was_installed_by_oem";
176
177 // Key for Geometry Cache preference.
178 const char kPrefGeometryCache[] = "geometry_cache";
179
180 // A preference that indicates when an extension is last launched.
181 const 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.
186 const char kPrefEvictedEphemeralApp[] = "evicted_ephemeral_app";
187
188 // Am installation parameter bundled with an extension.
189 const char kPrefInstallParam[] = "install_parameter";
190
191 // A list of installed ids and a signature.
192 const 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.
197 const 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.
201 const char kPrefDisableStorageNotifications[] = "disable_storage_notifications";
202
203 // Provider of write access to a dictionary storing extension prefs.
204 class 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
232 std::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.
239 bool IsBlacklistBitSet(const base::DictionaryValue* ext) {
240   bool bool_value;
241   return ext->GetBoolean(kPrefBlacklist, &bool_value) && bool_value;
242 }
243
244 bool IsEvictedEphemeralApp(const base::DictionaryValue* ext) {
245   bool bool_value;
246   return ext->GetBoolean(kPrefEvictedEphemeralApp, &bool_value) && bool_value;
247 }
248
249 void 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
277 ExtensionPrefs::TimeProvider::TimeProvider() {
278 }
279
280 ExtensionPrefs::TimeProvider::~TimeProvider() {
281 }
282
283 base::Time ExtensionPrefs::TimeProvider::GetCurrentTime() const {
284   return base::Time::Now();
285 }
286
287 //
288 // ScopedUpdate
289 //
290 template <typename T, base::Value::Type type_enum_value>
291 ExtensionPrefs::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
301 template <typename T, base::Value::Type type_enum_value>
302 ExtensionPrefs::ScopedUpdate<T, type_enum_value>::~ScopedUpdate() {
303 }
304
305 template <typename T, base::Value::Type type_enum_value>
306 T* 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
319 template <typename T, base::Value::Type type_enum_value>
320 T* 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.
340 template class ExtensionPrefs::ScopedUpdate<base::DictionaryValue,
341                                             base::Value::TYPE_DICTIONARY>;
342 template class ExtensionPrefs::ScopedUpdate<base::ListValue,
343                                             base::Value::TYPE_LIST>;
344
345 //
346 // ExtensionPrefs
347 //
348
349 // static
350 ExtensionPrefs* 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
367 ExtensionPrefs* 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
384 ExtensionPrefs::~ExtensionPrefs() {
385 }
386
387 // static
388 ExtensionPrefs* ExtensionPrefs::Get(content::BrowserContext* context) {
389   return ExtensionPrefsFactory::GetInstance()->GetForBrowserContext(context);
390 }
391
392 static 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
405 void 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
452 const 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
464 void 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
478 void 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
488 bool 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
498 bool 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
508 bool 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
518 bool 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
531 bool 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
545 bool ExtensionPrefs::HasPrefForExtension(
546     const std::string& extension_id) const {
547   return GetExtensionPref(extension_id) != NULL;
548 }
549
550 bool 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
562 void 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
569 bool 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
576 PermissionSet* 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 // ]
629 template<typename T>
630 static 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
646 void 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
677 int 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
687 bool ExtensionPrefs::IsExternalExtensionAcknowledged(
688     const std::string& extension_id) {
689   return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalAcknowledged);
690 }
691
692 void 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
700 bool ExtensionPrefs::IsBlacklistedExtensionAcknowledged(
701     const std::string& extension_id) {
702   return ReadPrefAsBooleanAndReturn(extension_id, kPrefBlacklistAcknowledged);
703 }
704
705 void 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
713 bool ExtensionPrefs::IsExternalInstallFirstRun(
714     const std::string& extension_id) {
715   return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalInstallFirstRun);
716 }
717
718 void 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
725 bool ExtensionPrefs::HasWipeoutBeenAcknowledged(
726     const std::string& extension_id) {
727   return ReadPrefAsBooleanAndReturn(extension_id, kPrefWipeoutAcknowledged);
728 }
729
730 void 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
737 bool ExtensionPrefs::HasSettingsApiBubbleBeenAcknowledged(
738     const std::string& extension_id) {
739   return ReadPrefAsBooleanAndReturn(extension_id,
740                                     kPrefSettingsBubbleAcknowledged);
741 }
742
743 void 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
751 bool ExtensionPrefs::HasNtpOverriddenBubbleBeenAcknowledged(
752     const std::string& extension_id) {
753   return ReadPrefAsBooleanAndReturn(extension_id, kPrefNtpBubbleAcknowledged);
754 }
755
756 void 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
764 bool 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
772 bool ExtensionPrefs::ExtensionsBlacklistedByDefault() const {
773   return admin_policy::BlacklistedByDefault(
774       prefs_->GetList(pref_names::kInstallDenyList));
775 }
776
777 bool ExtensionPrefs::DidExtensionEscalatePermissions(
778     const std::string& extension_id) {
779   return ReadPrefAsBooleanAndReturn(extension_id,
780                                     kExtensionDidEscalatePermissions);
781 }
782
783 void ExtensionPrefs::SetDidExtensionEscalatePermissions(
784     const Extension* extension, bool did_escalate) {
785   UpdateExtensionPref(extension->id(), kExtensionDidEscalatePermissions,
786                       new base::FundamentalValue(did_escalate));
787 }
788
789 int 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
798 void ExtensionPrefs::AddDisableReason(const std::string& extension_id,
799                                       Extension::DisableReason disable_reason) {
800   ModifyDisableReason(extension_id, disable_reason, DISABLE_REASON_ADD);
801 }
802
803 void ExtensionPrefs::RemoveDisableReason(
804     const std::string& extension_id,
805     Extension::DisableReason disable_reason) {
806   ModifyDisableReason(extension_id, disable_reason, DISABLE_REASON_REMOVE);
807 }
808
809 void ExtensionPrefs::ClearDisableReasons(const std::string& extension_id) {
810   ModifyDisableReason(
811       extension_id, Extension::DISABLE_NONE, DISABLE_REASON_CLEAR);
812 }
813
814 void 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
847 std::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
870 void 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
892 bool ExtensionPrefs::IsExtensionBlacklisted(const std::string& id) const {
893   const base::DictionaryValue* ext_prefs = GetExtensionPref(id);
894   return ext_prefs && IsBlacklistBitSet(ext_prefs);
895 }
896
897 namespace {
898
899 // Serializes a 64bit integer as a string value.
900 void 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.
911 bool 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|.
925 void 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).
933 base::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
943 base::Time ExtensionPrefs::LastPingDay(const std::string& extension_id) const {
944   DCHECK(Extension::IdIsValid(extension_id));
945   return ReadTime(GetExtensionPref(extension_id), kLastPingDay);
946 }
947
948 void 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
955 base::Time ExtensionPrefs::BlacklistLastPingDay() const {
956   return ReadTime(prefs_->GetDictionary(kExtensionsBlacklistUpdate),
957                   kLastPingDay);
958 }
959
960 void ExtensionPrefs::SetBlacklistLastPingDay(const base::Time& time) {
961   DictionaryPrefUpdate update(prefs_, kExtensionsBlacklistUpdate);
962   SaveTime(update.Get(), kLastPingDay, time);
963 }
964
965 base::Time ExtensionPrefs::LastActivePingDay(const std::string& extension_id) {
966   DCHECK(Extension::IdIsValid(extension_id));
967   return ReadTime(GetExtensionPref(extension_id), kLastActivePingDay);
968 }
969
970 void 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
977 bool 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
985 void ExtensionPrefs::SetActiveBit(const std::string& extension_id,
986                                   bool active) {
987   UpdateExtensionPref(extension_id, kActiveBit,
988                       new base::FundamentalValue(active));
989 }
990
991 void 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
1042 void 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
1069 PermissionSet* ExtensionPrefs::GetGrantedPermissions(
1070     const std::string& extension_id) {
1071   CHECK(Extension::IdIsValid(extension_id));
1072   return ReadPrefAsPermissionSet(extension_id, kPrefGrantedPermissions);
1073 }
1074
1075 void 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
1093 void 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
1111 PermissionSet* ExtensionPrefs::GetActivePermissions(
1112     const std::string& extension_id) {
1113   CHECK(Extension::IdIsValid(extension_id));
1114   return ReadPrefAsPermissionSet(extension_id, kPrefActivePermissions);
1115 }
1116
1117 void ExtensionPrefs::SetActivePermissions(
1118     const std::string& extension_id,
1119     const PermissionSet* permissions) {
1120   SetExtensionPrefPermissionSet(
1121       extension_id, kPrefActivePermissions, permissions);
1122 }
1123
1124 void 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
1130 bool 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
1139 void 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
1145 bool 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
1154 bool ExtensionPrefs::IsIncognitoEnabled(const std::string& extension_id) const {
1155   return ReadPrefAsBooleanAndReturn(extension_id, kPrefIncognitoEnabled);
1156 }
1157
1158 void 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
1165 bool ExtensionPrefs::AllowFileAccess(const std::string& extension_id) const {
1166   return ReadPrefAsBooleanAndReturn(extension_id, kPrefAllowFileAccess);
1167 }
1168
1169 void ExtensionPrefs::SetAllowFileAccess(const std::string& extension_id,
1170                                         bool allow) {
1171   UpdateExtensionPref(extension_id, kPrefAllowFileAccess,
1172                       new base::FundamentalValue(allow));
1173 }
1174
1175 bool 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
1181 bool 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
1196 bool ExtensionPrefs::IsExternalExtensionUninstalled(
1197     const std::string& id) const {
1198   return DoesExtensionHaveState(id, Extension::EXTERNAL_EXTENSION_UNINSTALLED);
1199 }
1200
1201 bool ExtensionPrefs::IsExtensionDisabled(
1202     const std::string& id) const {
1203   return DoesExtensionHaveState(id, Extension::DISABLED);
1204 }
1205
1206 ExtensionIdList ExtensionPrefs::GetToolbarOrder() {
1207   ExtensionIdList id_list_out;
1208   GetUserExtensionPrefIntoContainer(pref_names::kToolbar, &id_list_out);
1209   return id_list_out;
1210 }
1211
1212 void ExtensionPrefs::SetToolbarOrder(const ExtensionIdList& extension_ids) {
1213   SetExtensionPrefFromContainer(pref_names::kToolbar, extension_ids);
1214 }
1215
1216 bool ExtensionPrefs::GetKnownDisabled(ExtensionIdSet* id_set_out) {
1217   return GetUserExtensionPrefIntoContainer(pref_names::kKnownDisabled,
1218                                            id_set_out);
1219 }
1220
1221 void ExtensionPrefs::SetKnownDisabled(const ExtensionIdSet& extension_ids) {
1222   SetExtensionPrefFromContainer(pref_names::kKnownDisabled, extension_ids);
1223 }
1224
1225 void 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
1245 void 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
1274 void 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
1285 void 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
1292 BlacklistState 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
1304 std::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
1315 void 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
1332 base::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
1345 scoped_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
1384 scoped_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
1413 scoped_ptr<ExtensionPrefs::ExtensionsInfo>
1414 ExtensionPrefs::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
1433 scoped_ptr<ExtensionPrefs::ExtensionsInfo>
1434 ExtensionPrefs::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
1456 void 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
1486 bool 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
1495 bool 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
1535 scoped_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
1549 ExtensionPrefs::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
1567 scoped_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
1586 scoped_ptr<ExtensionPrefs::ExtensionsInfo>
1587 ExtensionPrefs::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
1612 scoped_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
1624 void 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
1634 bool ExtensionPrefs::WasAppDraggedByUser(const std::string& extension_id) {
1635   return ReadPrefAsBooleanAndReturn(extension_id, kPrefUserDraggedApp);
1636 }
1637
1638 void ExtensionPrefs::SetAppDraggedByUser(const std::string& extension_id) {
1639   UpdateExtensionPref(extension_id, kPrefUserDraggedApp,
1640                       new base::FundamentalValue(true));
1641 }
1642
1643 bool 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
1652 bool 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
1661 int 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
1678 int 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
1688 bool 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
1698 bool 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
1706 base::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
1722 base::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
1737 void 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
1744 void 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
1756 ExtensionIdList 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
1781 void ExtensionPrefs::AddObserver(ExtensionPrefsObserver* observer) {
1782   observer_list_.AddObserver(observer);
1783 }
1784
1785 void ExtensionPrefs::RemoveObserver(ExtensionPrefsObserver* observer) {
1786   observer_list_.RemoveObserver(observer);
1787 }
1788
1789 void 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
1808 void 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
1837 bool 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
1845 URLPatternSet 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
1866 const 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
1879 void ExtensionPrefs::SetGeometryCache(
1880     const std::string& extension_id,
1881     scoped_ptr<base::DictionaryValue> cache) {
1882   UpdateExtensionPref(extension_id, kPrefGeometryCache, cache.release());
1883 }
1884
1885 const base::DictionaryValue* ExtensionPrefs::GetInstallSignature() {
1886   return prefs_->GetDictionary(kInstallSignature);
1887 }
1888
1889 void 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
1900 std::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
1911 void 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
1918 int64 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
1930 void 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
1936 bool 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
1948 void 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
1956 ExtensionPrefs::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
1984 void ExtensionPrefs::SetNeedsStorageGarbageCollection(bool value) {
1985   prefs_->SetBoolean(pref_names::kStorageGarbageCollect, value);
1986 }
1987
1988 bool ExtensionPrefs::NeedsStorageGarbageCollection() {
1989   return prefs_->GetBoolean(pref_names::kStorageGarbageCollect);
1990 }
1991
1992 // static
1993 void 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
2056 template <class ExtensionIdContainer>
2057 bool 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
2081 template <class ExtensionIdContainer>
2082 void 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
2094 void 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
2142 void 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
2179 void 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