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