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"
40 #include "ash/shell.h"
43 #include "win8/util/win8_util.h"
47 using base::DictionaryValue
;
48 using base::ListValue
;
50 namespace extensions
{
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
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
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
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
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
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
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
{
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
);
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
) {
227 return ext
->GetBoolean(kPrefBlacklist
, &bool_value
) && bool_value
;
236 ExtensionPrefs::TimeProvider::TimeProvider() {
239 ExtensionPrefs::TimeProvider::~TimeProvider() {
242 base::Time
ExtensionPrefs::TimeProvider::GetCurrentTime() const {
243 return base::Time::Now();
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
),
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
)) {
273 return key_value
->GetType() == type_enum_value
?
274 static_cast<T
*>(key_value
) :
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
)) {
290 extension
->SetWithoutPathExpansion(key_
, value_as_t
);
292 CHECK(key_value
->GetType() == type_enum_value
);
293 value_as_t
= static_cast<T
*>(key_value
);
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
>;
308 ExtensionPrefs
* ExtensionPrefs::Create(
310 const base::FilePath
& root_dir
,
311 ExtensionPrefValueMap
* extension_pref_value_map
,
312 bool extensions_disabled
) {
313 return ExtensionPrefs::Create(prefs
,
315 extension_pref_value_map
,
317 make_scoped_ptr(new TimeProvider()));
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
,
330 extension_pref_value_map
,
331 time_provider
.Pass(),
332 extensions_disabled
));
333 return prefs
.release();
336 ExtensionPrefs::~ExtensionPrefs() {
340 ExtensionPrefs
* ExtensionPrefs::Get(Profile
* profile
) {
341 return ExtensionPrefsFactory::GetInstance()->GetForProfile(profile
);
345 const char ExtensionPrefs::kExtensionsPref
[] = "extensions.settings";
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);
363 void ExtensionPrefs::MakePathsRelative() {
364 const DictionaryValue
* dict
= prefs_
->GetDictionary(kExtensionsPref
);
365 if (!dict
|| dict
->empty())
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
))
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.
381 base::FilePath::StringType path_string
;
382 if (!extension_dict
->GetString(kPrefPath
, &path_string
))
384 base::FilePath
path(path_string
);
385 if (path
.IsAbsolute())
386 absolute_keys
.insert(i
.key());
388 if (absolute_keys
.empty())
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
;
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
;
414 !extensions
->GetDictionary(extension_id
, &extension_dict
)) {
417 return extension_dict
;
420 void ExtensionPrefs::UpdateExtensionPref(const std::string
& extension_id
,
421 const std::string
& key
,
423 if (!Extension::IdIsValid(extension_id
)) {
424 NOTREACHED() << "Invalid extension_id " << extension_id
;
427 ScopedExtensionPrefUpdate
update(prefs_
, extension_id
);
429 update
->Set(key
, data_value
);
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
))
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
))
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
))
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
))
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
))
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
,
508 const ListValue
* value
= NULL
;
509 if (!ReadPrefAsList(extension_id
, pref_key
, &value
))
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
))
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.
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());
579 DictionaryValue
* tmp
= new DictionaryValue();
580 tmp
->Set(i
->name(), detail
.release());
581 api_values
->Append(tmp
);
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
) {
606 ReadPrefAsInteger(extension_id
, kPrefAcknowledgePromptCount
, &count
);
608 UpdateExtensionPref(extension_id
, kPrefAcknowledgePromptCount
,
609 Value::CreateIntegerValue(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
)) {
655 prefs_
->SetBoolean(prefs::kExtensionAlertsInitializedPref
, true);
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
) {
678 if (ReadPrefAsInteger(extension_id
, kPrefDisableReasons
, &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
);
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
);
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();
722 if (IsBlacklistBitSet(static_cast<const DictionaryValue
*>(&it
.value())))
723 ids
.insert(it
.key());
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") <<
739 // Always make sure the "acknowledged" bit is cleared since the blacklist bit
741 UpdateExtensionPref(extension_id
, kPrefBlacklistAcknowledged
, NULL
);
743 if (is_blacklisted
) {
744 UpdateExtensionPref(extension_id
,
746 new base::FundamentalValue(true));
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
);
762 // Serializes |time| as a string value mapped to |key| in |dictionary|.
763 void SaveTime(DictionaryValue
* dictionary
,
765 const base::Time
& time
) {
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
) {
777 std::string string_value
;
779 if (dictionary
->GetString(key
, &string_value
)) {
780 if (base::StringToInt64(string_value
, &value
)) {
781 return base::Time::FromInternalValue(value
);
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
),
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
);
826 if (dictionary
&& dictionary
->GetBoolean(kActiveBit
, &result
))
831 void ExtensionPrefs::SetActiveBit(const std::string
& extension_id
,
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.
846 const DictionaryValue
* ext
= GetExtensionPref(*ext_id
);
847 if (!ext
|| !ext
->GetBoolean(kPrefOldGrantedFullAccess
, &full_access
))
850 // Remove the full access bit (empty list will get trimmed).
852 *ext_id
, kPrefOldGrantedFullAccess
, new ListValue());
854 // Add the plugin permission if the full access bit was set.
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();
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
878 const ListValue
* hosts
= NULL
;
879 std::string explicit_hosts
=
880 JoinPrefs(kPrefGrantedPermissions
, kPrefExplicitHosts
);
881 if (ext
->GetList(kPrefOldGrantedHosts
, &hosts
)) {
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
) {
896 if (ReadPrefAsInteger(*ext_id
, kDeprecatedPrefDisableReason
, &value
)) {
897 int new_value
= Extension::DISABLE_NONE
;
899 case Extension::DEPRECATED_DISABLE_USER_ACTION
:
900 new_value
= Extension::DISABLE_USER_ACTION
;
902 case Extension::DEPRECATED_DISABLE_PERMISSIONS_INCREASE
:
903 new_value
= Extension::DISABLE_PERMISSIONS_INCREASE
;
905 case Extension::DEPRECATED_DISABLE_RELOAD
:
906 new_value
= Extension::DISABLE_RELOAD
;
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
,
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
);
983 bool running
= false;
984 extension
->GetBoolean(kPrefRunning
, &running
);
988 void ExtensionPrefs::SetHasWindows(const std::string
& extension_id
,
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
);
998 bool has_windows
= false;
999 extension
->GetBoolean(kHasWindows
, &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
,
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
,
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
) {
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
);
1042 result
= default_pref_value
;
1045 if (ash::Shell::IsForcedMaximizeMode() &&
1046 (result
== LAUNCH_FULLSCREEN
|| result
== LAUNCH_WINDOW
))
1047 result
= LAUNCH_REGULAR
;
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
1053 if (!extension
->is_platform_app() && result
== LAUNCH_WINDOW
)
1054 result
= LAUNCH_REGULAR
;
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
;
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|
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
;
1103 // All other launch types (tab, pinned, fullscreen) are
1104 // implemented as tabs in a window.
1105 result
= extension_misc::LAUNCH_TAB
;
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
;
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
);
1133 if (!extension
|| !extension
->GetInteger(kPrefState
, &state
))
1136 if (state
< 0 || state
>= Extension::NUM_STATES
) {
1137 LOG(ERROR
) << "Bad pref 'state' for extension '" << id
<< "'";
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
,
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);
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
);
1208 return std::string();
1210 std::string version
;
1211 extension
->GetString(kPrefVersion
, &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
)
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
);
1237 return base::FilePath();
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 {
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
)) {
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
);
1291 !extensions
->GetDictionaryWithoutPathExpansion(extension_id
, &ext
))
1292 return scoped_ptr
<ExtensionInfo
>();
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()))
1319 scoped_ptr
<ExtensionInfo
> info
=
1320 GetInstalledExtensionInfo(extension_id
.key());
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()
1346 UpdateExtensionPref(extension
->id(), kDelayedInstallInfo
, extension_dict
);
1349 bool ExtensionPrefs::RemoveDelayedInstallInfo(
1350 const std::string
& extension_id
) {
1351 if (!GetExtensionPref(extension_id
))
1353 ScopedExtensionPrefUpdate
update(prefs_
, extension_id
);
1354 bool result
= update
->Remove(kDelayedInstallInfo
, NULL
);
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
)) {
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(
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
);
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()))
1418 scoped_ptr
<ExtensionInfo
> info
= GetDelayedInstallInfo(extension_id
.key());
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
))
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
))
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;
1473 dictionary
->GetBoolean(kPrefWasInstalledByDefault
, &result
))
1478 base::Time
ExtensionPrefs::GetInstallTime(
1479 const std::string
& extension_id
) const {
1480 const DictionaryValue
* extension
= GetExtensionPref(extension_id
);
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
) {
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
);
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();
1520 const DictionaryValue
* ext
= NULL
;
1521 if (!it
.value().GetAsDictionary(&ext
)) {
1522 NOTREACHED() << "Invalid pref for extension " << it
.key();
1525 if (!IsBlacklistBitSet(ext
))
1526 result
.push_back(it
.key());
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
,
1544 Value::CreateStringValue(base::Int64ToString(
1545 install_time
.ToInternalValue())));
1550 void ExtensionPrefs::InitPrefStore() {
1551 if (extensions_disabled_
) {
1552 extension_pref_value_map_
->NotifyInitializationCompleted();
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.
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
,
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
);
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
1602 result
.AddPattern(entry
);
1608 const DictionaryValue
* ExtensionPrefs::GetGeometryCache(
1609 const std::string
& extension_id
) const {
1610 const DictionaryValue
* extension_prefs
= GetExtensionPref(extension_id
);
1611 if (!extension_prefs
)
1614 const DictionaryValue
* ext
= NULL
;
1615 if (!extension_prefs
->GetDictionary(kPrefGeometryCache
, &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
);
1634 if (!dictionary
->Get(kLastChooseEntryDirectory
, &value
))
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(
1648 const base::FilePath
& root_dir
,
1649 ExtensionPrefValueMap
* extension_pref_value_map
,
1650 scoped_ptr
<TimeProvider
> time_provider
,
1651 bool extensions_disabled
)
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();
1663 void ExtensionPrefs::SetNeedsStorageGarbageCollection(bool value
) {
1664 prefs_
->SetBoolean(prefs::kExtensionStorageGarbageCollect
, value
);
1667 bool ExtensionPrefs::NeedsStorageGarbageCollection() {
1668 return prefs_
->GetBoolean(prefs::kExtensionStorageGarbageCollect
);
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
,
1705 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
1706 registry
->RegisterInt64Pref(
1707 prefs::kNextExtensionsUpdateCheck
,
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
);
1725 ExtensionIdList
ExtensionPrefs::GetExtensionPrefAsVector(
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(
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_
,
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
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
1815 if (needs_sort_ordinal
) {
1816 extension_sorting_
->EnsureValidOrdinals(extension_id
,
1817 suggested_page_ordinal
);
1820 bool is_enabled
= false;
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
,
1828 content_settings_store_
->RegisterExtension(extension_id
, install_time
,
1832 } // namespace extensions