Remove unused field from extension_sorting.cc
[chromium-blink-merge.git] / chrome / browser / extensions / extension_prefs.cc
blob8a212c931e8d25cd0169b428e278f0ec4632811c
1 // Copyright (c) 2012 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 "chrome/browser/extensions/extension_prefs.h"
7 #include "base/prefs/pref_notifier.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/value_conversions.h"
13 #include "chrome/browser/extensions/admin_policy.h"
14 #include "chrome/browser/extensions/api/content_settings/content_settings_store.h"
15 #include "chrome/browser/extensions/api/preference/preference_api.h"
16 #include "chrome/browser/extensions/event_router.h"
17 #include "chrome/browser/extensions/extension_pref_store.h"
18 #include "chrome/browser/extensions/extension_prefs_factory.h"
19 #include "chrome/browser/extensions/extension_sorting.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/host_desktop.h"
22 #include "chrome/common/chrome_notification_types.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/extensions/feature_switch.h"
25 #include "chrome/common/extensions/manifest.h"
26 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
27 #include "chrome/common/extensions/permissions/permission_set.h"
28 #include "chrome/common/extensions/permissions/permissions_info.h"
29 #include "chrome/common/extensions/user_script.h"
30 #include "chrome/common/pref_names.h"
31 #include "chrome/common/url_constants.h"
32 #include "components/user_prefs/pref_registry_syncable.h"
33 #include "content/public/browser/notification_service.h"
34 #include "extensions/browser/pref_names.h"
35 #include "extensions/common/url_pattern.h"
36 #include "grit/generated_resources.h"
37 #include "ui/base/l10n/l10n_util.h"
39 #if defined(USE_ASH)
40 #include "ash/shell.h"
41 #endif
42 #if defined(OS_WIN)
43 #include "win8/util/win8_util.h"
44 #endif // OS_WIN
46 using base::Value;
47 using base::DictionaryValue;
48 using base::ListValue;
50 namespace extensions {
52 namespace {
54 // Additional preferences keys, which are not needed by external clients.
56 // True if this extension is running. Note this preference stops getting updated
57 // during Chrome shutdown (and won't be updated on a browser crash) and so can
58 // be used at startup to determine whether the extension was running when Chrome
59 // was last terminated.
60 const char kPrefRunning[] = "running";
62 // Whether this extension had windows when it was last running.
63 const char kHasWindows[] = "has_windows";
65 // Where an extension was installed from. (see Manifest::Location)
66 const char kPrefLocation[] = "location";
68 // Enabled, disabled, killed, etc. (see Extension::State)
69 const char kPrefState[] = "state";
71 // The path to the current version's manifest file.
72 const char kPrefPath[] = "path";
74 // The dictionary containing the extension's manifest.
75 const char kPrefManifest[] = "manifest";
77 // The version number.
78 const char kPrefVersion[] = "manifest.version";
80 // Indicates whether an extension is blacklisted.
81 const char kPrefBlacklist[] = "blacklist";
83 // The count of how many times we prompted the user to acknowledge an
84 // extension.
85 const char kPrefAcknowledgePromptCount[] = "ack_prompt_count";
87 // Indicates whether the user has acknowledged various types of extensions.
88 const char kPrefExternalAcknowledged[] = "ack_external";
89 const char kPrefBlacklistAcknowledged[] = "ack_blacklist";
91 // Indicates whether the external extension was installed during the first
92 // run of this profile.
93 const char kPrefExternalInstallFirstRun[] = "external_first_run";
95 // Indicates whether to show an install warning when the user enables.
96 const char kExtensionDidEscalatePermissions[] = "install_warning_on_enable";
98 // DO NOT USE, use kPrefDisableReasons instead.
99 // Indicates whether the extension was updated while it was disabled.
100 const char kDeprecatedPrefDisableReason[] = "disable_reason";
102 // A bitmask of all the reasons an extension is disabled.
103 const char kPrefDisableReasons[] = "disable_reasons";
105 // The key for a serialized Time value indicating the start of the day (from the
106 // server's perspective) an extension last included a "ping" parameter during
107 // its update check.
108 const char kLastPingDay[] = "lastpingday";
110 // Similar to kLastPingDay, but for "active" instead of "rollcall" pings.
111 const char kLastActivePingDay[] = "last_active_pingday";
113 // A bit we use to keep track of whether we need to do an "active" ping.
114 const char kActiveBit[] = "active_bit";
116 // Path for settings specific to blacklist update.
117 const char kExtensionsBlacklistUpdate[] = "extensions.blacklistupdate";
119 // Path for the delayed install info dictionary preference. The actual string
120 // value is a legacy artifact for when delayed installs only pertained to
121 // updates that were waiting for idle.
122 const char kDelayedInstallInfo[] = "idle_install_info";
124 // Path for the suggested page ordinal of a delayed extension install.
125 const char kPrefSuggestedPageOrdinal[] = "suggested_page_ordinal";
127 // A preference that, if true, will allow this extension to run in incognito
128 // mode.
129 const char kPrefIncognitoEnabled[] = "incognito";
131 // A preference to control whether an extension is allowed to inject script in
132 // pages with file URLs.
133 const char kPrefAllowFileAccess[] = "newAllowFileAccess";
134 // TODO(jstritar): As part of fixing http://crbug.com/91577, we revoked all
135 // extension file access by renaming the pref. We should eventually clean up
136 // the old flag and possibly go back to that name.
137 // const char kPrefAllowFileAccessOld[] = "allowFileAccess";
139 // A preference set by the the NTP to persist the desired launch container type
140 // used for apps.
141 const char kPrefLaunchType[] = "launchType";
143 // A preference specifying if the user dragged the app on the NTP.
144 const char kPrefUserDraggedApp[] = "user_dragged_app_ntp";
146 // Preferences that hold which permissions the user has granted the extension.
147 // We explicitly keep track of these so that extensions can contain unknown
148 // permissions, for backwards compatibility reasons, and we can still prompt
149 // the user to accept them once recognized. We store the active permission
150 // permissions because they may differ from those defined in the manifest.
151 const char kPrefActivePermissions[] = "active_permissions";
152 const char kPrefGrantedPermissions[] = "granted_permissions";
154 // The preference names for PermissionSet values.
155 const char kPrefAPIs[] = "api";
156 const char kPrefExplicitHosts[] = "explicit_host";
157 const char kPrefScriptableHosts[] = "scriptable_host";
159 // The preference names for the old granted permissions scheme.
160 const char kPrefOldGrantedFullAccess[] = "granted_permissions.full";
161 const char kPrefOldGrantedHosts[] = "granted_permissions.host";
162 const char kPrefOldGrantedAPIs[] = "granted_permissions.api";
164 // A preference that indicates when an extension was installed.
165 const char kPrefInstallTime[] = "install_time";
167 // A preference which saves the creation flags for extensions.
168 const char kPrefCreationFlags[] = "creation_flags";
170 // A preference that indicates whether the extension was installed from the
171 // Chrome Web Store.
172 const char kPrefFromWebStore[] = "from_webstore";
174 // A preference that indicates whether the extension was installed from a
175 // mock App created from a bookmark.
176 const char kPrefFromBookmark[] = "from_bookmark";
178 // A preference that indicates whether the extension was installed as
179 // default apps.
180 const char kPrefWasInstalledByDefault[] = "was_installed_by_default";
182 // Key for Geometry Cache preference.
183 const char kPrefGeometryCache[] = "geometry_cache";
185 // Key for the path of the directory of the file last chosen by the user in
186 // response to a chrome.fileSystem.chooseEntry() call.
187 const char kLastChooseEntryDirectory[] = "last_choose_file_directory";
189 // Provider of write access to a dictionary storing extension prefs.
190 class ScopedExtensionPrefUpdate : public DictionaryPrefUpdate {
191 public:
192 ScopedExtensionPrefUpdate(PrefService* service,
193 const std::string& extension_id) :
194 DictionaryPrefUpdate(service, ExtensionPrefs::kExtensionsPref),
195 extension_id_(extension_id) {}
197 virtual ~ScopedExtensionPrefUpdate() {
200 // DictionaryPrefUpdate overrides:
201 virtual DictionaryValue* Get() OVERRIDE {
202 DictionaryValue* dict = DictionaryPrefUpdate::Get();
203 DictionaryValue* extension = NULL;
204 if (!dict->GetDictionary(extension_id_, &extension)) {
205 // Extension pref does not exist, create it.
206 extension = new DictionaryValue();
207 dict->SetWithoutPathExpansion(extension_id_, extension);
209 return extension;
212 private:
213 const std::string extension_id_;
215 DISALLOW_COPY_AND_ASSIGN(ScopedExtensionPrefUpdate);
218 std::string JoinPrefs(const std::string& parent, const char* child) {
219 return parent + "." + child;
222 // Checks if kPrefBlacklist is set to true in the DictionaryValue.
223 // Return false if the value is false or kPrefBlacklist does not exist.
224 // This is used to decide if an extension is blacklisted.
225 bool IsBlacklistBitSet(const DictionaryValue* ext) {
226 bool bool_value;
227 return ext->GetBoolean(kPrefBlacklist, &bool_value) && bool_value;
230 } // namespace
233 // TimeProvider
236 ExtensionPrefs::TimeProvider::TimeProvider() {
239 ExtensionPrefs::TimeProvider::~TimeProvider() {
242 base::Time ExtensionPrefs::TimeProvider::GetCurrentTime() const {
243 return base::Time::Now();
247 // ScopedUpdate
249 template <typename T, base::Value::Type type_enum_value>
250 ExtensionPrefs::ScopedUpdate<T, type_enum_value>::ScopedUpdate(
251 ExtensionPrefs* prefs,
252 const std::string& extension_id,
253 const std::string& key)
254 : update_(prefs->pref_service(), kExtensionsPref),
255 extension_id_(extension_id),
256 key_(key) {
257 DCHECK(Extension::IdIsValid(extension_id_));
260 template <typename T, base::Value::Type type_enum_value>
261 ExtensionPrefs::ScopedUpdate<T, type_enum_value>::~ScopedUpdate() {
264 template <typename T, base::Value::Type type_enum_value>
265 T* ExtensionPrefs::ScopedUpdate<T, type_enum_value>::Get() {
266 DictionaryValue* dict = update_.Get();
267 DictionaryValue* extension = NULL;
268 Value* key_value = NULL;
269 if (!dict->GetDictionary(extension_id_, &extension) ||
270 !extension->Get(key_, &key_value)) {
271 return NULL;
273 return key_value->GetType() == type_enum_value ?
274 static_cast<T*>(key_value) :
275 NULL;
278 template <typename T, base::Value::Type type_enum_value>
279 T* ExtensionPrefs::ScopedUpdate<T, type_enum_value>::Create() {
280 DictionaryValue* dict = update_.Get();
281 DictionaryValue* extension = NULL;
282 Value* key_value = NULL;
283 T* value_as_t = NULL;
284 if (!dict->GetDictionary(extension_id_, &extension)) {
285 extension = new base::DictionaryValue;
286 dict->SetWithoutPathExpansion(extension_id_, extension);
288 if (!extension->Get(key_, &key_value)) {
289 value_as_t = new T;
290 extension->SetWithoutPathExpansion(key_, value_as_t);
291 } else {
292 CHECK(key_value->GetType() == type_enum_value);
293 value_as_t = static_cast<T*>(key_value);
295 return value_as_t;
298 // Explicit instantiations for Dictionary and List value types.
299 template class ExtensionPrefs::ScopedUpdate<DictionaryValue,
300 Value::TYPE_DICTIONARY>;
301 template class ExtensionPrefs::ScopedUpdate<ListValue, Value::TYPE_LIST>;
304 // ExtensionPrefs
307 // static
308 ExtensionPrefs* ExtensionPrefs::Create(
309 PrefService* prefs,
310 const base::FilePath& root_dir,
311 ExtensionPrefValueMap* extension_pref_value_map,
312 bool extensions_disabled) {
313 return ExtensionPrefs::Create(prefs,
314 root_dir,
315 extension_pref_value_map,
316 extensions_disabled,
317 make_scoped_ptr(new TimeProvider()));
320 // static
321 ExtensionPrefs* ExtensionPrefs::Create(
322 PrefService* pref_service,
323 const base::FilePath& root_dir,
324 ExtensionPrefValueMap* extension_pref_value_map,
325 bool extensions_disabled,
326 scoped_ptr<TimeProvider> time_provider) {
327 scoped_ptr<ExtensionPrefs> prefs(
328 new ExtensionPrefs(pref_service,
329 root_dir,
330 extension_pref_value_map,
331 time_provider.Pass(),
332 extensions_disabled));
333 return prefs.release();
336 ExtensionPrefs::~ExtensionPrefs() {
339 // static
340 ExtensionPrefs* ExtensionPrefs::Get(Profile* profile) {
341 return ExtensionPrefsFactory::GetInstance()->GetForProfile(profile);
344 // static
345 const char ExtensionPrefs::kExtensionsPref[] = "extensions.settings";
346 // static
347 const char ExtensionPrefs::kExtensionsLastChromeVersion[] =
348 "extensions.last_chrome_version";
350 static base::FilePath::StringType MakePathRelative(const base::FilePath& parent,
351 const base::FilePath& child) {
352 if (!parent.IsParent(child))
353 return child.value();
355 base::FilePath::StringType retval = child.value().substr(
356 parent.value().length());
357 if (base::FilePath::IsSeparator(retval[0]))
358 return retval.substr(1);
359 else
360 return retval;
363 void ExtensionPrefs::MakePathsRelative() {
364 const DictionaryValue* dict = prefs_->GetDictionary(kExtensionsPref);
365 if (!dict || dict->empty())
366 return;
368 // Collect all extensions ids with absolute paths in |absolute_keys|.
369 std::set<std::string> absolute_keys;
370 for (DictionaryValue::Iterator i(*dict); !i.IsAtEnd(); i.Advance()) {
371 const DictionaryValue* extension_dict = NULL;
372 if (!i.value().GetAsDictionary(&extension_dict))
373 continue;
374 int location_value;
375 if (extension_dict->GetInteger(kPrefLocation, &location_value) &&
376 Manifest::IsUnpackedLocation(
377 static_cast<Manifest::Location>(location_value))) {
378 // Unpacked extensions can have absolute paths.
379 continue;
381 base::FilePath::StringType path_string;
382 if (!extension_dict->GetString(kPrefPath, &path_string))
383 continue;
384 base::FilePath path(path_string);
385 if (path.IsAbsolute())
386 absolute_keys.insert(i.key());
388 if (absolute_keys.empty())
389 return;
391 // Fix these paths.
392 DictionaryPrefUpdate update(prefs_, kExtensionsPref);
393 DictionaryValue* update_dict = update.Get();
394 for (std::set<std::string>::iterator i = absolute_keys.begin();
395 i != absolute_keys.end(); ++i) {
396 DictionaryValue* extension_dict = NULL;
397 if (!update_dict->GetDictionaryWithoutPathExpansion(*i, &extension_dict)) {
398 NOTREACHED() << "Control should never reach here for extension " << *i;
399 continue;
401 base::FilePath::StringType path_string;
402 extension_dict->GetString(kPrefPath, &path_string);
403 base::FilePath path(path_string);
404 extension_dict->SetString(kPrefPath,
405 MakePathRelative(install_directory_, path));
409 const DictionaryValue* ExtensionPrefs::GetExtensionPref(
410 const std::string& extension_id) const {
411 const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
412 const DictionaryValue* extension_dict = NULL;
413 if (!extensions ||
414 !extensions->GetDictionary(extension_id, &extension_dict)) {
415 return NULL;
417 return extension_dict;
420 void ExtensionPrefs::UpdateExtensionPref(const std::string& extension_id,
421 const std::string& key,
422 Value* data_value) {
423 if (!Extension::IdIsValid(extension_id)) {
424 NOTREACHED() << "Invalid extension_id " << extension_id;
425 return;
427 ScopedExtensionPrefUpdate update(prefs_, extension_id);
428 if (data_value)
429 update->Set(key, data_value);
430 else
431 update->Remove(key, NULL);
434 void ExtensionPrefs::DeleteExtensionPrefs(const std::string& extension_id) {
435 extension_pref_value_map_->UnregisterExtension(extension_id);
436 content_settings_store_->UnregisterExtension(extension_id);
437 DictionaryPrefUpdate update(prefs_, kExtensionsPref);
438 DictionaryValue* dict = update.Get();
439 dict->Remove(extension_id, NULL);
442 bool ExtensionPrefs::ReadPrefAsBoolean(const std::string& extension_id,
443 const std::string& pref_key,
444 bool* out_value) const {
445 const DictionaryValue* ext = GetExtensionPref(extension_id);
446 if (!ext || !ext->GetBoolean(pref_key, out_value))
447 return false;
449 return true;
452 bool ExtensionPrefs::ReadPrefAsInteger(const std::string& extension_id,
453 const std::string& pref_key,
454 int* out_value) const {
455 const DictionaryValue* ext = GetExtensionPref(extension_id);
456 if (!ext || !ext->GetInteger(pref_key, out_value))
457 return false;
459 return true;
462 bool ExtensionPrefs::ReadPrefAsString(const std::string& extension_id,
463 const std::string& pref_key,
464 std::string* out_value) const {
465 const DictionaryValue* ext = GetExtensionPref(extension_id);
466 if (!ext || !ext->GetString(pref_key, out_value))
467 return false;
469 return true;
472 bool ExtensionPrefs::ReadPrefAsList(const std::string& extension_id,
473 const std::string& pref_key,
474 const ListValue** out_value) const {
475 const DictionaryValue* ext = GetExtensionPref(extension_id);
476 const ListValue* out = NULL;
477 if (!ext || !ext->GetList(pref_key, &out))
478 return false;
479 if (out_value)
480 *out_value = out;
482 return true;
485 bool ExtensionPrefs::ReadPrefAsDictionary(
486 const std::string& extension_id,
487 const std::string& pref_key,
488 const DictionaryValue** out_value) const {
489 const DictionaryValue* ext = GetExtensionPref(extension_id);
490 const DictionaryValue* out = NULL;
491 if (!ext || !ext->GetDictionary(pref_key, &out))
492 return false;
493 if (out_value)
494 *out_value = out;
496 return true;
499 bool ExtensionPrefs::HasPrefForExtension(
500 const std::string& extension_id) const {
501 return GetExtensionPref(extension_id) != NULL;
504 bool ExtensionPrefs::ReadPrefAsURLPatternSet(const std::string& extension_id,
505 const std::string& pref_key,
506 URLPatternSet* result,
507 int valid_schemes) {
508 const ListValue* value = NULL;
509 if (!ReadPrefAsList(extension_id, pref_key, &value))
510 return false;
512 bool allow_file_access = AllowFileAccess(extension_id);
513 return result->Populate(*value, valid_schemes, allow_file_access, NULL);
516 void ExtensionPrefs::SetExtensionPrefURLPatternSet(
517 const std::string& extension_id,
518 const std::string& pref_key,
519 const URLPatternSet& new_value) {
520 UpdateExtensionPref(extension_id, pref_key, new_value.ToValue().release());
523 bool ExtensionPrefs::ReadPrefAsBooleanAndReturn(
524 const std::string& extension_id,
525 const std::string& pref_key) const {
526 bool out_value = false;
527 return ReadPrefAsBoolean(extension_id, pref_key, &out_value) && out_value;
530 PermissionSet* ExtensionPrefs::ReadPrefAsPermissionSet(
531 const std::string& extension_id,
532 const std::string& pref_key) {
533 if (!GetExtensionPref(extension_id))
534 return NULL;
536 // Retrieve the API permissions. Please refer SetExtensionPrefPermissionSet()
537 // for api_values format.
538 APIPermissionSet apis;
539 const ListValue* api_values = NULL;
540 std::string api_pref = JoinPrefs(pref_key, kPrefAPIs);
541 if (ReadPrefAsList(extension_id, api_pref, &api_values)) {
542 APIPermissionSet::ParseFromJSON(api_values, &apis, NULL, NULL);
545 // Retrieve the explicit host permissions.
546 URLPatternSet explicit_hosts;
547 ReadPrefAsURLPatternSet(
548 extension_id, JoinPrefs(pref_key, kPrefExplicitHosts),
549 &explicit_hosts, Extension::kValidHostPermissionSchemes);
551 // Retrieve the scriptable host permissions.
552 URLPatternSet scriptable_hosts;
553 ReadPrefAsURLPatternSet(
554 extension_id, JoinPrefs(pref_key, kPrefScriptableHosts),
555 &scriptable_hosts, UserScript::ValidUserScriptSchemes());
557 return new PermissionSet(apis, explicit_hosts, scriptable_hosts);
560 void ExtensionPrefs::SetExtensionPrefPermissionSet(
561 const std::string& extension_id,
562 const std::string& pref_key,
563 const PermissionSet* new_value) {
564 // Set the API permissions.
565 // The format of api_values is:
566 // [ "permission_name1", // permissions do not support detail.
567 // "permission_name2",
568 // {"permission_name3": value },
569 // // permission supports detail, permission detail will be stored in value.
570 // ...
571 // ]
572 ListValue* api_values = new ListValue();
573 APIPermissionSet apis = new_value->apis();
574 std::string api_pref = JoinPrefs(pref_key, kPrefAPIs);
575 for (APIPermissionSet::const_iterator i = apis.begin();
576 i != apis.end(); ++i) {
577 scoped_ptr<Value> detail(i->ToValue());
578 if (detail) {
579 DictionaryValue* tmp = new DictionaryValue();
580 tmp->Set(i->name(), detail.release());
581 api_values->Append(tmp);
582 } else {
583 api_values->Append(Value::CreateStringValue(i->name()));
586 UpdateExtensionPref(extension_id, api_pref, api_values);
588 // Set the explicit host permissions.
589 if (!new_value->explicit_hosts().is_empty()) {
590 SetExtensionPrefURLPatternSet(extension_id,
591 JoinPrefs(pref_key, kPrefExplicitHosts),
592 new_value->explicit_hosts());
595 // Set the scriptable host permissions.
596 if (!new_value->scriptable_hosts().is_empty()) {
597 SetExtensionPrefURLPatternSet(extension_id,
598 JoinPrefs(pref_key, kPrefScriptableHosts),
599 new_value->scriptable_hosts());
603 int ExtensionPrefs::IncrementAcknowledgePromptCount(
604 const std::string& extension_id) {
605 int count = 0;
606 ReadPrefAsInteger(extension_id, kPrefAcknowledgePromptCount, &count);
607 ++count;
608 UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount,
609 Value::CreateIntegerValue(count));
610 return count;
613 bool ExtensionPrefs::IsExternalExtensionAcknowledged(
614 const std::string& extension_id) {
615 return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalAcknowledged);
618 void ExtensionPrefs::AcknowledgeExternalExtension(
619 const std::string& extension_id) {
620 DCHECK(Extension::IdIsValid(extension_id));
621 UpdateExtensionPref(extension_id, kPrefExternalAcknowledged,
622 Value::CreateBooleanValue(true));
623 UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, NULL);
626 bool ExtensionPrefs::IsBlacklistedExtensionAcknowledged(
627 const std::string& extension_id) {
628 return ReadPrefAsBooleanAndReturn(extension_id, kPrefBlacklistAcknowledged);
631 void ExtensionPrefs::AcknowledgeBlacklistedExtension(
632 const std::string& extension_id) {
633 DCHECK(Extension::IdIsValid(extension_id));
634 UpdateExtensionPref(extension_id, kPrefBlacklistAcknowledged,
635 Value::CreateBooleanValue(true));
636 UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, NULL);
639 bool ExtensionPrefs::IsExternalInstallFirstRun(
640 const std::string& extension_id) {
641 return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalInstallFirstRun);
644 void ExtensionPrefs::SetExternalInstallFirstRun(
645 const std::string& extension_id) {
646 DCHECK(Extension::IdIsValid(extension_id));
647 UpdateExtensionPref(extension_id, kPrefExternalInstallFirstRun,
648 Value::CreateBooleanValue(true));
651 bool ExtensionPrefs::SetAlertSystemFirstRun() {
652 if (prefs_->GetBoolean(prefs::kExtensionAlertsInitializedPref)) {
653 return true;
655 prefs_->SetBoolean(prefs::kExtensionAlertsInitializedPref, true);
656 return false;
659 bool ExtensionPrefs::ExtensionsBlacklistedByDefault() const {
660 return admin_policy::BlacklistedByDefault(
661 prefs_->GetList(prefs::kExtensionInstallDenyList));
664 bool ExtensionPrefs::DidExtensionEscalatePermissions(
665 const std::string& extension_id) {
666 return ReadPrefAsBooleanAndReturn(extension_id,
667 kExtensionDidEscalatePermissions);
670 void ExtensionPrefs::SetDidExtensionEscalatePermissions(
671 const Extension* extension, bool did_escalate) {
672 UpdateExtensionPref(extension->id(), kExtensionDidEscalatePermissions,
673 Value::CreateBooleanValue(did_escalate));
676 int ExtensionPrefs::GetDisableReasons(const std::string& extension_id) {
677 int value = -1;
678 if (ReadPrefAsInteger(extension_id, kPrefDisableReasons, &value) &&
679 value >= 0) {
680 return value;
682 return Extension::DISABLE_NONE;
685 void ExtensionPrefs::AddDisableReason(const std::string& extension_id,
686 Extension::DisableReason disable_reason) {
687 int new_value = GetDisableReasons(extension_id) |
688 static_cast<int>(disable_reason);
689 UpdateExtensionPref(extension_id, kPrefDisableReasons,
690 Value::CreateIntegerValue(new_value));
693 void ExtensionPrefs::RemoveDisableReason(
694 const std::string& extension_id,
695 Extension::DisableReason disable_reason) {
696 int new_value = GetDisableReasons(extension_id) &
697 ~static_cast<int>(disable_reason);
698 if (new_value == Extension::DISABLE_NONE) {
699 UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL);
700 } else {
701 UpdateExtensionPref(extension_id, kPrefDisableReasons,
702 Value::CreateIntegerValue(new_value));
706 void ExtensionPrefs::ClearDisableReasons(const std::string& extension_id) {
707 UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL);
710 std::set<std::string> ExtensionPrefs::GetBlacklistedExtensions() {
711 std::set<std::string> ids;
713 const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
714 if (!extensions)
715 return ids;
717 for (DictionaryValue::Iterator it(*extensions); !it.IsAtEnd(); it.Advance()) {
718 if (!it.value().IsType(Value::TYPE_DICTIONARY)) {
719 NOTREACHED() << "Invalid pref for extension " << it.key();
720 continue;
722 if (IsBlacklistBitSet(static_cast<const DictionaryValue*>(&it.value())))
723 ids.insert(it.key());
726 return ids;
729 void ExtensionPrefs::SetExtensionBlacklisted(const std::string& extension_id,
730 bool is_blacklisted) {
731 bool currently_blacklisted = IsExtensionBlacklisted(extension_id);
732 if (is_blacklisted == currently_blacklisted) {
733 NOTREACHED() << extension_id << " is " <<
734 (currently_blacklisted ? "already" : "not") <<
735 " blacklisted";
736 return;
739 // Always make sure the "acknowledged" bit is cleared since the blacklist bit
740 // is changing.
741 UpdateExtensionPref(extension_id, kPrefBlacklistAcknowledged, NULL);
743 if (is_blacklisted) {
744 UpdateExtensionPref(extension_id,
745 kPrefBlacklist,
746 new base::FundamentalValue(true));
747 } else {
748 UpdateExtensionPref(extension_id, kPrefBlacklist, NULL);
749 const DictionaryValue* dict = GetExtensionPref(extension_id);
750 if (dict && dict->empty())
751 DeleteExtensionPrefs(extension_id);
755 bool ExtensionPrefs::IsExtensionBlacklisted(const std::string& id) const {
756 const DictionaryValue* ext_prefs = GetExtensionPref(id);
757 return ext_prefs && IsBlacklistBitSet(ext_prefs);
760 namespace {
762 // Serializes |time| as a string value mapped to |key| in |dictionary|.
763 void SaveTime(DictionaryValue* dictionary,
764 const char* key,
765 const base::Time& time) {
766 if (!dictionary)
767 return;
768 std::string string_value = base::Int64ToString(time.ToInternalValue());
769 dictionary->SetString(key, string_value);
772 // The opposite of SaveTime. If |key| is not found, this returns an empty Time
773 // (is_null() will return true).
774 base::Time ReadTime(const DictionaryValue* dictionary, const char* key) {
775 if (!dictionary)
776 return base::Time();
777 std::string string_value;
778 int64 value;
779 if (dictionary->GetString(key, &string_value)) {
780 if (base::StringToInt64(string_value, &value)) {
781 return base::Time::FromInternalValue(value);
784 return base::Time();
787 } // namespace
789 base::Time ExtensionPrefs::LastPingDay(const std::string& extension_id) const {
790 DCHECK(Extension::IdIsValid(extension_id));
791 return ReadTime(GetExtensionPref(extension_id), kLastPingDay);
794 void ExtensionPrefs::SetLastPingDay(const std::string& extension_id,
795 const base::Time& time) {
796 DCHECK(Extension::IdIsValid(extension_id));
797 ScopedExtensionPrefUpdate update(prefs_, extension_id);
798 SaveTime(update.Get(), kLastPingDay, time);
801 base::Time ExtensionPrefs::BlacklistLastPingDay() const {
802 return ReadTime(prefs_->GetDictionary(kExtensionsBlacklistUpdate),
803 kLastPingDay);
806 void ExtensionPrefs::SetBlacklistLastPingDay(const base::Time& time) {
807 DictionaryPrefUpdate update(prefs_, kExtensionsBlacklistUpdate);
808 SaveTime(update.Get(), kLastPingDay, time);
811 base::Time ExtensionPrefs::LastActivePingDay(const std::string& extension_id) {
812 DCHECK(Extension::IdIsValid(extension_id));
813 return ReadTime(GetExtensionPref(extension_id), kLastActivePingDay);
816 void ExtensionPrefs::SetLastActivePingDay(const std::string& extension_id,
817 const base::Time& time) {
818 DCHECK(Extension::IdIsValid(extension_id));
819 ScopedExtensionPrefUpdate update(prefs_, extension_id);
820 SaveTime(update.Get(), kLastActivePingDay, time);
823 bool ExtensionPrefs::GetActiveBit(const std::string& extension_id) {
824 const DictionaryValue* dictionary = GetExtensionPref(extension_id);
825 bool result = false;
826 if (dictionary && dictionary->GetBoolean(kActiveBit, &result))
827 return result;
828 return false;
831 void ExtensionPrefs::SetActiveBit(const std::string& extension_id,
832 bool active) {
833 UpdateExtensionPref(extension_id, kActiveBit,
834 Value::CreateBooleanValue(active));
837 void ExtensionPrefs::MigratePermissions(const ExtensionIdList& extension_ids) {
838 PermissionsInfo* info = PermissionsInfo::GetInstance();
839 for (ExtensionIdList::const_iterator ext_id =
840 extension_ids.begin(); ext_id != extension_ids.end(); ++ext_id) {
842 // An extension's granted permissions need to be migrated if the
843 // full_access bit is present. This bit was always present in the previous
844 // scheme and is never present now.
845 bool full_access;
846 const DictionaryValue* ext = GetExtensionPref(*ext_id);
847 if (!ext || !ext->GetBoolean(kPrefOldGrantedFullAccess, &full_access))
848 continue;
850 // Remove the full access bit (empty list will get trimmed).
851 UpdateExtensionPref(
852 *ext_id, kPrefOldGrantedFullAccess, new ListValue());
854 // Add the plugin permission if the full access bit was set.
855 if (full_access) {
856 const ListValue* apis = NULL;
857 ListValue* new_apis = NULL;
859 std::string granted_apis =
860 JoinPrefs(kPrefGrantedPermissions, kPrefAPIs);
861 if (ext->GetList(kPrefOldGrantedAPIs, &apis))
862 new_apis = apis->DeepCopy();
863 else
864 new_apis = new ListValue();
866 std::string plugin_name = info->GetByID(
867 APIPermission::kPlugin)->name();
868 new_apis->Append(Value::CreateStringValue(plugin_name));
869 UpdateExtensionPref(*ext_id, granted_apis, new_apis);
872 // The granted permissions originally only held the effective hosts,
873 // which are a combination of host and user script host permissions.
874 // We now maintain these lists separately. For migration purposes, it
875 // does not matter how we treat the old effective hosts as long as the
876 // new effective hosts will be the same, so we move them to explicit
877 // host permissions.
878 const ListValue* hosts = NULL;
879 std::string explicit_hosts =
880 JoinPrefs(kPrefGrantedPermissions, kPrefExplicitHosts);
881 if (ext->GetList(kPrefOldGrantedHosts, &hosts)) {
882 UpdateExtensionPref(
883 *ext_id, explicit_hosts, hosts->DeepCopy());
885 // We can get rid of the old one by setting it to an empty list.
886 UpdateExtensionPref(*ext_id, kPrefOldGrantedHosts, new ListValue());
891 void ExtensionPrefs::MigrateDisableReasons(
892 const ExtensionIdList& extension_ids) {
893 for (ExtensionIdList::const_iterator ext_id =
894 extension_ids.begin(); ext_id != extension_ids.end(); ++ext_id) {
895 int value = -1;
896 if (ReadPrefAsInteger(*ext_id, kDeprecatedPrefDisableReason, &value)) {
897 int new_value = Extension::DISABLE_NONE;
898 switch (value) {
899 case Extension::DEPRECATED_DISABLE_USER_ACTION:
900 new_value = Extension::DISABLE_USER_ACTION;
901 break;
902 case Extension::DEPRECATED_DISABLE_PERMISSIONS_INCREASE:
903 new_value = Extension::DISABLE_PERMISSIONS_INCREASE;
904 break;
905 case Extension::DEPRECATED_DISABLE_RELOAD:
906 new_value = Extension::DISABLE_RELOAD;
907 break;
910 UpdateExtensionPref(*ext_id, kPrefDisableReasons,
911 Value::CreateIntegerValue(new_value));
912 // Remove the old disable reason.
913 UpdateExtensionPref(*ext_id, kDeprecatedPrefDisableReason, NULL);
918 PermissionSet* ExtensionPrefs::GetGrantedPermissions(
919 const std::string& extension_id) {
920 CHECK(Extension::IdIsValid(extension_id));
921 return ReadPrefAsPermissionSet(extension_id, kPrefGrantedPermissions);
924 void ExtensionPrefs::AddGrantedPermissions(
925 const std::string& extension_id,
926 const PermissionSet* permissions) {
927 CHECK(Extension::IdIsValid(extension_id));
929 scoped_refptr<PermissionSet> granted_permissions(
930 GetGrantedPermissions(extension_id));
932 // The new granted permissions are the union of the already granted
933 // permissions and the newly granted permissions.
934 scoped_refptr<PermissionSet> new_perms(
935 PermissionSet::CreateUnion(
936 permissions, granted_permissions.get()));
938 SetExtensionPrefPermissionSet(
939 extension_id, kPrefGrantedPermissions, new_perms.get());
942 void ExtensionPrefs::RemoveGrantedPermissions(
943 const std::string& extension_id,
944 const PermissionSet* permissions) {
945 CHECK(Extension::IdIsValid(extension_id));
947 scoped_refptr<PermissionSet> granted_permissions(
948 GetGrantedPermissions(extension_id));
950 // The new granted permissions are the difference of the already granted
951 // permissions and the newly ungranted permissions.
952 scoped_refptr<PermissionSet> new_perms(
953 PermissionSet::CreateDifference(
954 granted_permissions.get(), permissions));
956 SetExtensionPrefPermissionSet(
957 extension_id, kPrefGrantedPermissions, new_perms.get());
960 PermissionSet* ExtensionPrefs::GetActivePermissions(
961 const std::string& extension_id) {
962 CHECK(Extension::IdIsValid(extension_id));
963 return ReadPrefAsPermissionSet(extension_id, kPrefActivePermissions);
966 void ExtensionPrefs::SetActivePermissions(
967 const std::string& extension_id,
968 const PermissionSet* permissions) {
969 SetExtensionPrefPermissionSet(
970 extension_id, kPrefActivePermissions, permissions);
973 void ExtensionPrefs::SetExtensionRunning(const std::string& extension_id,
974 bool is_running) {
975 Value* value = Value::CreateBooleanValue(is_running);
976 UpdateExtensionPref(extension_id, kPrefRunning, value);
979 bool ExtensionPrefs::IsExtensionRunning(const std::string& extension_id) {
980 const DictionaryValue* extension = GetExtensionPref(extension_id);
981 if (!extension)
982 return false;
983 bool running = false;
984 extension->GetBoolean(kPrefRunning, &running);
985 return running;
988 void ExtensionPrefs::SetHasWindows(const std::string& extension_id,
989 bool has_windows) {
990 Value* value = Value::CreateBooleanValue(has_windows);
991 UpdateExtensionPref(extension_id, kHasWindows, value);
994 bool ExtensionPrefs::HasWindows(const std::string& extension_id) {
995 const DictionaryValue* extension = GetExtensionPref(extension_id);
996 if (!extension)
997 return false;
998 bool has_windows = false;
999 extension->GetBoolean(kHasWindows, &has_windows);
1000 return has_windows;
1003 bool ExtensionPrefs::IsIncognitoEnabled(const std::string& extension_id) {
1004 return ReadPrefAsBooleanAndReturn(extension_id, kPrefIncognitoEnabled);
1007 void ExtensionPrefs::SetIsIncognitoEnabled(const std::string& extension_id,
1008 bool enabled) {
1009 UpdateExtensionPref(extension_id, kPrefIncognitoEnabled,
1010 Value::CreateBooleanValue(enabled));
1013 bool ExtensionPrefs::AllowFileAccess(const std::string& extension_id) {
1014 return ReadPrefAsBooleanAndReturn(extension_id, kPrefAllowFileAccess);
1017 void ExtensionPrefs::SetAllowFileAccess(const std::string& extension_id,
1018 bool allow) {
1019 UpdateExtensionPref(extension_id, kPrefAllowFileAccess,
1020 Value::CreateBooleanValue(allow));
1023 bool ExtensionPrefs::HasAllowFileAccessSetting(
1024 const std::string& extension_id) const {
1025 const DictionaryValue* ext = GetExtensionPref(extension_id);
1026 return ext && ext->HasKey(kPrefAllowFileAccess);
1029 ExtensionPrefs::LaunchType ExtensionPrefs::GetLaunchType(
1030 const Extension* extension,
1031 ExtensionPrefs::LaunchType default_pref_value) {
1032 int value = -1;
1033 LaunchType result = LAUNCH_REGULAR;
1035 if (ReadPrefAsInteger(extension->id(), kPrefLaunchType, &value) &&
1036 (value == LAUNCH_PINNED ||
1037 value == LAUNCH_REGULAR ||
1038 value == LAUNCH_FULLSCREEN ||
1039 value == LAUNCH_WINDOW)) {
1040 result = static_cast<LaunchType>(value);
1041 } else {
1042 result = default_pref_value;
1044 #if (USE_ASH)
1045 if (ash::Shell::IsForcedMaximizeMode() &&
1046 (result == LAUNCH_FULLSCREEN || result == LAUNCH_WINDOW))
1047 result = LAUNCH_REGULAR;
1048 #endif
1049 #if defined(OS_MACOSX)
1050 // App windows are not yet supported on mac. Pref sync could make
1051 // the launch type LAUNCH_WINDOW, even if there is no UI to set it
1052 // on mac.
1053 if (!extension->is_platform_app() && result == LAUNCH_WINDOW)
1054 result = LAUNCH_REGULAR;
1055 #endif
1057 #if defined(OS_WIN)
1058 // We don't support app windows in Windows 8 single window Metro mode.
1059 if (win8::IsSingleWindowMetroMode() && result == LAUNCH_WINDOW)
1060 result = LAUNCH_REGULAR;
1061 #endif // OS_WIN
1063 return result;
1066 extension_misc::LaunchContainer ExtensionPrefs::GetLaunchContainer(
1067 const Extension* extension,
1068 ExtensionPrefs::LaunchType default_pref_value) {
1069 extension_misc::LaunchContainer manifest_launch_container =
1070 AppLaunchInfo::GetLaunchContainer(extension);
1072 const extension_misc::LaunchContainer kInvalidLaunchContainer =
1073 static_cast<extension_misc::LaunchContainer>(-1);
1075 extension_misc::LaunchContainer result = kInvalidLaunchContainer;
1077 if (manifest_launch_container == extension_misc::LAUNCH_PANEL) {
1078 // Apps with app.launch.container = 'panel' should always respect the
1079 // manifest setting.
1080 result = manifest_launch_container;
1081 } else if (manifest_launch_container == extension_misc::LAUNCH_TAB) {
1082 // Look for prefs that indicate the user's choice of launch
1083 // container. The app's menu on the NTP provides a UI to set
1084 // this preference. If no preference is set, |default_pref_value|
1085 // is used.
1086 ExtensionPrefs::LaunchType prefs_launch_type =
1087 GetLaunchType(extension, default_pref_value);
1089 if (prefs_launch_type == ExtensionPrefs::LAUNCH_WINDOW) {
1090 // If the pref is set to launch a window (or no pref is set, and
1091 // window opening is the default), make the container a window.
1092 result = extension_misc::LAUNCH_WINDOW;
1093 #if defined(USE_ASH)
1094 } else if (prefs_launch_type == ExtensionPrefs::LAUNCH_FULLSCREEN &&
1095 chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH) {
1096 // LAUNCH_FULLSCREEN launches in a maximized app window in ash.
1097 // For desktop chrome AURA on all platforms we should open the
1098 // application in full screen mode in the current tab, on the same
1099 // lines as non AURA chrome.
1100 result = extension_misc::LAUNCH_WINDOW;
1101 #endif
1102 } else {
1103 // All other launch types (tab, pinned, fullscreen) are
1104 // implemented as tabs in a window.
1105 result = extension_misc::LAUNCH_TAB;
1107 } else {
1108 // If a new value for app.launch.container is added, logic
1109 // for it should be added here. extension_misc::LAUNCH_WINDOW
1110 // is not present because there is no way to set it in a manifest.
1111 NOTREACHED() << manifest_launch_container;
1114 // All paths should set |result|.
1115 if (result == kInvalidLaunchContainer) {
1116 DLOG(FATAL) << "Failed to set a launch container.";
1117 result = extension_misc::LAUNCH_TAB;
1120 return result;
1123 void ExtensionPrefs::SetLaunchType(const std::string& extension_id,
1124 LaunchType launch_type) {
1125 UpdateExtensionPref(extension_id, kPrefLaunchType,
1126 Value::CreateIntegerValue(static_cast<int>(launch_type)));
1129 bool ExtensionPrefs::DoesExtensionHaveState(
1130 const std::string& id, Extension::State check_state) const {
1131 const DictionaryValue* extension = GetExtensionPref(id);
1132 int state = -1;
1133 if (!extension || !extension->GetInteger(kPrefState, &state))
1134 return false;
1136 if (state < 0 || state >= Extension::NUM_STATES) {
1137 LOG(ERROR) << "Bad pref 'state' for extension '" << id << "'";
1138 return false;
1141 return state == check_state;
1144 bool ExtensionPrefs::IsExternalExtensionUninstalled(
1145 const std::string& id) const {
1146 return DoesExtensionHaveState(id, Extension::EXTERNAL_EXTENSION_UNINSTALLED);
1149 bool ExtensionPrefs::IsExtensionDisabled(
1150 const std::string& id) const {
1151 return DoesExtensionHaveState(id, Extension::DISABLED);
1154 ExtensionIdList ExtensionPrefs::GetToolbarOrder() {
1155 return GetExtensionPrefAsVector(prefs::kExtensionToolbar);
1158 void ExtensionPrefs::SetToolbarOrder(const ExtensionIdList& extension_ids) {
1159 SetExtensionPrefFromVector(prefs::kExtensionToolbar, extension_ids);
1162 void ExtensionPrefs::OnExtensionInstalled(
1163 const Extension* extension,
1164 Extension::State initial_state,
1165 const syncer::StringOrdinal& page_ordinal) {
1166 ScopedExtensionPrefUpdate update(prefs_, extension->id());
1167 DictionaryValue* extension_dict = update.Get();
1168 const base::Time install_time = time_provider_->GetCurrentTime();
1169 PopulateExtensionInfoPrefs(extension, install_time, initial_state,
1170 extension_dict);
1171 FinishExtensionInfoPrefs(extension->id(), install_time,
1172 extension->RequiresSortOrdinal(),
1173 page_ordinal, extension_dict);
1176 void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id,
1177 const Manifest::Location& location,
1178 bool external_uninstall) {
1179 extension_sorting_->ClearOrdinals(extension_id);
1181 // For external extensions, we save a preference reminding ourself not to try
1182 // and install the extension anymore (except when |external_uninstall| is
1183 // true, which signifies that the registry key was deleted or the pref file
1184 // no longer lists the extension).
1185 if (!external_uninstall && Manifest::IsExternalLocation(location)) {
1186 UpdateExtensionPref(extension_id, kPrefState,
1187 Value::CreateIntegerValue(
1188 Extension::EXTERNAL_EXTENSION_UNINSTALLED));
1189 extension_pref_value_map_->SetExtensionState(extension_id, false);
1190 content_settings_store_->SetExtensionState(extension_id, false);
1191 } else {
1192 DeleteExtensionPrefs(extension_id);
1196 void ExtensionPrefs::SetExtensionState(const std::string& extension_id,
1197 Extension::State state) {
1198 UpdateExtensionPref(extension_id, kPrefState,
1199 Value::CreateIntegerValue(state));
1200 bool enabled = (state == Extension::ENABLED);
1201 extension_pref_value_map_->SetExtensionState(extension_id, enabled);
1202 content_settings_store_->SetExtensionState(extension_id, enabled);
1205 std::string ExtensionPrefs::GetVersionString(const std::string& extension_id) {
1206 const DictionaryValue* extension = GetExtensionPref(extension_id);
1207 if (!extension)
1208 return std::string();
1210 std::string version;
1211 extension->GetString(kPrefVersion, &version);
1213 return version;
1216 void ExtensionPrefs::UpdateManifest(const Extension* extension) {
1217 if (!Manifest::IsUnpackedLocation(extension->location())) {
1218 const DictionaryValue* extension_dict =
1219 GetExtensionPref(extension->id());
1220 if (!extension_dict)
1221 return;
1222 const DictionaryValue* old_manifest = NULL;
1223 bool update_required =
1224 !extension_dict->GetDictionary(kPrefManifest, &old_manifest) ||
1225 !extension->manifest()->value()->Equals(old_manifest);
1226 if (update_required) {
1227 UpdateExtensionPref(extension->id(), kPrefManifest,
1228 extension->manifest()->value()->DeepCopy());
1233 base::FilePath ExtensionPrefs::GetExtensionPath(
1234 const std::string& extension_id) {
1235 const DictionaryValue* dict = GetExtensionPref(extension_id);
1236 if (!dict)
1237 return base::FilePath();
1239 std::string path;
1240 if (!dict->GetString(kPrefPath, &path))
1241 return base::FilePath();
1243 return install_directory_.Append(
1244 base::FilePath::FromWStringHack(UTF8ToWide(path)));
1247 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetInstalledInfoHelper(
1248 const std::string& extension_id,
1249 const DictionaryValue* extension) const {
1250 int location_value;
1251 if (!extension->GetInteger(kPrefLocation, &location_value))
1252 return scoped_ptr<ExtensionInfo>();
1254 base::FilePath::StringType path;
1255 if (!extension->GetString(kPrefPath, &path))
1256 return scoped_ptr<ExtensionInfo>();
1258 // Make path absolute. Unpacked extensions will already have absolute paths,
1259 // otherwise make it so.
1260 Manifest::Location location = static_cast<Manifest::Location>(location_value);
1261 if (!Manifest::IsUnpackedLocation(location)) {
1262 DCHECK(location == Manifest::COMPONENT ||
1263 !base::FilePath(path).IsAbsolute());
1264 path = install_directory_.Append(path).value();
1267 // Only the following extension types have data saved in the preferences.
1268 if (location != Manifest::INTERNAL &&
1269 !Manifest::IsUnpackedLocation(location) &&
1270 !Manifest::IsExternalLocation(location)) {
1271 NOTREACHED();
1272 return scoped_ptr<ExtensionInfo>();
1275 const DictionaryValue* manifest = NULL;
1276 if (!Manifest::IsUnpackedLocation(location) &&
1277 !extension->GetDictionary(kPrefManifest, &manifest)) {
1278 LOG(WARNING) << "Missing manifest for extension " << extension_id;
1279 // Just a warning for now.
1282 return scoped_ptr<ExtensionInfo>(new ExtensionInfo(
1283 manifest, extension_id, base::FilePath(path), location));
1286 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetInstalledExtensionInfo(
1287 const std::string& extension_id) const {
1288 const DictionaryValue* ext = NULL;
1289 const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
1290 if (!extensions ||
1291 !extensions->GetDictionaryWithoutPathExpansion(extension_id, &ext))
1292 return scoped_ptr<ExtensionInfo>();
1293 int state_value;
1294 if (!ext->GetInteger(kPrefState, &state_value) ||
1295 state_value == Extension::ENABLED_COMPONENT) {
1296 // Old preferences files may not have kPrefState for component extensions.
1297 return scoped_ptr<ExtensionInfo>();
1300 if (state_value == Extension::EXTERNAL_EXTENSION_UNINSTALLED) {
1301 LOG(WARNING) << "External extension with id " << extension_id
1302 << " has been uninstalled by the user";
1303 return scoped_ptr<ExtensionInfo>();
1306 return GetInstalledInfoHelper(extension_id, ext);
1309 scoped_ptr<ExtensionPrefs::ExtensionsInfo>
1310 ExtensionPrefs::GetInstalledExtensionsInfo() const {
1311 scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
1313 const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
1314 for (DictionaryValue::Iterator extension_id(*extensions);
1315 !extension_id.IsAtEnd(); extension_id.Advance()) {
1316 if (!Extension::IdIsValid(extension_id.key()))
1317 continue;
1319 scoped_ptr<ExtensionInfo> info =
1320 GetInstalledExtensionInfo(extension_id.key());
1321 if (info)
1322 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
1325 return extensions_info.Pass();
1328 void ExtensionPrefs::SetDelayedInstallInfo(
1329 const Extension* extension,
1330 Extension::State initial_state,
1331 const syncer::StringOrdinal& page_ordinal) {
1332 DictionaryValue* extension_dict = new DictionaryValue();
1333 PopulateExtensionInfoPrefs(extension, time_provider_->GetCurrentTime(),
1334 initial_state, extension_dict);
1336 // Add transient data that is needed by FinishDelayedInstallInfo(), but
1337 // should not be in the final extension prefs. All entries here should have
1338 // a corresponding Remove() call in FinishDelayedInstallInfo().
1339 if (extension->RequiresSortOrdinal()) {
1340 extension_dict->SetString(
1341 kPrefSuggestedPageOrdinal,
1342 page_ordinal.IsValid() ? page_ordinal.ToInternalValue()
1343 : std::string());
1346 UpdateExtensionPref(extension->id(), kDelayedInstallInfo, extension_dict);
1349 bool ExtensionPrefs::RemoveDelayedInstallInfo(
1350 const std::string& extension_id) {
1351 if (!GetExtensionPref(extension_id))
1352 return false;
1353 ScopedExtensionPrefUpdate update(prefs_, extension_id);
1354 bool result = update->Remove(kDelayedInstallInfo, NULL);
1355 return result;
1358 bool ExtensionPrefs::FinishDelayedInstallInfo(
1359 const std::string& extension_id) {
1360 CHECK(Extension::IdIsValid(extension_id));
1361 ScopedExtensionPrefUpdate update(prefs_, extension_id);
1362 DictionaryValue* extension_dict = update.Get();
1363 DictionaryValue* pending_install_dict = NULL;
1364 if (!extension_dict->GetDictionary(kDelayedInstallInfo,
1365 &pending_install_dict)) {
1366 return false;
1369 // Retrieve and clear transient values populated by SetDelayedInstallInfo().
1370 // Also do any other data cleanup that makes sense.
1371 std::string serialized_ordinal;
1372 syncer::StringOrdinal suggested_page_ordinal;
1373 bool needs_sort_ordinal = false;
1374 if (pending_install_dict->GetString(kPrefSuggestedPageOrdinal,
1375 &serialized_ordinal)) {
1376 suggested_page_ordinal = syncer::StringOrdinal(serialized_ordinal);
1377 needs_sort_ordinal = true;
1378 pending_install_dict->Remove(kPrefSuggestedPageOrdinal, NULL);
1381 const base::Time install_time = time_provider_->GetCurrentTime();
1382 pending_install_dict->Set(
1383 kPrefInstallTime,
1384 Value::CreateStringValue(
1385 base::Int64ToString(install_time.ToInternalValue())));
1387 // Commit the delayed install data.
1388 extension_dict->MergeDictionary(pending_install_dict);
1389 FinishExtensionInfoPrefs(extension_id, install_time, needs_sort_ordinal,
1390 suggested_page_ordinal, extension_dict);
1391 return true;
1394 scoped_ptr<ExtensionInfo> ExtensionPrefs::GetDelayedInstallInfo(
1395 const std::string& extension_id) const {
1396 const DictionaryValue* extension_prefs =
1397 GetExtensionPref(extension_id);
1398 if (!extension_prefs)
1399 return scoped_ptr<ExtensionInfo>();
1401 const DictionaryValue* ext = NULL;
1402 if (!extension_prefs->GetDictionary(kDelayedInstallInfo, &ext))
1403 return scoped_ptr<ExtensionInfo>();
1405 return GetInstalledInfoHelper(extension_id, ext);
1408 scoped_ptr<ExtensionPrefs::ExtensionsInfo> ExtensionPrefs::
1409 GetAllDelayedInstallInfo() const {
1410 scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
1412 const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
1413 for (DictionaryValue::Iterator extension_id(*extensions);
1414 !extension_id.IsAtEnd(); extension_id.Advance()) {
1415 if (!Extension::IdIsValid(extension_id.key()))
1416 continue;
1418 scoped_ptr<ExtensionInfo> info = GetDelayedInstallInfo(extension_id.key());
1419 if (info)
1420 extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
1423 return extensions_info.Pass();
1426 bool ExtensionPrefs::WasAppDraggedByUser(const std::string& extension_id) {
1427 return ReadPrefAsBooleanAndReturn(extension_id, kPrefUserDraggedApp);
1430 void ExtensionPrefs::SetAppDraggedByUser(const std::string& extension_id) {
1431 UpdateExtensionPref(extension_id, kPrefUserDraggedApp,
1432 Value::CreateBooleanValue(true));
1435 bool ExtensionPrefs::IsFromWebStore(
1436 const std::string& extension_id) const {
1437 const DictionaryValue* dictionary = GetExtensionPref(extension_id);
1438 bool result = false;
1439 if (dictionary && dictionary->GetBoolean(kPrefFromWebStore, &result))
1440 return result;
1441 return false;
1444 bool ExtensionPrefs::IsFromBookmark(
1445 const std::string& extension_id) const {
1446 const DictionaryValue* dictionary = GetExtensionPref(extension_id);
1447 bool result = false;
1448 if (dictionary && dictionary->GetBoolean(kPrefFromBookmark, &result))
1449 return result;
1450 return false;
1453 int ExtensionPrefs::GetCreationFlags(const std::string& extension_id) const {
1454 int creation_flags = Extension::NO_FLAGS;
1455 if (!ReadPrefAsInteger(extension_id, kPrefCreationFlags, &creation_flags)) {
1456 // Since kPrefCreationFlags was added later, it will be missing for
1457 // previously installed extensions.
1458 if (IsFromBookmark(extension_id))
1459 creation_flags |= Extension::FROM_BOOKMARK;
1460 if (IsFromWebStore(extension_id))
1461 creation_flags |= Extension::FROM_WEBSTORE;
1462 if (WasInstalledByDefault(extension_id))
1463 creation_flags |= Extension::WAS_INSTALLED_BY_DEFAULT;
1465 return creation_flags;
1468 bool ExtensionPrefs::WasInstalledByDefault(
1469 const std::string& extension_id) const {
1470 const DictionaryValue* dictionary = GetExtensionPref(extension_id);
1471 bool result = false;
1472 if (dictionary &&
1473 dictionary->GetBoolean(kPrefWasInstalledByDefault, &result))
1474 return result;
1475 return false;
1478 base::Time ExtensionPrefs::GetInstallTime(
1479 const std::string& extension_id) const {
1480 const DictionaryValue* extension = GetExtensionPref(extension_id);
1481 if (!extension) {
1482 NOTREACHED();
1483 return base::Time();
1485 std::string install_time_str;
1486 if (!extension->GetString(kPrefInstallTime, &install_time_str))
1487 return base::Time();
1488 int64 install_time_i64 = 0;
1489 if (!base::StringToInt64(install_time_str, &install_time_i64))
1490 return base::Time();
1491 return base::Time::FromInternalValue(install_time_i64);
1494 void ExtensionPrefs::GetExtensions(ExtensionIdList* out) {
1495 CHECK(out);
1497 scoped_ptr<ExtensionsInfo> extensions_info(GetInstalledExtensionsInfo());
1499 for (size_t i = 0; i < extensions_info->size(); ++i) {
1500 ExtensionInfo* info = extensions_info->at(i).get();
1501 out->push_back(info->extension_id);
1505 // static
1506 ExtensionIdList ExtensionPrefs::GetExtensionsFrom(
1507 const PrefService* pref_service) {
1508 ExtensionIdList result;
1510 const DictionaryValue* extension_prefs = NULL;
1511 const Value* extension_prefs_value =
1512 pref_service->GetUserPrefValue(kExtensionsPref);
1513 if (!extension_prefs_value ||
1514 !extension_prefs_value->GetAsDictionary(&extension_prefs)) {
1515 return result; // Empty set
1518 for (DictionaryValue::Iterator it(*extension_prefs); !it.IsAtEnd();
1519 it.Advance()) {
1520 const DictionaryValue* ext = NULL;
1521 if (!it.value().GetAsDictionary(&ext)) {
1522 NOTREACHED() << "Invalid pref for extension " << it.key();
1523 continue;
1525 if (!IsBlacklistBitSet(ext))
1526 result.push_back(it.key());
1528 return result;
1531 void ExtensionPrefs::FixMissingPrefs(const ExtensionIdList& extension_ids) {
1532 // Fix old entries that did not get an installation time entry when they
1533 // were installed or don't have a preferences field.
1534 for (ExtensionIdList::const_iterator ext_id = extension_ids.begin();
1535 ext_id != extension_ids.end(); ++ext_id) {
1536 if (GetInstallTime(*ext_id) == base::Time()) {
1537 LOG(INFO) << "Could not parse installation time of extension "
1538 << *ext_id << ". It was probably installed before setting "
1539 << kPrefInstallTime << " was introduced. Updating "
1540 << kPrefInstallTime << " to the current time.";
1541 const base::Time install_time = time_provider_->GetCurrentTime();
1542 UpdateExtensionPref(*ext_id,
1543 kPrefInstallTime,
1544 Value::CreateStringValue(base::Int64ToString(
1545 install_time.ToInternalValue())));
1550 void ExtensionPrefs::InitPrefStore() {
1551 if (extensions_disabled_) {
1552 extension_pref_value_map_->NotifyInitializationCompleted();
1553 return;
1556 // When this is called, the PrefService is initialized and provides access
1557 // to the user preferences stored in a JSON file.
1558 ExtensionIdList extension_ids;
1559 GetExtensions(&extension_ids);
1560 // Create empty preferences dictionary for each extension (these dictionaries
1561 // are pruned when persisting the preferences to disk).
1562 for (ExtensionIdList::iterator ext_id = extension_ids.begin();
1563 ext_id != extension_ids.end(); ++ext_id) {
1564 ScopedExtensionPrefUpdate update(prefs_, *ext_id);
1565 // This creates an empty dictionary if none is stored.
1566 update.Get();
1569 FixMissingPrefs(extension_ids);
1570 MigratePermissions(extension_ids);
1571 MigrateDisableReasons(extension_ids);
1572 extension_sorting_->Initialize(extension_ids);
1574 PreferenceAPI::InitExtensionControlledPrefs(this, extension_pref_value_map_);
1576 extension_pref_value_map_->NotifyInitializationCompleted();
1579 bool ExtensionPrefs::HasIncognitoPrefValue(const std::string& pref_key) {
1580 bool has_incognito_pref_value = false;
1581 extension_pref_value_map_->GetEffectivePrefValue(pref_key,
1582 true,
1583 &has_incognito_pref_value);
1584 return has_incognito_pref_value;
1587 URLPatternSet ExtensionPrefs::GetAllowedInstallSites() {
1588 URLPatternSet result;
1589 const ListValue* list = prefs_->GetList(prefs::kExtensionAllowedInstallSites);
1590 CHECK(list);
1592 for (size_t i = 0; i < list->GetSize(); ++i) {
1593 std::string entry_string;
1594 URLPattern entry(URLPattern::SCHEME_ALL);
1595 if (!list->GetString(i, &entry_string) ||
1596 entry.Parse(entry_string) != URLPattern::PARSE_SUCCESS) {
1597 LOG(ERROR) << "Invalid value for preference: "
1598 << prefs::kExtensionAllowedInstallSites
1599 << "." << i;
1600 continue;
1602 result.AddPattern(entry);
1605 return result;
1608 const DictionaryValue* ExtensionPrefs::GetGeometryCache(
1609 const std::string& extension_id) const {
1610 const DictionaryValue* extension_prefs = GetExtensionPref(extension_id);
1611 if (!extension_prefs)
1612 return NULL;
1614 const DictionaryValue* ext = NULL;
1615 if (!extension_prefs->GetDictionary(kPrefGeometryCache, &ext))
1616 return NULL;
1618 return ext;
1621 void ExtensionPrefs::SetGeometryCache(
1622 const std::string& extension_id,
1623 scoped_ptr<DictionaryValue> cache) {
1624 UpdateExtensionPref(extension_id, kPrefGeometryCache, cache.release());
1627 bool ExtensionPrefs::GetLastChooseEntryDirectory(
1628 const std::string& extension_id, base::FilePath* result) const {
1629 const DictionaryValue* dictionary = GetExtensionPref(extension_id);
1630 if (!dictionary)
1631 return false;
1633 const Value* value;
1634 if (!dictionary->Get(kLastChooseEntryDirectory, &value))
1635 return false;
1637 return base::GetValueAsFilePath(*value, result);
1640 void ExtensionPrefs::SetLastChooseEntryDirectory(
1641 const std::string& extension_id, const base::FilePath& value) {
1642 UpdateExtensionPref(extension_id, kLastChooseEntryDirectory,
1643 base::CreateFilePathValue(value));
1646 ExtensionPrefs::ExtensionPrefs(
1647 PrefService* prefs,
1648 const base::FilePath& root_dir,
1649 ExtensionPrefValueMap* extension_pref_value_map,
1650 scoped_ptr<TimeProvider> time_provider,
1651 bool extensions_disabled)
1652 : prefs_(prefs),
1653 install_directory_(root_dir),
1654 extension_pref_value_map_(extension_pref_value_map),
1655 extension_sorting_(new ExtensionSorting(this)),
1656 content_settings_store_(new ContentSettingsStore()),
1657 time_provider_(time_provider.Pass()),
1658 extensions_disabled_(extensions_disabled) {
1659 MakePathsRelative();
1660 InitPrefStore();
1663 void ExtensionPrefs::SetNeedsStorageGarbageCollection(bool value) {
1664 prefs_->SetBoolean(prefs::kExtensionStorageGarbageCollect, value);
1667 bool ExtensionPrefs::NeedsStorageGarbageCollection() {
1668 return prefs_->GetBoolean(prefs::kExtensionStorageGarbageCollect);
1671 // static
1672 void ExtensionPrefs::RegisterUserPrefs(
1673 user_prefs::PrefRegistrySyncable* registry) {
1674 registry->RegisterDictionaryPref(
1675 kExtensionsPref, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1676 registry->RegisterListPref(prefs::kExtensionToolbar,
1677 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
1678 registry->RegisterIntegerPref(
1679 prefs::kExtensionToolbarSize,
1680 -1, // default value
1681 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1682 registry->RegisterDictionaryPref(
1683 kExtensionsBlacklistUpdate,
1684 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1685 registry->RegisterListPref(prefs::kExtensionInstallAllowList,
1686 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1687 registry->RegisterListPref(prefs::kExtensionInstallDenyList,
1688 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1689 registry->RegisterDictionaryPref(
1690 prefs::kExtensionInstallForceList,
1691 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1692 registry->RegisterListPref(prefs::kExtensionAllowedTypes,
1693 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1694 registry->RegisterStringPref(
1695 prefs::kExtensionBlacklistUpdateVersion,
1696 "0", // default value
1697 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1698 registry->RegisterBooleanPref(
1699 prefs::kExtensionStorageGarbageCollect,
1700 false, // default value
1701 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1702 registry->RegisterInt64Pref(
1703 prefs::kLastExtensionsUpdateCheck,
1704 0, // default value
1705 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1706 registry->RegisterInt64Pref(
1707 prefs::kNextExtensionsUpdateCheck,
1708 0, // default value
1709 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1710 registry->RegisterListPref(prefs::kExtensionAllowedInstallSites,
1711 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1712 registry->RegisterStringPref(
1713 kExtensionsLastChromeVersion,
1714 std::string(), // default value
1715 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1717 #if defined(TOOLKIT_VIEWS)
1718 registry->RegisterIntegerPref(
1719 prefs::kBrowserActionContainerWidth,
1721 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
1722 #endif
1725 ExtensionIdList ExtensionPrefs::GetExtensionPrefAsVector(
1726 const char* pref) {
1727 ExtensionIdList extension_ids;
1728 const ListValue* list_of_values = prefs_->GetList(pref);
1729 if (!list_of_values)
1730 return extension_ids;
1732 std::string extension_id;
1733 for (size_t i = 0; i < list_of_values->GetSize(); ++i) {
1734 if (list_of_values->GetString(i, &extension_id))
1735 extension_ids.push_back(extension_id);
1737 return extension_ids;
1740 void ExtensionPrefs::SetExtensionPrefFromVector(
1741 const char* pref,
1742 const ExtensionIdList& strings) {
1743 ListPrefUpdate update(prefs_, pref);
1744 ListValue* list_of_values = update.Get();
1745 list_of_values->Clear();
1746 for (ExtensionIdList::const_iterator iter = strings.begin();
1747 iter != strings.end(); ++iter)
1748 list_of_values->Append(new StringValue(*iter));
1751 void ExtensionPrefs::PopulateExtensionInfoPrefs(
1752 const Extension* extension,
1753 const base::Time install_time,
1754 Extension::State initial_state,
1755 DictionaryValue* extension_dict) {
1756 // Leave the state blank for component extensions so that old chrome versions
1757 // loading new profiles do not fail in GetInstalledExtensionInfo. Older
1758 // Chrome versions would only check for an omitted state.
1759 if (initial_state != Extension::ENABLED_COMPONENT)
1760 extension_dict->Set(kPrefState, Value::CreateIntegerValue(initial_state));
1762 extension_dict->Set(kPrefLocation,
1763 Value::CreateIntegerValue(extension->location()));
1764 extension_dict->Set(kPrefCreationFlags,
1765 Value::CreateIntegerValue(extension->creation_flags()));
1766 extension_dict->Set(kPrefFromWebStore,
1767 Value::CreateBooleanValue(extension->from_webstore()));
1768 extension_dict->Set(kPrefFromBookmark,
1769 Value::CreateBooleanValue(extension->from_bookmark()));
1770 extension_dict->Set(
1771 kPrefWasInstalledByDefault,
1772 Value::CreateBooleanValue(extension->was_installed_by_default()));
1773 extension_dict->Set(kPrefInstallTime,
1774 Value::CreateStringValue(
1775 base::Int64ToString(install_time.ToInternalValue())));
1777 base::FilePath::StringType path = MakePathRelative(install_directory_,
1778 extension->path());
1779 extension_dict->Set(kPrefPath, Value::CreateStringValue(path));
1780 // We store prefs about LOAD extensions, but don't cache their manifest
1781 // since it may change on disk.
1782 if (!Manifest::IsUnpackedLocation(extension->location())) {
1783 extension_dict->Set(kPrefManifest,
1784 extension->manifest()->value()->DeepCopy());
1788 void ExtensionPrefs::FinishExtensionInfoPrefs(
1789 const std::string& extension_id,
1790 const base::Time install_time,
1791 bool needs_sort_ordinal,
1792 const syncer::StringOrdinal& suggested_page_ordinal,
1793 DictionaryValue* extension_dict) {
1794 // Reinitializes various preferences with empty dictionaries.
1795 extension_dict->Set(pref_names::kPrefPreferences, new DictionaryValue);
1796 extension_dict->Set(pref_names::kPrefIncognitoPreferences,
1797 new DictionaryValue);
1798 extension_dict->Set(pref_names::kPrefRegularOnlyPreferences,
1799 new DictionaryValue);
1800 extension_dict->Set(pref_names::kPrefContentSettings, new ListValue);
1801 extension_dict->Set(pref_names::kPrefIncognitoContentSettings, new ListValue);
1803 // If this point has been reached, any pending installs should be considered
1804 // out of date.
1805 extension_dict->Remove(kDelayedInstallInfo, NULL);
1807 // Clear state that may be registered from a previous install.
1808 extension_dict->Remove(EventRouter::kRegisteredEvents, NULL);
1810 // FYI, all code below here races on sudden shutdown because
1811 // |extension_dict|, |extension_sorting_|, |extension_pref_value_map_|,
1812 // and |content_settings_store_| are updated non-transactionally. This is
1813 // probably not fixable without nested transactional updates to pref
1814 // dictionaries.
1815 if (needs_sort_ordinal) {
1816 extension_sorting_->EnsureValidOrdinals(extension_id,
1817 suggested_page_ordinal);
1820 bool is_enabled = false;
1821 int initial_state;
1822 if (extension_dict->GetInteger(kPrefState, &initial_state)) {
1823 is_enabled = initial_state == Extension::ENABLED;
1826 extension_pref_value_map_->RegisterExtension(extension_id, install_time,
1827 is_enabled);
1828 content_settings_store_->RegisterExtension(extension_id, install_time,
1829 is_enabled);
1832 } // namespace extensions