Add unit test for the Settings API Bubble.
[chromium-blink-merge.git] / extensions / browser / extension_prefs.cc
blob7cbf38cdce1f8697868a1719cbde3fc81561a8ee
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.
5 #include "extensions/browser/extension_prefs.h"
7 #include <iterator>
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"
31 using base::Value;
32 using base::DictionaryValue;
33 using base::ListValue;
35 namespace extensions {
37 namespace {
39 // Additional preferences keys, which are not needed by external clients.
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";
47 // Whether this extension had windows when it was last running.
48 const char kIsActive[] = "is_active";
50 // Where an extension was installed from. (see Manifest::Location)
51 const char kPrefLocation[] = "location";
53 // Enabled, disabled, killed, etc. (see Extension::State)
54 const char kPrefState[] = "state";
56 // The path to the current version's manifest file.
57 const char kPrefPath[] = "path";
59 // The dictionary containing the extension's manifest.
60 const char kPrefManifest[] = "manifest";
62 // The version number.
63 const char kPrefVersion[] = "manifest.version";
65 // Indicates whether an extension is blacklisted.
66 const char kPrefBlacklist[] = "blacklist";
68 // If extension is greylisted.
69 const char kPrefBlacklistState[] = "blacklist_state";
71 // The count of how many times we prompted the user to acknowledge an
72 // extension.
73 const char kPrefAcknowledgePromptCount[] = "ack_prompt_count";
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";
81 // Indicates whether the external extension was installed during the first
82 // run of this profile.
83 const char kPrefExternalInstallFirstRun[] = "external_first_run";
85 // Indicates whether to show an install warning when the user enables.
86 const char kExtensionDidEscalatePermissions[] = "install_warning_on_enable";
88 // DO NOT USE, use kPrefDisableReasons instead.
89 // Indicates whether the extension was updated while it was disabled.
90 const char kDeprecatedPrefDisableReason[] = "disable_reason";
92 // A bitmask of all the reasons an extension is disabled.
93 const char kPrefDisableReasons[] = "disable_reasons";
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";
100 // Similar to kLastPingDay, but for "active" instead of "rollcall" pings.
101 const char kLastActivePingDay[] = "last_active_pingday";
103 // A bit we use to keep track of whether we need to do an "active" ping.
104 const char kActiveBit[] = "active_bit";
106 // Path for settings specific to blacklist update.
107 const char kExtensionsBlacklistUpdate[] = "extensions.blacklistupdate";
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";
114 // Reason why the extension's install was delayed.
115 const char kDelayedInstallReason[] = "delay_install_reason";
117 // Path for the suggested page ordinal of a delayed extension install.
118 const char kPrefSuggestedPageOrdinal[] = "suggested_page_ordinal";
120 // A preference that, if true, will allow this extension to run in incognito
121 // mode.
122 const char kPrefIncognitoEnabled[] = "incognito";
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";
132 // A preference specifying if the user dragged the app on the NTP.
133 const char kPrefUserDraggedApp[] = "user_dragged_app_ntp";
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";
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";
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";
154 // A preference that indicates when an extension was installed.
155 const char kPrefInstallTime[] = "install_time";
157 // A preference which saves the creation flags for extensions.
158 const char kPrefCreationFlags[] = "creation_flags";
160 // A preference that indicates whether the extension was installed from the
161 // Chrome Web Store.
162 const char kPrefFromWebStore[] = "from_webstore";
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";
168 // A preference that indicates whether the extension was installed as a
169 // default app.
170 const char kPrefWasInstalledByDefault[] = "was_installed_by_default";
172 // A preference that indicates whether the extension was installed as an
173 // OEM app.
174 const char kPrefWasInstalledByOem[] = "was_installed_by_oem";
176 // Key for Geometry Cache preference.
177 const char kPrefGeometryCache[] = "geometry_cache";
179 // A preference that indicates when an extension is last launched.
180 const char kPrefLastLaunchTime[] = "last_launch_time";
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";
187 // Am installation parameter bundled with an extension.
188 const char kPrefInstallParam[] = "install_parameter";
190 // A list of installed ids and a signature.
191 const char kInstallSignature[] = "extensions.install_signature";
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) {}
201 virtual ~ScopedExtensionPrefUpdate() {
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);
213 return extension;
216 private:
217 const std::string extension_id_;
219 DISALLOW_COPY_AND_ASSIGN(ScopedExtensionPrefUpdate);
222 std::string JoinPrefs(const std::string& parent, const char* child) {
223 return parent + "." + child;
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;
234 bool IsEvictedEphemeralApp(const base::DictionaryValue* ext) {
235 bool bool_value;
236 return ext->GetBoolean(kPrefEvictedEphemeralApp, &bool_value) && bool_value;
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;
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;
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());
261 } // namespace
264 // TimeProvider
267 ExtensionPrefs::TimeProvider::TimeProvider() {
270 ExtensionPrefs::TimeProvider::~TimeProvider() {
273 base::Time ExtensionPrefs::TimeProvider::GetCurrentTime() const {
274 return base::Time::Now();
278 // ScopedUpdate
280 template <typename T, base::Value::Type type_enum_value>
281 ExtensionPrefs::ScopedUpdate<T, type_enum_value>::ScopedUpdate(
282 ExtensionPrefs* prefs,
283 const std::string& extension_id,
284 const std::string& key)
285 : update_(prefs->pref_service(), pref_names::kExtensions),
286 extension_id_(extension_id),
287 key_(key) {
288 DCHECK(Extension::IdIsValid(extension_id_));
291 template <typename T, base::Value::Type type_enum_value>
292 ExtensionPrefs::ScopedUpdate<T, type_enum_value>::~ScopedUpdate() {
295 template <typename T, base::Value::Type type_enum_value>
296 T* ExtensionPrefs::ScopedUpdate<T, type_enum_value>::Get() {
297 base::DictionaryValue* dict = update_.Get();
298 base::DictionaryValue* extension = NULL;
299 base::Value* key_value = NULL;
300 if (!dict->GetDictionary(extension_id_, &extension) ||
301 !extension->Get(key_, &key_value)) {
302 return NULL;
304 return key_value->GetType() == type_enum_value ?
305 static_cast<T*>(key_value) :
306 NULL;
309 template <typename T, base::Value::Type type_enum_value>
310 T* ExtensionPrefs::ScopedUpdate<T, type_enum_value>::Create() {
311 base::DictionaryValue* dict = update_.Get();
312 base::DictionaryValue* extension = NULL;
313 base::Value* key_value = NULL;
314 T* value_as_t = NULL;
315 if (!dict->GetDictionary(extension_id_, &extension)) {
316 extension = new base::DictionaryValue;
317 dict->SetWithoutPathExpansion(extension_id_, extension);
319 if (!extension->Get(key_, &key_value)) {
320 value_as_t = new T;
321 extension->SetWithoutPathExpansion(key_, value_as_t);
322 } else {
323 CHECK(key_value->GetType() == type_enum_value);
324 value_as_t = static_cast<T*>(key_value);
326 return value_as_t;
329 // Explicit instantiations for Dictionary and List value types.
330 template class ExtensionPrefs::ScopedUpdate<base::DictionaryValue,
331 base::Value::TYPE_DICTIONARY>;
332 template class ExtensionPrefs::ScopedUpdate<base::ListValue,
333 base::Value::TYPE_LIST>;
336 // ExtensionPrefs
339 // static
340 ExtensionPrefs* ExtensionPrefs::Create(
341 PrefService* prefs,
342 const base::FilePath& root_dir,
343 ExtensionPrefValueMap* extension_pref_value_map,
344 scoped_ptr<AppSorting> app_sorting,
345 bool extensions_disabled,
346 const std::vector<ExtensionPrefsObserver*>& early_observers) {
347 return ExtensionPrefs::Create(prefs,
348 root_dir,
349 extension_pref_value_map,
350 app_sorting.Pass(),
351 extensions_disabled,
352 early_observers,
353 make_scoped_ptr(new TimeProvider()));
356 // static
357 ExtensionPrefs* ExtensionPrefs::Create(
358 PrefService* pref_service,
359 const base::FilePath& root_dir,
360 ExtensionPrefValueMap* extension_pref_value_map,
361 scoped_ptr<AppSorting> app_sorting,
362 bool extensions_disabled,
363 const std::vector<ExtensionPrefsObserver*>& early_observers,
364 scoped_ptr<TimeProvider> time_provider) {
365 return new ExtensionPrefs(pref_service,
366 root_dir,
367 extension_pref_value_map,
368 app_sorting.Pass(),
369 time_provider.Pass(),
370 extensions_disabled,
371 early_observers);
374 ExtensionPrefs::~ExtensionPrefs() {
377 // static
378 ExtensionPrefs* ExtensionPrefs::Get(content::BrowserContext* context) {
379 return ExtensionPrefsFactory::GetInstance()->GetForBrowserContext(context);
382 static base::FilePath::StringType MakePathRelative(const base::FilePath& parent,
383 const base::FilePath& child) {
384 if (!parent.IsParent(child))
385 return child.value();
387 base::FilePath::StringType retval = child.value().substr(
388 parent.value().length());
389 if (base::FilePath::IsSeparator(retval[0]))
390 return retval.substr(1);
391 else
392 return retval;
395 void ExtensionPrefs::MakePathsRelative() {
396 const base::DictionaryValue* dict =
397 prefs_->GetDictionary(pref_names::kExtensions);
398 if (!dict || dict->empty())
399 return;
401 // Collect all extensions ids with absolute paths in |absolute_keys|.
402 std::set<std::string> absolute_keys;
403 for (base::DictionaryValue::Iterator i(*dict); !i.IsAtEnd(); i.Advance()) {
404 const base::DictionaryValue* extension_dict = NULL;
405 if (!i.value().GetAsDictionary(&extension_dict))
406 continue;
407 int location_value;
408 if (extension_dict->GetInteger(kPrefLocation, &location_value) &&
409 Manifest::IsUnpackedLocation(
410 static_cast<Manifest::Location>(location_value))) {
411 // Unpacked extensions can have absolute paths.
412 continue;
414 base::FilePath::StringType path_string;
415 if (!extension_dict->GetString(kPrefPath, &path_string))
416 continue;
417 base::FilePath path(path_string);
418 if (path.IsAbsolute())
419 absolute_keys.insert(i.key());
421 if (absolute_keys.empty())
422 return;
424 // Fix these paths.
425 DictionaryPrefUpdate update(prefs_, pref_names::kExtensions);
426 base::DictionaryValue* update_dict = update.Get();
427 for (std::set<std::string>::iterator i = absolute_keys.begin();
428 i != absolute_keys.end(); ++i) {
429 base::DictionaryValue* extension_dict = NULL;
430 if (!update_dict->GetDictionaryWithoutPathExpansion(*i, &extension_dict)) {
431 NOTREACHED() << "Control should never reach here for extension " << *i;
432 continue;
434 base::FilePath::StringType path_string;
435 extension_dict->GetString(kPrefPath, &path_string);
436 base::FilePath path(path_string);
437 extension_dict->SetString(kPrefPath,
438 MakePathRelative(install_directory_, path));
442 const base::DictionaryValue* ExtensionPrefs::GetExtensionPref(
443 const std::string& extension_id) const {
444 const base::DictionaryValue* extensions =
445 prefs_->GetDictionary(pref_names::kExtensions);
446 const base::DictionaryValue* extension_dict = NULL;
447 if (!extensions ||
448 !extensions->GetDictionary(extension_id, &extension_dict)) {
449 return NULL;
451 return extension_dict;
454 void ExtensionPrefs::UpdateExtensionPref(const std::string& extension_id,
455 const std::string& key,
456 base::Value* data_value) {
457 if (!Extension::IdIsValid(extension_id)) {
458 NOTREACHED() << "Invalid extension_id " << extension_id;
459 return;
461 ScopedExtensionPrefUpdate update(prefs_, extension_id);
462 if (data_value)
463 update->Set(key, data_value);
464 else
465 update->Remove(key, NULL);
468 void ExtensionPrefs::DeleteExtensionPrefs(const std::string& extension_id) {
469 extension_pref_value_map_->UnregisterExtension(extension_id);
470 FOR_EACH_OBSERVER(ExtensionPrefsObserver,
471 observer_list_,
472 OnExtensionPrefsDeleted(extension_id));
473 DictionaryPrefUpdate update(prefs_, pref_names::kExtensions);
474 base::DictionaryValue* dict = update.Get();
475 dict->Remove(extension_id, NULL);
478 bool ExtensionPrefs::ReadPrefAsBoolean(const std::string& extension_id,
479 const std::string& pref_key,
480 bool* out_value) const {
481 const base::DictionaryValue* ext = GetExtensionPref(extension_id);
482 if (!ext || !ext->GetBoolean(pref_key, out_value))
483 return false;
485 return true;
488 bool ExtensionPrefs::ReadPrefAsInteger(const std::string& extension_id,
489 const std::string& pref_key,
490 int* out_value) const {
491 const base::DictionaryValue* ext = GetExtensionPref(extension_id);
492 if (!ext || !ext->GetInteger(pref_key, out_value))
493 return false;
495 return true;
498 bool ExtensionPrefs::ReadPrefAsString(const std::string& extension_id,
499 const std::string& pref_key,
500 std::string* out_value) const {
501 const base::DictionaryValue* ext = GetExtensionPref(extension_id);
502 if (!ext || !ext->GetString(pref_key, out_value))
503 return false;
505 return true;
508 bool ExtensionPrefs::ReadPrefAsList(const std::string& extension_id,
509 const std::string& pref_key,
510 const base::ListValue** out_value) const {
511 const base::DictionaryValue* ext = GetExtensionPref(extension_id);
512 const base::ListValue* out = NULL;
513 if (!ext || !ext->GetList(pref_key, &out))
514 return false;
515 if (out_value)
516 *out_value = out;
518 return true;
521 bool ExtensionPrefs::ReadPrefAsDictionary(
522 const std::string& extension_id,
523 const std::string& pref_key,
524 const base::DictionaryValue** out_value) const {
525 const base::DictionaryValue* ext = GetExtensionPref(extension_id);
526 const base::DictionaryValue* out = NULL;
527 if (!ext || !ext->GetDictionary(pref_key, &out))
528 return false;
529 if (out_value)
530 *out_value = out;
532 return true;
535 bool ExtensionPrefs::HasPrefForExtension(
536 const std::string& extension_id) const {
537 return GetExtensionPref(extension_id) != NULL;
540 bool ExtensionPrefs::ReadPrefAsURLPatternSet(const std::string& extension_id,
541 const std::string& pref_key,
542 URLPatternSet* result,
543 int valid_schemes) {
544 const base::ListValue* value = NULL;
545 if (!ReadPrefAsList(extension_id, pref_key, &value))
546 return false;
548 bool allow_file_access = AllowFileAccess(extension_id);
549 return result->Populate(*value, valid_schemes, allow_file_access, NULL);
552 void ExtensionPrefs::SetExtensionPrefURLPatternSet(
553 const std::string& extension_id,
554 const std::string& pref_key,
555 const URLPatternSet& new_value) {
556 UpdateExtensionPref(extension_id, pref_key, new_value.ToValue().release());
559 bool ExtensionPrefs::ReadPrefAsBooleanAndReturn(
560 const std::string& extension_id,
561 const std::string& pref_key) const {
562 bool out_value = false;
563 return ReadPrefAsBoolean(extension_id, pref_key, &out_value) && out_value;
566 PermissionSet* ExtensionPrefs::ReadPrefAsPermissionSet(
567 const std::string& extension_id,
568 const std::string& pref_key) {
569 if (!GetExtensionPref(extension_id))
570 return NULL;
572 // Retrieve the API permissions. Please refer SetExtensionPrefPermissionSet()
573 // for api_values format.
574 APIPermissionSet apis;
575 const base::ListValue* api_values = NULL;
576 std::string api_pref = JoinPrefs(pref_key, kPrefAPIs);
577 if (ReadPrefAsList(extension_id, api_pref, &api_values)) {
578 APIPermissionSet::ParseFromJSON(api_values,
579 APIPermissionSet::kAllowInternalPermissions,
580 &apis, NULL, NULL);
583 // Retrieve the Manifest Keys permissions. Please refer to
584 // |SetExtensionPrefPermissionSet| for manifest_permissions_values format.
585 ManifestPermissionSet manifest_permissions;
586 const base::ListValue* manifest_permissions_values = NULL;
587 std::string manifest_permission_pref =
588 JoinPrefs(pref_key, kPrefManifestPermissions);
589 if (ReadPrefAsList(extension_id, manifest_permission_pref,
590 &manifest_permissions_values)) {
591 ManifestPermissionSet::ParseFromJSON(
592 manifest_permissions_values, &manifest_permissions, NULL, NULL);
595 // Retrieve the explicit host permissions.
596 URLPatternSet explicit_hosts;
597 ReadPrefAsURLPatternSet(
598 extension_id, JoinPrefs(pref_key, kPrefExplicitHosts),
599 &explicit_hosts, Extension::kValidHostPermissionSchemes);
601 // Retrieve the scriptable host permissions.
602 URLPatternSet scriptable_hosts;
603 ReadPrefAsURLPatternSet(
604 extension_id, JoinPrefs(pref_key, kPrefScriptableHosts),
605 &scriptable_hosts, UserScript::ValidUserScriptSchemes());
607 return new PermissionSet(
608 apis, manifest_permissions, explicit_hosts, scriptable_hosts);
611 // Set the API or Manifest permissions.
612 // The format of api_values is:
613 // [ "permission_name1", // permissions do not support detail.
614 // "permission_name2",
615 // {"permission_name3": value },
616 // // permission supports detail, permission detail will be stored in value.
617 // ...
618 // ]
619 template<typename T>
620 static base::ListValue* CreatePermissionList(const T& permissions) {
621 base::ListValue* values = new base::ListValue();
622 for (typename T::const_iterator i = permissions.begin();
623 i != permissions.end(); ++i) {
624 scoped_ptr<base::Value> detail(i->ToValue());
625 if (detail) {
626 base::DictionaryValue* tmp = new base::DictionaryValue();
627 tmp->Set(i->name(), detail.release());
628 values->Append(tmp);
629 } else {
630 values->Append(new base::StringValue(i->name()));
633 return values;
636 void ExtensionPrefs::SetExtensionPrefPermissionSet(
637 const std::string& extension_id,
638 const std::string& pref_key,
639 const PermissionSet* new_value) {
640 std::string api_pref = JoinPrefs(pref_key, kPrefAPIs);
641 base::ListValue* api_values = CreatePermissionList(new_value->apis());
642 UpdateExtensionPref(extension_id, api_pref, api_values);
644 std::string manifest_permissions_pref =
645 JoinPrefs(pref_key, kPrefManifestPermissions);
646 base::ListValue* manifest_permissions_values = CreatePermissionList(
647 new_value->manifest_permissions());
648 UpdateExtensionPref(extension_id,
649 manifest_permissions_pref,
650 manifest_permissions_values);
652 // Set the explicit host permissions.
653 if (!new_value->explicit_hosts().is_empty()) {
654 SetExtensionPrefURLPatternSet(extension_id,
655 JoinPrefs(pref_key, kPrefExplicitHosts),
656 new_value->explicit_hosts());
659 // Set the scriptable host permissions.
660 if (!new_value->scriptable_hosts().is_empty()) {
661 SetExtensionPrefURLPatternSet(extension_id,
662 JoinPrefs(pref_key, kPrefScriptableHosts),
663 new_value->scriptable_hosts());
667 int ExtensionPrefs::IncrementAcknowledgePromptCount(
668 const std::string& extension_id) {
669 int count = 0;
670 ReadPrefAsInteger(extension_id, kPrefAcknowledgePromptCount, &count);
671 ++count;
672 UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount,
673 new base::FundamentalValue(count));
674 return count;
677 bool ExtensionPrefs::IsExternalExtensionAcknowledged(
678 const std::string& extension_id) {
679 return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalAcknowledged);
682 void ExtensionPrefs::AcknowledgeExternalExtension(
683 const std::string& extension_id) {
684 DCHECK(Extension::IdIsValid(extension_id));
685 UpdateExtensionPref(extension_id, kPrefExternalAcknowledged,
686 new base::FundamentalValue(true));
687 UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, NULL);
690 bool ExtensionPrefs::IsBlacklistedExtensionAcknowledged(
691 const std::string& extension_id) {
692 return ReadPrefAsBooleanAndReturn(extension_id, kPrefBlacklistAcknowledged);
695 void ExtensionPrefs::AcknowledgeBlacklistedExtension(
696 const std::string& extension_id) {
697 DCHECK(Extension::IdIsValid(extension_id));
698 UpdateExtensionPref(extension_id, kPrefBlacklistAcknowledged,
699 new base::FundamentalValue(true));
700 UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, NULL);
703 bool ExtensionPrefs::IsExternalInstallFirstRun(
704 const std::string& extension_id) {
705 return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalInstallFirstRun);
708 void ExtensionPrefs::SetExternalInstallFirstRun(
709 const std::string& extension_id) {
710 DCHECK(Extension::IdIsValid(extension_id));
711 UpdateExtensionPref(extension_id, kPrefExternalInstallFirstRun,
712 new base::FundamentalValue(true));
715 bool ExtensionPrefs::HasWipeoutBeenAcknowledged(
716 const std::string& extension_id) {
717 return ReadPrefAsBooleanAndReturn(extension_id, kPrefWipeoutAcknowledged);
720 void ExtensionPrefs::SetWipeoutAcknowledged(
721 const std::string& extension_id,
722 bool value) {
723 UpdateExtensionPref(extension_id, kPrefWipeoutAcknowledged,
724 value ? base::Value::CreateBooleanValue(value) : NULL);
727 bool ExtensionPrefs::HasSettingsApiBubbleBeenAcknowledged(
728 const std::string& extension_id) {
729 return ReadPrefAsBooleanAndReturn(extension_id,
730 kPrefSettingsBubbleAcknowledged);
733 void ExtensionPrefs::SetSettingsApiBubbleBeenAcknowledged(
734 const std::string& extension_id,
735 bool value) {
736 UpdateExtensionPref(extension_id,
737 kPrefSettingsBubbleAcknowledged,
738 value ? base::Value::CreateBooleanValue(value) : NULL);
741 bool ExtensionPrefs::SetAlertSystemFirstRun() {
742 if (prefs_->GetBoolean(pref_names::kAlertsInitialized)) {
743 return true;
745 prefs_->SetBoolean(pref_names::kAlertsInitialized, true);
746 return false;
749 bool ExtensionPrefs::ExtensionsBlacklistedByDefault() const {
750 return admin_policy::BlacklistedByDefault(
751 prefs_->GetList(pref_names::kInstallDenyList));
754 bool ExtensionPrefs::DidExtensionEscalatePermissions(
755 const std::string& extension_id) {
756 return ReadPrefAsBooleanAndReturn(extension_id,
757 kExtensionDidEscalatePermissions);
760 void ExtensionPrefs::SetDidExtensionEscalatePermissions(
761 const Extension* extension, bool did_escalate) {
762 UpdateExtensionPref(extension->id(), kExtensionDidEscalatePermissions,
763 new base::FundamentalValue(did_escalate));
766 int ExtensionPrefs::GetDisableReasons(const std::string& extension_id) const {
767 int value = -1;
768 if (ReadPrefAsInteger(extension_id, kPrefDisableReasons, &value) &&
769 value >= 0) {
770 return value;
772 return Extension::DISABLE_NONE;
775 void ExtensionPrefs::AddDisableReason(const std::string& extension_id,
776 Extension::DisableReason disable_reason) {
777 ModifyDisableReason(extension_id, disable_reason, DISABLE_REASON_ADD);
780 void ExtensionPrefs::RemoveDisableReason(
781 const std::string& extension_id,
782 Extension::DisableReason disable_reason) {
783 ModifyDisableReason(extension_id, disable_reason, DISABLE_REASON_REMOVE);
786 void ExtensionPrefs::ClearDisableReasons(const std::string& extension_id) {
787 ModifyDisableReason(
788 extension_id, Extension::DISABLE_NONE, DISABLE_REASON_CLEAR);
791 void ExtensionPrefs::ModifyDisableReason(const std::string& extension_id,
792 Extension::DisableReason reason,
793 DisableReasonChange change) {
794 int old_value = GetDisableReasons(extension_id);
795 int new_value = old_value;
796 switch (change) {
797 case DISABLE_REASON_ADD:
798 new_value |= static_cast<int>(reason);
799 break;
800 case DISABLE_REASON_REMOVE:
801 new_value &= ~static_cast<int>(reason);
802 break;
803 case DISABLE_REASON_CLEAR:
804 new_value = Extension::DISABLE_NONE;
805 break;
808 if (old_value == new_value) // no change, return.
809 return;
811 if (new_value == Extension::DISABLE_NONE) {
812 UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL);
813 } else {
814 UpdateExtensionPref(extension_id,
815 kPrefDisableReasons,
816 new base::FundamentalValue(new_value));
819 FOR_EACH_OBSERVER(ExtensionPrefsObserver,
820 observer_list_,
821 OnExtensionDisableReasonsChanged(extension_id, new_value));
824 std::set<std::string> ExtensionPrefs::GetBlacklistedExtensions() {
825 std::set<std::string> ids;
827 const base::DictionaryValue* extensions =
828 prefs_->GetDictionary(pref_names::kExtensions);
829 if (!extensions)
830 return ids;
832 for (base::DictionaryValue::Iterator it(*extensions);
833 !it.IsAtEnd(); it.Advance()) {
834 if (!it.value().IsType(base::Value::TYPE_DICTIONARY)) {
835 NOTREACHED() << "Invalid pref for extension " << it.key();
836 continue;
838 if (IsBlacklistBitSet(
839 static_cast<const base::DictionaryValue*>(&it.value()))) {
840 ids.insert(it.key());
844 return ids;
847 void ExtensionPrefs::SetExtensionBlacklisted(const std::string& extension_id,
848 bool is_blacklisted) {
849 bool currently_blacklisted = IsExtensionBlacklisted(extension_id);
850 if (is_blacklisted == currently_blacklisted)
851 return;
853 // Always make sure the "acknowledged" bit is cleared since the blacklist bit
854 // is changing.
855 UpdateExtensionPref(extension_id, kPrefBlacklistAcknowledged, NULL);
857 if (is_blacklisted) {
858 UpdateExtensionPref(extension_id,
859 kPrefBlacklist,
860 new base::FundamentalValue(true));
861 } else {
862 UpdateExtensionPref(extension_id, kPrefBlacklist, NULL);
863 const base::DictionaryValue* dict = GetExtensionPref(extension_id);
864 if (dict && dict->empty())
865 DeleteExtensionPrefs(extension_id);
869 bool ExtensionPrefs::IsExtensionBlacklisted(const std::string& id) const {
870 const base::DictionaryValue* ext_prefs = GetExtensionPref(id);
871 return ext_prefs && IsBlacklistBitSet(ext_prefs);
874 namespace {
876 // Serializes |time| as a string value mapped to |key| in |dictionary|.
877 void SaveTime(base::DictionaryValue* dictionary,
878 const char* key,
879 const base::Time& time) {
880 if (!dictionary)
881 return;
882 std::string string_value = base::Int64ToString(time.ToInternalValue());
883 dictionary->SetString(key, string_value);
886 // The opposite of SaveTime. If |key| is not found, this returns an empty Time
887 // (is_null() will return true).
888 base::Time ReadTime(const base::DictionaryValue* dictionary, const char* key) {
889 if (!dictionary)
890 return base::Time();
891 std::string string_value;
892 int64 value;
893 if (dictionary->GetString(key, &string_value)) {
894 if (base::StringToInt64(string_value, &value)) {
895 return base::Time::FromInternalValue(value);
898 return base::Time();
901 } // namespace
903 base::Time ExtensionPrefs::LastPingDay(const std::string& extension_id) const {
904 DCHECK(Extension::IdIsValid(extension_id));
905 return ReadTime(GetExtensionPref(extension_id), kLastPingDay);
908 void ExtensionPrefs::SetLastPingDay(const std::string& extension_id,
909 const base::Time& time) {
910 DCHECK(Extension::IdIsValid(extension_id));
911 ScopedExtensionPrefUpdate update(prefs_, extension_id);
912 SaveTime(update.Get(), kLastPingDay, time);
915 base::Time ExtensionPrefs::BlacklistLastPingDay() const {
916 return ReadTime(prefs_->GetDictionary(kExtensionsBlacklistUpdate),
917 kLastPingDay);
920 void ExtensionPrefs::SetBlacklistLastPingDay(const base::Time& time) {
921 DictionaryPrefUpdate update(prefs_, kExtensionsBlacklistUpdate);
922 SaveTime(update.Get(), kLastPingDay, time);
925 base::Time ExtensionPrefs::LastActivePingDay(const std::string& extension_id) {
926 DCHECK(Extension::IdIsValid(extension_id));
927 return ReadTime(GetExtensionPref(extension_id), kLastActivePingDay);
930 void ExtensionPrefs::SetLastActivePingDay(const std::string& extension_id,
931 const base::Time& time) {
932 DCHECK(Extension::IdIsValid(extension_id));
933 ScopedExtensionPrefUpdate update(prefs_, extension_id);
934 SaveTime(update.Get(), kLastActivePingDay, time);
937 bool ExtensionPrefs::GetActiveBit(const std::string& extension_id) {
938 const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
939 bool result = false;
940 if (dictionary && dictionary->GetBoolean(kActiveBit, &result))
941 return result;
942 return false;
945 void ExtensionPrefs::SetActiveBit(const std::string& extension_id,
946 bool active) {
947 UpdateExtensionPref(extension_id, kActiveBit,
948 new base::FundamentalValue(active));
951 void ExtensionPrefs::MigratePermissions(const ExtensionIdList& extension_ids) {
952 PermissionsInfo* info = PermissionsInfo::GetInstance();
953 for (ExtensionIdList::const_iterator ext_id =
954 extension_ids.begin(); ext_id != extension_ids.end(); ++ext_id) {
955 // An extension's granted permissions need to be migrated if the
956 // full_access bit is present. This bit was always present in the previous
957 // scheme and is never present now.
958 bool full_access;
959 const base::DictionaryValue* ext = GetExtensionPref(*ext_id);
960 if (!ext || !ext->GetBoolean(kPrefOldGrantedFullAccess, &full_access))
961 continue;
963 // Remove the full access bit (empty list will get trimmed).
964 UpdateExtensionPref(
965 *ext_id, kPrefOldGrantedFullAccess, new base::ListValue());
967 // Add the plugin permission if the full access bit was set.
968 if (full_access) {
969 const base::ListValue* apis = NULL;
970 base::ListValue* new_apis = NULL;
972 std::string granted_apis = JoinPrefs(kPrefGrantedPermissions, kPrefAPIs);
973 if (ext->GetList(kPrefOldGrantedAPIs, &apis))
974 new_apis = apis->DeepCopy();
975 else
976 new_apis = new base::ListValue();
978 std::string plugin_name = info->GetByID(APIPermission::kPlugin)->name();
979 new_apis->Append(new base::StringValue(plugin_name));
980 UpdateExtensionPref(*ext_id, granted_apis, new_apis);
983 // The granted permissions originally only held the effective hosts,
984 // which are a combination of host and user script host permissions.
985 // We now maintain these lists separately. For migration purposes, it
986 // does not matter how we treat the old effective hosts as long as the
987 // new effective hosts will be the same, so we move them to explicit
988 // host permissions.
989 const base::ListValue* hosts = NULL;
990 std::string explicit_hosts =
991 JoinPrefs(kPrefGrantedPermissions, kPrefExplicitHosts);
992 if (ext->GetList(kPrefOldGrantedHosts, &hosts)) {
993 UpdateExtensionPref(
994 *ext_id, explicit_hosts, hosts->DeepCopy());
996 // We can get rid of the old one by setting it to an empty list.
997 UpdateExtensionPref(*ext_id, kPrefOldGrantedHosts, new base::ListValue());
1002 void ExtensionPrefs::MigrateDisableReasons(
1003 const ExtensionIdList& extension_ids) {
1004 for (ExtensionIdList::const_iterator ext_id =
1005 extension_ids.begin(); ext_id != extension_ids.end(); ++ext_id) {
1006 int value = -1;
1007 if (ReadPrefAsInteger(*ext_id, kDeprecatedPrefDisableReason, &value)) {
1008 int new_value = Extension::DISABLE_NONE;
1009 switch (value) {
1010 case Extension::DEPRECATED_DISABLE_USER_ACTION:
1011 new_value = Extension::DISABLE_USER_ACTION;
1012 break;
1013 case Extension::DEPRECATED_DISABLE_PERMISSIONS_INCREASE:
1014 new_value = Extension::DISABLE_PERMISSIONS_INCREASE;
1015 break;
1016 case Extension::DEPRECATED_DISABLE_RELOAD:
1017 new_value = Extension::DISABLE_RELOAD;
1018 break;
1021 UpdateExtensionPref(*ext_id, kPrefDisableReasons,
1022 new base::FundamentalValue(new_value));
1023 // Remove the old disable reason.
1024 UpdateExtensionPref(*ext_id, kDeprecatedPrefDisableReason, NULL);
1029 PermissionSet* ExtensionPrefs::GetGrantedPermissions(
1030 const std::string& extension_id) {
1031 CHECK(Extension::IdIsValid(extension_id));
1032 return ReadPrefAsPermissionSet(extension_id, kPrefGrantedPermissions);
1035 void ExtensionPrefs::AddGrantedPermissions(
1036 const std::string& extension_id,
1037 const PermissionSet* permissions) {
1038 CHECK(Extension::IdIsValid(extension_id));
1040 scoped_refptr<PermissionSet> granted_permissions(
1041 GetGrantedPermissions(extension_id));
1043 // The new granted permissions are the union of the already granted
1044 // permissions and the newly granted permissions.
1045 scoped_refptr<PermissionSet> new_perms(
1046 PermissionSet::CreateUnion(
1047 permissions, granted_permissions.get()));
1049 SetExtensionPrefPermissionSet(
1050 extension_id, kPrefGrantedPermissions, new_perms.get());
1053 void ExtensionPrefs::RemoveGrantedPermissions(
1054 const std::string& extension_id,
1055 const PermissionSet* permissions) {
1056 CHECK(Extension::IdIsValid(extension_id));
1058 scoped_refptr<PermissionSet> granted_permissions(
1059 GetGrantedPermissions(extension_id));
1061 // The new granted permissions are the difference of the already granted
1062 // permissions and the newly ungranted permissions.
1063 scoped_refptr<PermissionSet> new_perms(
1064 PermissionSet::CreateDifference(
1065 granted_permissions.get(), permissions));
1067 SetExtensionPrefPermissionSet(
1068 extension_id, kPrefGrantedPermissions, new_perms.get());
1071 PermissionSet* ExtensionPrefs::GetActivePermissions(
1072 const std::string& extension_id) {
1073 CHECK(Extension::IdIsValid(extension_id));
1074 return ReadPrefAsPermissionSet(extension_id, kPrefActivePermissions);
1077 void ExtensionPrefs::SetActivePermissions(
1078 const std::string& extension_id,
1079 const PermissionSet* permissions) {
1080 SetExtensionPrefPermissionSet(
1081 extension_id, kPrefActivePermissions, permissions);
1084 void ExtensionPrefs::SetExtensionRunning(const std::string& extension_id,
1085 bool is_running) {
1086 base::Value* value = new base::FundamentalValue(is_running);
1087 UpdateExtensionPref(extension_id, kPrefRunning, value);
1090 bool ExtensionPrefs::IsExtensionRunning(const std::string& extension_id) {
1091 const base::DictionaryValue* extension = GetExtensionPref(extension_id);
1092 if (!extension)
1093 return false;
1094 bool running = false;
1095 extension->GetBoolean(kPrefRunning, &running);
1096 return running;
1099 void ExtensionPrefs::SetIsActive(const std::string& extension_id,
1100 bool is_active) {
1101 base::Value* value = new base::FundamentalValue(is_active);
1102 UpdateExtensionPref(extension_id, kIsActive, value);
1105 bool ExtensionPrefs::IsActive(const std::string& extension_id) {
1106 const base::DictionaryValue* extension = GetExtensionPref(extension_id);
1107 if (!extension)
1108 return false;
1109 bool is_active = false;
1110 extension->GetBoolean(kIsActive, &is_active);
1111 return is_active;
1114 bool ExtensionPrefs::IsIncognitoEnabled(const std::string& extension_id) const {
1115 return ReadPrefAsBooleanAndReturn(extension_id, kPrefIncognitoEnabled);
1118 void ExtensionPrefs::SetIsIncognitoEnabled(const std::string& extension_id,
1119 bool enabled) {
1120 UpdateExtensionPref(extension_id, kPrefIncognitoEnabled,
1121 new base::FundamentalValue(enabled));
1122 extension_pref_value_map_->SetExtensionIncognitoState(extension_id, enabled);
1125 bool ExtensionPrefs::AllowFileAccess(const std::string& extension_id) const {
1126 return ReadPrefAsBooleanAndReturn(extension_id, kPrefAllowFileAccess);
1129 void ExtensionPrefs::SetAllowFileAccess(const std::string& extension_id,
1130 bool allow) {
1131 UpdateExtensionPref(extension_id, kPrefAllowFileAccess,
1132 new base::FundamentalValue(allow));
1135 bool ExtensionPrefs::HasAllowFileAccessSetting(
1136 const std::string& extension_id) const {
1137 const base::DictionaryValue* ext = GetExtensionPref(extension_id);
1138 return ext && ext->HasKey(kPrefAllowFileAccess);
1141 bool ExtensionPrefs::DoesExtensionHaveState(
1142 const std::string& id, Extension::State check_state) const {
1143 const base::DictionaryValue* extension = GetExtensionPref(id);
1144 int state = -1;
1145 if (!extension || !extension->GetInteger(kPrefState, &state))
1146 return false;
1148 if (state < 0 || state >= Extension::NUM_STATES) {
1149 LOG(ERROR) << "Bad pref 'state' for extension '" << id << "'";
1150 return false;
1153 return state == check_state;
1156 bool ExtensionPrefs::IsExternalExtensionUninstalled(
1157 const std::string& id) const {
1158 return DoesExtensionHaveState(id, Extension::EXTERNAL_EXTENSION_UNINSTALLED);
1161 bool ExtensionPrefs::IsExtensionDisabled(
1162 const std::string& id) const {
1163 return DoesExtensionHaveState(id, Extension::DISABLED);
1166 ExtensionIdList ExtensionPrefs::GetToolbarOrder() {
1167 ExtensionIdList id_list_out;
1168 GetUserExtensionPrefIntoContainer(pref_names::kToolbar, &id_list_out);
1169 return id_list_out;
1172 void ExtensionPrefs::SetToolbarOrder(const ExtensionIdList& extension_ids) {
1173 SetExtensionPrefFromContainer(pref_names::kToolbar, extension_ids);
1176 bool ExtensionPrefs::GetKnownDisabled(ExtensionIdSet* id_set_out) {
1177 return GetUserExtensionPrefIntoContainer(pref_names::kKnownDisabled,
1178 id_set_out);
1181 void ExtensionPrefs::SetKnownDisabled(const ExtensionIdSet& extension_ids) {
1182 SetExtensionPrefFromContainer(pref_names::kKnownDisabled, extension_ids);
1185 void ExtensionPrefs::OnExtensionInstalled(
1186 const Extension* extension,
1187 Extension::State initial_state,
1188 bool blacklisted_for_malware,
1189 const syncer::StringOrdinal& page_ordinal,
1190 const std::string& install_parameter) {
1191 ScopedExtensionPrefUpdate update(prefs_, extension->id());
1192 base::DictionaryValue* extension_dict = update.Get();
1193 const base::Time install_time = time_provider_->GetCurrentTime();
1194 PopulateExtensionInfoPrefs(extension,
1195 install_time,
1196 initial_state,
1197 blacklisted_for_malware,
1198 install_parameter,
1199 extension_dict);
1200 FinishExtensionInfoPrefs(extension->id(), install_time,
1201 extension->RequiresSortOrdinal(),
1202 page_ordinal, extension_dict);
1205 void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id,
1206 const Manifest::Location& location,
1207 bool external_uninstall) {
1208 app_sorting_->ClearOrdinals(extension_id);
1210 // For external extensions, we save a preference reminding ourself not to try
1211 // and install the extension anymore (except when |external_uninstall| is
1212 // true, which signifies that the registry key was deleted or the pref file
1213 // no longer lists the extension).
1214 if (!external_uninstall && Manifest::IsExternalLocation(location)) {
1215 UpdateExtensionPref(extension_id, kPrefState,
1216 new base::FundamentalValue(
1217 Extension::EXTERNAL_EXTENSION_UNINSTALLED));
1218 extension_pref_value_map_->SetExtensionState(extension_id, false);
1219 FOR_EACH_OBSERVER(ExtensionPrefsObserver,
1220 observer_list_,
1221 OnExtensionStateChanged(extension_id, false));
1222 } else {
1223 int creation_flags = GetCreationFlags(extension_id);
1224 if (creation_flags & Extension::IS_EPHEMERAL) {
1225 // Keep ephemeral apps around, but mark them as evicted.
1226 UpdateExtensionPref(extension_id, kPrefEvictedEphemeralApp,
1227 new base::FundamentalValue(true));
1228 } else {
1229 DeleteExtensionPrefs(extension_id);
1234 void ExtensionPrefs::SetExtensionState(const std::string& extension_id,
1235 Extension::State state) {
1236 UpdateExtensionPref(extension_id, kPrefState,
1237 new base::FundamentalValue(state));
1238 bool enabled = (state == Extension::ENABLED);
1239 extension_pref_value_map_->SetExtensionState(extension_id, enabled);
1240 FOR_EACH_OBSERVER(ExtensionPrefsObserver,
1241 observer_list_,
1242 OnExtensionStateChanged(extension_id, enabled));
1245 void ExtensionPrefs::SetExtensionBlacklistState(const std::string& extension_id,
1246 BlacklistState state) {
1247 SetExtensionBlacklisted(extension_id, state == BLACKLISTED_MALWARE);
1248 UpdateExtensionPref(extension_id, kPrefBlacklistState,
1249 new base::FundamentalValue(state));
1252 BlacklistState ExtensionPrefs::GetExtensionBlacklistState(
1253 const std::string& extension_id) {
1254 if (IsExtensionBlacklisted(extension_id))
1255 return BLACKLISTED_MALWARE;
1256 const base::DictionaryValue* ext_prefs = GetExtensionPref(extension_id);
1257 int int_value;
1258 if (ext_prefs && ext_prefs->GetInteger(kPrefBlacklistState, &int_value))
1259 return static_cast<BlacklistState>(int_value);
1261 return NOT_BLACKLISTED;
1264 std::string ExtensionPrefs::GetVersionString(const std::string& extension_id) {
1265 const base::DictionaryValue* extension = GetExtensionPref(extension_id);
1266 if (!extension)
1267 return std::string();
1269 std::string version;
1270 extension->GetString(kPrefVersion, &version);
1272 return version;
1275 void ExtensionPrefs::UpdateManifest(const Extension* extension) {
1276 if (!Manifest::IsUnpackedLocation(extension->location())) {
1277 const base::DictionaryValue* extension_dict =
1278 GetExtensionPref(extension->id());
1279 if (!extension_dict)
1280 return;
1281 const base::DictionaryValue* old_manifest = NULL;
1282 bool update_required =
1283 !extension_dict->GetDictionary(kPrefManifest, &old_manifest) ||
1284 !extension->manifest()->value()->Equals(old_manifest);
1285 if (update_required) {
1286 UpdateExtensionPref(extension->id(), kPrefManifest,
1287 extension->manifest()->value()->DeepCopy());
1292 base::FilePath ExtensionPrefs::GetExtensionPath(
1293 const std::string& extension_id) {
1294 const base::DictionaryValue* dict = GetExtensionPref(extension_id);
1295 if (!dict)
1296 return base::FilePath();
1298 std::string path;
1299 if (!dict->GetString(kPrefPath, &path))
1300 return base::FilePath();
1302 return install_directory_.Append(base::FilePath::FromUTF8Unsafe(path));
1305 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetInstalledInfoHelper(
1306 const std::string& extension_id,
1307 const base::DictionaryValue* extension) const {
1308 int location_value;
1309 if (!extension->GetInteger(kPrefLocation, &location_value))
1310 return scoped_ptr<ExtensionInfo>();
1312 base::FilePath::StringType path;
1313 if (!extension->GetString(kPrefPath, &path))
1314 return scoped_ptr<ExtensionInfo>();
1316 // Make path absolute. Unpacked extensions will already have absolute paths,
1317 // otherwise make it so.
1318 Manifest::Location location = static_cast<Manifest::Location>(location_value);
1319 if (!Manifest::IsUnpackedLocation(location)) {
1320 DCHECK(location == Manifest::COMPONENT ||
1321 !base::FilePath(path).IsAbsolute());
1322 path = install_directory_.Append(path).value();
1325 // Only the following extension types have data saved in the preferences.
1326 if (location != Manifest::INTERNAL &&
1327 !Manifest::IsUnpackedLocation(location) &&
1328 !Manifest::IsExternalLocation(location)) {
1329 NOTREACHED();
1330 return scoped_ptr<ExtensionInfo>();
1333 const base::DictionaryValue* manifest = NULL;
1334 if (!Manifest::IsUnpackedLocation(location) &&
1335 !extension->GetDictionary(kPrefManifest, &manifest)) {
1336 LOG(WARNING) << "Missing manifest for extension " << extension_id;
1337 // Just a warning for now.
1340 return scoped_ptr<ExtensionInfo>(new ExtensionInfo(
1341 manifest, extension_id, base::FilePath(path), location));
1344 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetInstalledExtensionInfo(
1345 const std::string& extension_id) const {
1346 const base::DictionaryValue* ext = NULL;
1347 const base::DictionaryValue* extensions =
1348 prefs_->GetDictionary(pref_names::kExtensions);
1349 if (!extensions ||
1350 !extensions->GetDictionaryWithoutPathExpansion(extension_id, &ext))
1351 return scoped_ptr<ExtensionInfo>();
1352 int state_value;
1353 if (!ext->GetInteger(kPrefState, &state_value) ||
1354 state_value == Extension::ENABLED_COMPONENT) {
1355 // Old preferences files may not have kPrefState for component extensions.
1356 return scoped_ptr<ExtensionInfo>();
1359 if (state_value == Extension::EXTERNAL_EXTENSION_UNINSTALLED) {
1360 LOG(WARNING) << "External extension with id " << extension_id
1361 << " has been uninstalled by the user";
1362 return scoped_ptr<ExtensionInfo>();
1365 if (IsEvictedEphemeralApp(ext)) {
1366 // Hide evicted ephemeral apps.
1367 return scoped_ptr<ExtensionInfo>();
1370 return GetInstalledInfoHelper(extension_id, ext);
1373 scoped_ptr<ExtensionPrefs::ExtensionsInfo>
1374 ExtensionPrefs::GetInstalledExtensionsInfo() const {
1375 scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
1377 const base::DictionaryValue* extensions =
1378 prefs_->GetDictionary(pref_names::kExtensions);
1379 for (base::DictionaryValue::Iterator extension_id(*extensions);
1380 !extension_id.IsAtEnd(); extension_id.Advance()) {
1381 if (!Extension::IdIsValid(extension_id.key()))
1382 continue;
1384 scoped_ptr<ExtensionInfo> info =
1385 GetInstalledExtensionInfo(extension_id.key());
1386 if (info)
1387 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
1390 return extensions_info.Pass();
1393 scoped_ptr<ExtensionPrefs::ExtensionsInfo>
1394 ExtensionPrefs::GetUninstalledExtensionsInfo() const {
1395 scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
1397 const base::DictionaryValue* extensions =
1398 prefs_->GetDictionary(pref_names::kExtensions);
1399 for (base::DictionaryValue::Iterator extension_id(*extensions);
1400 !extension_id.IsAtEnd(); extension_id.Advance()) {
1401 const base::DictionaryValue* ext = NULL;
1402 if (!Extension::IdIsValid(extension_id.key()) ||
1403 !IsExternalExtensionUninstalled(extension_id.key()) ||
1404 !extension_id.value().GetAsDictionary(&ext))
1405 continue;
1407 scoped_ptr<ExtensionInfo> info =
1408 GetInstalledInfoHelper(extension_id.key(), ext);
1409 if (info)
1410 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
1413 return extensions_info.Pass();
1416 void ExtensionPrefs::SetDelayedInstallInfo(
1417 const Extension* extension,
1418 Extension::State initial_state,
1419 bool blacklisted_for_malware,
1420 DelayReason delay_reason,
1421 const syncer::StringOrdinal& page_ordinal,
1422 const std::string& install_parameter) {
1423 base::DictionaryValue* extension_dict = new base::DictionaryValue();
1424 PopulateExtensionInfoPrefs(extension,
1425 time_provider_->GetCurrentTime(),
1426 initial_state,
1427 blacklisted_for_malware,
1428 install_parameter,
1429 extension_dict);
1431 // Add transient data that is needed by FinishDelayedInstallInfo(), but
1432 // should not be in the final extension prefs. All entries here should have
1433 // a corresponding Remove() call in FinishDelayedInstallInfo().
1434 if (extension->RequiresSortOrdinal()) {
1435 extension_dict->SetString(
1436 kPrefSuggestedPageOrdinal,
1437 page_ordinal.IsValid() ? page_ordinal.ToInternalValue()
1438 : std::string());
1440 extension_dict->SetInteger(kDelayedInstallReason,
1441 static_cast<int>(delay_reason));
1443 UpdateExtensionPref(extension->id(), kDelayedInstallInfo, extension_dict);
1446 bool ExtensionPrefs::RemoveDelayedInstallInfo(
1447 const std::string& extension_id) {
1448 if (!GetExtensionPref(extension_id))
1449 return false;
1450 ScopedExtensionPrefUpdate update(prefs_, extension_id);
1451 bool result = update->Remove(kDelayedInstallInfo, NULL);
1452 return result;
1455 bool ExtensionPrefs::FinishDelayedInstallInfo(
1456 const std::string& extension_id) {
1457 CHECK(Extension::IdIsValid(extension_id));
1458 ScopedExtensionPrefUpdate update(prefs_, extension_id);
1459 base::DictionaryValue* extension_dict = update.Get();
1460 base::DictionaryValue* pending_install_dict = NULL;
1461 if (!extension_dict->GetDictionary(kDelayedInstallInfo,
1462 &pending_install_dict)) {
1463 return false;
1466 // Retrieve and clear transient values populated by SetDelayedInstallInfo().
1467 // Also do any other data cleanup that makes sense.
1468 std::string serialized_ordinal;
1469 syncer::StringOrdinal suggested_page_ordinal;
1470 bool needs_sort_ordinal = false;
1471 if (pending_install_dict->GetString(kPrefSuggestedPageOrdinal,
1472 &serialized_ordinal)) {
1473 suggested_page_ordinal = syncer::StringOrdinal(serialized_ordinal);
1474 needs_sort_ordinal = true;
1475 pending_install_dict->Remove(kPrefSuggestedPageOrdinal, NULL);
1477 pending_install_dict->Remove(kDelayedInstallReason, NULL);
1479 const base::Time install_time = time_provider_->GetCurrentTime();
1480 pending_install_dict->Set(
1481 kPrefInstallTime,
1482 new base::StringValue(
1483 base::Int64ToString(install_time.ToInternalValue())));
1485 // Commit the delayed install data.
1486 for (base::DictionaryValue::Iterator it(*pending_install_dict); !it.IsAtEnd();
1487 it.Advance()) {
1488 extension_dict->Set(it.key(), it.value().DeepCopy());
1490 FinishExtensionInfoPrefs(extension_id, install_time, needs_sort_ordinal,
1491 suggested_page_ordinal, extension_dict);
1492 return true;
1495 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetDelayedInstallInfo(
1496 const std::string& extension_id) const {
1497 const base::DictionaryValue* extension_prefs =
1498 GetExtensionPref(extension_id);
1499 if (!extension_prefs)
1500 return scoped_ptr<ExtensionInfo>();
1502 const base::DictionaryValue* ext = NULL;
1503 if (!extension_prefs->GetDictionary(kDelayedInstallInfo, &ext))
1504 return scoped_ptr<ExtensionInfo>();
1506 return GetInstalledInfoHelper(extension_id, ext);
1509 ExtensionPrefs::DelayReason ExtensionPrefs::GetDelayedInstallReason(
1510 const std::string& extension_id) const {
1511 const base::DictionaryValue* extension_prefs =
1512 GetExtensionPref(extension_id);
1513 if (!extension_prefs)
1514 return DELAY_REASON_NONE;
1516 const base::DictionaryValue* ext = NULL;
1517 if (!extension_prefs->GetDictionary(kDelayedInstallInfo, &ext))
1518 return DELAY_REASON_NONE;
1520 int delay_reason;
1521 if (!ext->GetInteger(kDelayedInstallReason, &delay_reason))
1522 return DELAY_REASON_NONE;
1524 return static_cast<DelayReason>(delay_reason);
1527 scoped_ptr<ExtensionPrefs::ExtensionsInfo> ExtensionPrefs::
1528 GetAllDelayedInstallInfo() const {
1529 scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
1531 const base::DictionaryValue* extensions =
1532 prefs_->GetDictionary(pref_names::kExtensions);
1533 for (base::DictionaryValue::Iterator extension_id(*extensions);
1534 !extension_id.IsAtEnd(); extension_id.Advance()) {
1535 if (!Extension::IdIsValid(extension_id.key()))
1536 continue;
1538 scoped_ptr<ExtensionInfo> info = GetDelayedInstallInfo(extension_id.key());
1539 if (info)
1540 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
1543 return extensions_info.Pass();
1546 scoped_ptr<ExtensionPrefs::ExtensionsInfo>
1547 ExtensionPrefs::GetEvictedEphemeralAppsInfo() const {
1548 scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
1550 const base::DictionaryValue* extensions =
1551 prefs_->GetDictionary(pref_names::kExtensions);
1552 for (base::DictionaryValue::Iterator extension_id(*extensions);
1553 !extension_id.IsAtEnd(); extension_id.Advance()) {
1554 const base::DictionaryValue* ext = NULL;
1555 if (!Extension::IdIsValid(extension_id.key()) ||
1556 !extension_id.value().GetAsDictionary(&ext)) {
1557 continue;
1560 if (!IsEvictedEphemeralApp(ext))
1561 continue;
1563 scoped_ptr<ExtensionInfo> info =
1564 GetInstalledInfoHelper(extension_id.key(), ext);
1565 if (info)
1566 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
1569 return extensions_info.Pass();
1572 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetEvictedEphemeralAppInfo(
1573 const std::string& extension_id) const {
1574 const base::DictionaryValue* extension_prefs = GetExtensionPref(extension_id);
1575 if (!extension_prefs)
1576 return scoped_ptr<ExtensionInfo>();
1578 if (!IsEvictedEphemeralApp(extension_prefs))
1579 return scoped_ptr<ExtensionInfo>();
1581 return GetInstalledInfoHelper(extension_id, extension_prefs);
1584 void ExtensionPrefs::RemoveEvictedEphemeralApp(
1585 const std::string& extension_id) {
1586 bool evicted_ephemeral_app = false;
1587 if (ReadPrefAsBoolean(extension_id,
1588 kPrefEvictedEphemeralApp,
1589 &evicted_ephemeral_app) && evicted_ephemeral_app) {
1590 DeleteExtensionPrefs(extension_id);
1594 bool ExtensionPrefs::WasAppDraggedByUser(const std::string& extension_id) {
1595 return ReadPrefAsBooleanAndReturn(extension_id, kPrefUserDraggedApp);
1598 void ExtensionPrefs::SetAppDraggedByUser(const std::string& extension_id) {
1599 UpdateExtensionPref(extension_id, kPrefUserDraggedApp,
1600 new base::FundamentalValue(true));
1603 bool ExtensionPrefs::IsFromWebStore(
1604 const std::string& extension_id) const {
1605 const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
1606 bool result = false;
1607 if (dictionary && dictionary->GetBoolean(kPrefFromWebStore, &result))
1608 return result;
1609 return false;
1612 bool ExtensionPrefs::IsFromBookmark(
1613 const std::string& extension_id) const {
1614 const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
1615 bool result = false;
1616 if (dictionary && dictionary->GetBoolean(kPrefFromBookmark, &result))
1617 return result;
1618 return false;
1621 int ExtensionPrefs::GetCreationFlags(const std::string& extension_id) const {
1622 int creation_flags = Extension::NO_FLAGS;
1623 if (!ReadPrefAsInteger(extension_id, kPrefCreationFlags, &creation_flags)) {
1624 // Since kPrefCreationFlags was added later, it will be missing for
1625 // previously installed extensions.
1626 if (IsFromBookmark(extension_id))
1627 creation_flags |= Extension::FROM_BOOKMARK;
1628 if (IsFromWebStore(extension_id))
1629 creation_flags |= Extension::FROM_WEBSTORE;
1630 if (WasInstalledByDefault(extension_id))
1631 creation_flags |= Extension::WAS_INSTALLED_BY_DEFAULT;
1632 if (WasInstalledByOem(extension_id))
1633 creation_flags |= Extension::WAS_INSTALLED_BY_OEM;
1635 return creation_flags;
1638 int ExtensionPrefs::GetDelayedInstallCreationFlags(
1639 const std::string& extension_id) const {
1640 int creation_flags = Extension::NO_FLAGS;
1641 const base::DictionaryValue* delayed_info = NULL;
1642 if (ReadPrefAsDictionary(extension_id, kDelayedInstallInfo, &delayed_info)) {
1643 delayed_info->GetInteger(kPrefCreationFlags, &creation_flags);
1645 return creation_flags;
1648 bool ExtensionPrefs::WasInstalledByDefault(
1649 const std::string& extension_id) const {
1650 const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
1651 bool result = false;
1652 if (dictionary &&
1653 dictionary->GetBoolean(kPrefWasInstalledByDefault, &result))
1654 return result;
1655 return false;
1658 bool ExtensionPrefs::WasInstalledByOem(const std::string& extension_id) const {
1659 const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
1660 bool result = false;
1661 if (dictionary && dictionary->GetBoolean(kPrefWasInstalledByOem, &result))
1662 return result;
1663 return false;
1666 base::Time ExtensionPrefs::GetInstallTime(
1667 const std::string& extension_id) const {
1668 const base::DictionaryValue* extension = GetExtensionPref(extension_id);
1669 if (!extension) {
1670 NOTREACHED();
1671 return base::Time();
1673 std::string install_time_str;
1674 if (!extension->GetString(kPrefInstallTime, &install_time_str))
1675 return base::Time();
1676 int64 install_time_i64 = 0;
1677 if (!base::StringToInt64(install_time_str, &install_time_i64))
1678 return base::Time();
1679 return base::Time::FromInternalValue(install_time_i64);
1682 base::Time ExtensionPrefs::GetLastLaunchTime(
1683 const std::string& extension_id) const {
1684 const base::DictionaryValue* extension = GetExtensionPref(extension_id);
1685 if (!extension)
1686 return base::Time();
1688 std::string launch_time_str;
1689 if (!extension->GetString(kPrefLastLaunchTime, &launch_time_str))
1690 return base::Time();
1691 int64 launch_time_i64 = 0;
1692 if (!base::StringToInt64(launch_time_str, &launch_time_i64))
1693 return base::Time();
1694 return base::Time::FromInternalValue(launch_time_i64);
1697 void ExtensionPrefs::SetLastLaunchTime(const std::string& extension_id,
1698 const base::Time& time) {
1699 DCHECK(Extension::IdIsValid(extension_id));
1700 ScopedExtensionPrefUpdate update(prefs_, extension_id);
1701 SaveTime(update.Get(), kPrefLastLaunchTime, time);
1704 void ExtensionPrefs::GetExtensions(ExtensionIdList* out) {
1705 CHECK(out);
1707 scoped_ptr<ExtensionsInfo> extensions_info(GetInstalledExtensionsInfo());
1709 for (size_t i = 0; i < extensions_info->size(); ++i) {
1710 ExtensionInfo* info = extensions_info->at(i).get();
1711 out->push_back(info->extension_id);
1715 // static
1716 ExtensionIdList ExtensionPrefs::GetExtensionsFrom(
1717 const PrefService* pref_service) {
1718 ExtensionIdList result;
1720 const base::DictionaryValue* extension_prefs = NULL;
1721 const base::Value* extension_prefs_value =
1722 pref_service->GetUserPrefValue(pref_names::kExtensions);
1723 if (!extension_prefs_value ||
1724 !extension_prefs_value->GetAsDictionary(&extension_prefs)) {
1725 return result; // Empty set
1728 for (base::DictionaryValue::Iterator it(*extension_prefs); !it.IsAtEnd();
1729 it.Advance()) {
1730 const base::DictionaryValue* ext = NULL;
1731 if (!it.value().GetAsDictionary(&ext)) {
1732 NOTREACHED() << "Invalid pref for extension " << it.key();
1733 continue;
1735 if (!IsBlacklistBitSet(ext))
1736 result.push_back(it.key());
1738 return result;
1741 void ExtensionPrefs::AddObserver(ExtensionPrefsObserver* observer) {
1742 observer_list_.AddObserver(observer);
1745 void ExtensionPrefs::RemoveObserver(ExtensionPrefsObserver* observer) {
1746 observer_list_.RemoveObserver(observer);
1749 void ExtensionPrefs::FixMissingPrefs(const ExtensionIdList& extension_ids) {
1750 // Fix old entries that did not get an installation time entry when they
1751 // were installed or don't have a preferences field.
1752 for (ExtensionIdList::const_iterator ext_id = extension_ids.begin();
1753 ext_id != extension_ids.end(); ++ext_id) {
1754 if (GetInstallTime(*ext_id) == base::Time()) {
1755 VLOG(1) << "Could not parse installation time of extension "
1756 << *ext_id << ". It was probably installed before setting "
1757 << kPrefInstallTime << " was introduced. Updating "
1758 << kPrefInstallTime << " to the current time.";
1759 const base::Time install_time = time_provider_->GetCurrentTime();
1760 UpdateExtensionPref(*ext_id,
1761 kPrefInstallTime,
1762 new base::StringValue(base::Int64ToString(
1763 install_time.ToInternalValue())));
1768 void ExtensionPrefs::InitPrefStore() {
1769 if (extensions_disabled_) {
1770 extension_pref_value_map_->NotifyInitializationCompleted();
1771 return;
1774 // When this is called, the PrefService is initialized and provides access
1775 // to the user preferences stored in a JSON file.
1776 ExtensionIdList extension_ids;
1777 GetExtensions(&extension_ids);
1778 // Create empty preferences dictionary for each extension (these dictionaries
1779 // are pruned when persisting the preferences to disk).
1780 for (ExtensionIdList::iterator ext_id = extension_ids.begin();
1781 ext_id != extension_ids.end(); ++ext_id) {
1782 ScopedExtensionPrefUpdate update(prefs_, *ext_id);
1783 // This creates an empty dictionary if none is stored.
1784 update.Get();
1787 FixMissingPrefs(extension_ids);
1788 MigratePermissions(extension_ids);
1789 MigrateDisableReasons(extension_ids);
1790 app_sorting_->Initialize(extension_ids);
1792 InitExtensionControlledPrefs(extension_pref_value_map_);
1794 extension_pref_value_map_->NotifyInitializationCompleted();
1797 bool ExtensionPrefs::HasIncognitoPrefValue(const std::string& pref_key) {
1798 bool has_incognito_pref_value = false;
1799 extension_pref_value_map_->GetEffectivePrefValue(pref_key,
1800 true,
1801 &has_incognito_pref_value);
1802 return has_incognito_pref_value;
1805 URLPatternSet ExtensionPrefs::GetAllowedInstallSites() {
1806 URLPatternSet result;
1807 const base::ListValue* list =
1808 prefs_->GetList(pref_names::kAllowedInstallSites);
1809 CHECK(list);
1811 for (size_t i = 0; i < list->GetSize(); ++i) {
1812 std::string entry_string;
1813 URLPattern entry(URLPattern::SCHEME_ALL);
1814 if (!list->GetString(i, &entry_string) ||
1815 entry.Parse(entry_string) != URLPattern::PARSE_SUCCESS) {
1816 LOG(ERROR) << "Invalid value for preference: "
1817 << pref_names::kAllowedInstallSites << "." << i;
1818 continue;
1820 result.AddPattern(entry);
1823 return result;
1826 const base::DictionaryValue* ExtensionPrefs::GetGeometryCache(
1827 const std::string& extension_id) const {
1828 const base::DictionaryValue* extension_prefs = GetExtensionPref(extension_id);
1829 if (!extension_prefs)
1830 return NULL;
1832 const base::DictionaryValue* ext = NULL;
1833 if (!extension_prefs->GetDictionary(kPrefGeometryCache, &ext))
1834 return NULL;
1836 return ext;
1839 void ExtensionPrefs::SetGeometryCache(
1840 const std::string& extension_id,
1841 scoped_ptr<base::DictionaryValue> cache) {
1842 UpdateExtensionPref(extension_id, kPrefGeometryCache, cache.release());
1845 const base::DictionaryValue* ExtensionPrefs::GetInstallSignature() {
1846 return prefs_->GetDictionary(kInstallSignature);
1849 void ExtensionPrefs::SetInstallSignature(
1850 const base::DictionaryValue* signature) {
1851 if (signature) {
1852 prefs_->Set(kInstallSignature, *signature);
1853 DVLOG(1) << "SetInstallSignature - saving";
1854 } else {
1855 DVLOG(1) << "SetInstallSignature - clearing";
1856 prefs_->ClearPref(kInstallSignature);
1860 std::string ExtensionPrefs::GetInstallParam(
1861 const std::string& extension_id) const {
1862 const base::DictionaryValue* extension = GetExtensionPref(extension_id);
1863 if (!extension) // Expected during unit testing.
1864 return std::string();
1865 std::string install_parameter;
1866 if (!extension->GetString(kPrefInstallParam, &install_parameter))
1867 return std::string();
1868 return install_parameter;
1871 void ExtensionPrefs::SetInstallParam(const std::string& extension_id,
1872 const std::string& install_parameter) {
1873 UpdateExtensionPref(extension_id,
1874 kPrefInstallParam,
1875 new base::StringValue(install_parameter));
1878 ExtensionPrefs::ExtensionPrefs(
1879 PrefService* prefs,
1880 const base::FilePath& root_dir,
1881 ExtensionPrefValueMap* extension_pref_value_map,
1882 scoped_ptr<AppSorting> app_sorting,
1883 scoped_ptr<TimeProvider> time_provider,
1884 bool extensions_disabled,
1885 const std::vector<ExtensionPrefsObserver*>& early_observers)
1886 : prefs_(prefs),
1887 install_directory_(root_dir),
1888 extension_pref_value_map_(extension_pref_value_map),
1889 app_sorting_(app_sorting.Pass()),
1890 time_provider_(time_provider.Pass()),
1891 extensions_disabled_(extensions_disabled) {
1892 app_sorting_->SetExtensionScopedPrefs(this);
1893 MakePathsRelative();
1895 // Ensure that any early observers are watching before prefs are initialized.
1896 for (std::vector<ExtensionPrefsObserver*>::const_iterator iter =
1897 early_observers.begin();
1898 iter != early_observers.end();
1899 ++iter) {
1900 AddObserver(*iter);
1903 InitPrefStore();
1906 void ExtensionPrefs::SetNeedsStorageGarbageCollection(bool value) {
1907 prefs_->SetBoolean(pref_names::kStorageGarbageCollect, value);
1910 bool ExtensionPrefs::NeedsStorageGarbageCollection() {
1911 return prefs_->GetBoolean(pref_names::kStorageGarbageCollect);
1914 // static
1915 void ExtensionPrefs::RegisterProfilePrefs(
1916 user_prefs::PrefRegistrySyncable* registry) {
1917 registry->RegisterDictionaryPref(
1918 pref_names::kExtensions,
1919 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1920 registry->RegisterListPref(pref_names::kToolbar,
1921 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
1922 registry->RegisterIntegerPref(
1923 pref_names::kToolbarSize,
1924 -1, // default value
1925 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1926 registry->RegisterDictionaryPref(
1927 kExtensionsBlacklistUpdate,
1928 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1929 registry->RegisterListPref(pref_names::kInstallAllowList,
1930 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1931 registry->RegisterListPref(pref_names::kInstallDenyList,
1932 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1933 registry->RegisterDictionaryPref(
1934 pref_names::kInstallForceList,
1935 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1936 registry->RegisterListPref(pref_names::kAllowedTypes,
1937 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1938 registry->RegisterBooleanPref(
1939 pref_names::kStorageGarbageCollect,
1940 false, // default value
1941 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1942 registry->RegisterInt64Pref(
1943 pref_names::kLastUpdateCheck,
1944 0, // default value
1945 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1946 registry->RegisterInt64Pref(
1947 pref_names::kNextUpdateCheck,
1948 0, // default value
1949 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1950 registry->RegisterListPref(pref_names::kAllowedInstallSites,
1951 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1952 registry->RegisterStringPref(
1953 pref_names::kLastChromeVersion,
1954 std::string(), // default value
1955 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1956 registry->RegisterListPref(pref_names::kKnownDisabled,
1957 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1958 #if defined(TOOLKIT_VIEWS)
1959 registry->RegisterIntegerPref(
1960 pref_names::kBrowserActionContainerWidth,
1962 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1963 #endif
1964 registry->RegisterDictionaryPref(
1965 kInstallSignature,
1966 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1968 registry->RegisterListPref(pref_names::kNativeMessagingBlacklist,
1969 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1970 registry->RegisterListPref(pref_names::kNativeMessagingWhitelist,
1971 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1972 registry->RegisterBooleanPref(
1973 pref_names::kNativeMessagingUserLevelHosts,
1974 true, // default value
1975 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1978 template <class ExtensionIdContainer>
1979 bool ExtensionPrefs::GetUserExtensionPrefIntoContainer(
1980 const char* pref,
1981 ExtensionIdContainer* id_container_out) {
1982 DCHECK(id_container_out->empty());
1984 const base::Value* user_pref_value = prefs_->GetUserPrefValue(pref);
1985 const base::ListValue* user_pref_as_list;
1986 if (!user_pref_value || !user_pref_value->GetAsList(&user_pref_as_list))
1987 return false;
1989 std::insert_iterator<ExtensionIdContainer> insert_iterator(
1990 *id_container_out, id_container_out->end());
1991 std::string extension_id;
1992 for (base::ListValue::const_iterator value_it = user_pref_as_list->begin();
1993 value_it != user_pref_as_list->end(); ++value_it) {
1994 if (!(*value_it)->GetAsString(&extension_id)) {
1995 NOTREACHED();
1996 continue;
1998 insert_iterator = extension_id;
2000 return true;
2003 template <class ExtensionIdContainer>
2004 void ExtensionPrefs::SetExtensionPrefFromContainer(
2005 const char* pref,
2006 const ExtensionIdContainer& strings) {
2007 ListPrefUpdate update(prefs_, pref);
2008 base::ListValue* list_of_values = update.Get();
2009 list_of_values->Clear();
2010 for (typename ExtensionIdContainer::const_iterator iter = strings.begin();
2011 iter != strings.end(); ++iter) {
2012 list_of_values->Append(new base::StringValue(*iter));
2016 void ExtensionPrefs::PopulateExtensionInfoPrefs(
2017 const Extension* extension,
2018 const base::Time install_time,
2019 Extension::State initial_state,
2020 bool blacklisted_for_malware,
2021 const std::string& install_parameter,
2022 base::DictionaryValue* extension_dict) {
2023 // Leave the state blank for component extensions so that old chrome versions
2024 // loading new profiles do not fail in GetInstalledExtensionInfo. Older
2025 // Chrome versions would only check for an omitted state.
2026 if (initial_state != Extension::ENABLED_COMPONENT)
2027 extension_dict->Set(kPrefState, new base::FundamentalValue(initial_state));
2029 extension_dict->Set(kPrefLocation,
2030 new base::FundamentalValue(extension->location()));
2031 extension_dict->Set(kPrefCreationFlags,
2032 new base::FundamentalValue(extension->creation_flags()));
2033 extension_dict->Set(kPrefFromWebStore,
2034 new base::FundamentalValue(extension->from_webstore()));
2035 extension_dict->Set(kPrefFromBookmark,
2036 new base::FundamentalValue(extension->from_bookmark()));
2037 extension_dict->Set(
2038 kPrefWasInstalledByDefault,
2039 new base::FundamentalValue(extension->was_installed_by_default()));
2040 extension_dict->Set(
2041 kPrefWasInstalledByOem,
2042 new base::FundamentalValue(extension->was_installed_by_oem()));
2043 extension_dict->Set(kPrefInstallTime,
2044 new base::StringValue(
2045 base::Int64ToString(install_time.ToInternalValue())));
2046 if (blacklisted_for_malware)
2047 extension_dict->Set(kPrefBlacklist, new base::FundamentalValue(true));
2049 base::FilePath::StringType path = MakePathRelative(install_directory_,
2050 extension->path());
2051 extension_dict->Set(kPrefPath, new base::StringValue(path));
2052 if (!install_parameter.empty()) {
2053 extension_dict->Set(kPrefInstallParam,
2054 new base::StringValue(install_parameter));
2056 // We store prefs about LOAD extensions, but don't cache their manifest
2057 // since it may change on disk.
2058 if (!Manifest::IsUnpackedLocation(extension->location())) {
2059 extension_dict->Set(kPrefManifest,
2060 extension->manifest()->value()->DeepCopy());
2064 void ExtensionPrefs::InitExtensionControlledPrefs(
2065 ExtensionPrefValueMap* value_map) {
2066 ExtensionIdList extension_ids;
2067 GetExtensions(&extension_ids);
2069 for (ExtensionIdList::iterator extension_id = extension_ids.begin();
2070 extension_id != extension_ids.end();
2071 ++extension_id) {
2072 base::Time install_time = GetInstallTime(*extension_id);
2073 bool is_enabled = !IsExtensionDisabled(*extension_id);
2074 bool is_incognito_enabled = IsIncognitoEnabled(*extension_id);
2075 value_map->RegisterExtension(
2076 *extension_id, install_time, is_enabled, is_incognito_enabled);
2078 FOR_EACH_OBSERVER(
2079 ExtensionPrefsObserver,
2080 observer_list_,
2081 OnExtensionRegistered(*extension_id, install_time, is_enabled));
2083 // Set regular extension controlled prefs.
2084 LoadExtensionControlledPrefs(
2085 this, value_map, *extension_id, kExtensionPrefsScopeRegular);
2086 // Set incognito extension controlled prefs.
2087 LoadExtensionControlledPrefs(this,
2088 value_map,
2089 *extension_id,
2090 kExtensionPrefsScopeIncognitoPersistent);
2091 // Set regular-only extension controlled prefs.
2092 LoadExtensionControlledPrefs(
2093 this, value_map, *extension_id, kExtensionPrefsScopeRegularOnly);
2095 FOR_EACH_OBSERVER(ExtensionPrefsObserver,
2096 observer_list_,
2097 OnExtensionPrefsLoaded(*extension_id, this));
2101 void ExtensionPrefs::FinishExtensionInfoPrefs(
2102 const std::string& extension_id,
2103 const base::Time install_time,
2104 bool needs_sort_ordinal,
2105 const syncer::StringOrdinal& suggested_page_ordinal,
2106 base::DictionaryValue* extension_dict) {
2107 // Reinitializes various preferences with empty dictionaries.
2108 if (!extension_dict->HasKey(pref_names::kPrefPreferences)) {
2109 extension_dict->Set(pref_names::kPrefPreferences,
2110 new base::DictionaryValue);
2113 if (!extension_dict->HasKey(pref_names::kPrefIncognitoPreferences)) {
2114 extension_dict->Set(pref_names::kPrefIncognitoPreferences,
2115 new base::DictionaryValue);
2118 if (!extension_dict->HasKey(pref_names::kPrefRegularOnlyPreferences)) {
2119 extension_dict->Set(pref_names::kPrefRegularOnlyPreferences,
2120 new base::DictionaryValue);
2123 if (!extension_dict->HasKey(pref_names::kPrefContentSettings))
2124 extension_dict->Set(pref_names::kPrefContentSettings, new base::ListValue);
2126 if (!extension_dict->HasKey(pref_names::kPrefIncognitoContentSettings)) {
2127 extension_dict->Set(pref_names::kPrefIncognitoContentSettings,
2128 new base::ListValue);
2131 // If this point has been reached, any pending installs should be considered
2132 // out of date.
2133 extension_dict->Remove(kDelayedInstallInfo, NULL);
2135 // Clear state that may be registered from a previous install.
2136 extension_dict->Remove(EventRouter::kRegisteredEvents, NULL);
2138 // When evicted ephemeral apps are re-installed, this flag must be reset.
2139 extension_dict->Remove(kPrefEvictedEphemeralApp, NULL);
2141 // FYI, all code below here races on sudden shutdown because |extension_dict|,
2142 // |app_sorting_|, |extension_pref_value_map_|, and (potentially) observers
2143 // are updated non-transactionally. This is probably not fixable without
2144 // nested transactional updates to pref dictionaries.
2145 if (needs_sort_ordinal)
2146 app_sorting_->EnsureValidOrdinals(extension_id, suggested_page_ordinal);
2148 bool is_enabled = false;
2149 int initial_state;
2150 if (extension_dict->GetInteger(kPrefState, &initial_state)) {
2151 is_enabled = initial_state == Extension::ENABLED;
2153 bool is_incognito_enabled = IsIncognitoEnabled(extension_id);
2155 extension_pref_value_map_->RegisterExtension(
2156 extension_id, install_time, is_enabled, is_incognito_enabled);
2158 FOR_EACH_OBSERVER(
2159 ExtensionPrefsObserver,
2160 observer_list_,
2161 OnExtensionRegistered(extension_id, install_time, is_enabled));
2164 } // namespace extensions