summaryrefslogtreecommitdiffstats
path: root/extensions/browser/extension_prefs.cc
diff options
context:
space:
mode:
authorderat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-22 18:20:03 +0000
committerderat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-22 18:20:03 +0000
commit489db0845d8070c3882a945fed1108acfb170185 (patch)
treef0a3a145789a6ba18c8fa4ebb4e786ae9360d1e5 /extensions/browser/extension_prefs.cc
parenta78957254f0072472366a75531f7e585cb23ff2c (diff)
downloadchromium_src-489db0845d8070c3882a945fed1108acfb170185.zip
chromium_src-489db0845d8070c3882a945fed1108acfb170185.tar.gz
chromium_src-489db0845d8070c3882a945fed1108acfb170185.tar.bz2
Move ExtensionPrefs and friends to extensions/ directory.
Move ExtensionPrefs and related classes from chrome/browser/extensions/ to the top-level extensions/ directory. The following classes are moved: ExtensionPrefStore ExtensionPrefValueMap ExtensionPrefValueMapFactory ExtensionPrefs ExtensionPrefsFactory ExtensionScopedPref The TestExtensionPrefs helper class and the ExtensionPrefsTest unit tests remain in chrome/browser/extensions, since TestExtensionPrefs has a dependency on Chrome's PrefServiceSyncable that seems like it will be difficult to break (more explanation at https://codereview.chromium.org/108643002/). BUG=313284 TBR=sky@chromium.org,pam@chromium.org Review URL: https://codereview.chromium.org/46853004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@246373 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'extensions/browser/extension_prefs.cc')
-rw-r--r--extensions/browser/extension_prefs.cc1892
1 files changed, 1892 insertions, 0 deletions
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
new file mode 100644
index 0000000..8e56ed7
--- /dev/null
+++ b/extensions/browser/extension_prefs.cc
@@ -0,0 +1,1892 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/extension_prefs.h"
+
+#include <iterator>
+
+#include "base/command_line.h"
+#include "base/prefs/pref_notifier.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/value_conversions.h"
+#include "chrome/browser/extensions/api/content_settings/content_settings_store.h"
+#include "chrome/browser/extensions/api/preference/preference_api.h"
+#include "components/user_prefs/pref_registry_syncable.h"
+#include "extensions/browser/admin_policy.h"
+#include "extensions/browser/app_sorting.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_pref_store.h"
+#include "extensions/browser/extension_prefs_factory.h"
+#include "extensions/browser/pref_names.h"
+#include "extensions/common/feature_switch.h"
+#include "extensions/common/manifest.h"
+#include "extensions/common/permissions/permission_set.h"
+#include "extensions/common/permissions/permissions_info.h"
+#include "extensions/common/url_pattern.h"
+#include "extensions/common/user_script.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using base::Value;
+using base::DictionaryValue;
+using base::ListValue;
+
+namespace extensions {
+
+namespace {
+
+// Additional preferences keys, which are not needed by external clients.
+
+// True if this extension is running. Note this preference stops getting updated
+// during Chrome shutdown (and won't be updated on a browser crash) and so can
+// be used at startup to determine whether the extension was running when Chrome
+// was last terminated.
+const char kPrefRunning[] = "running";
+
+// Whether this extension had windows when it was last running.
+const char kIsActive[] = "is_active";
+
+// Where an extension was installed from. (see Manifest::Location)
+const char kPrefLocation[] = "location";
+
+// Enabled, disabled, killed, etc. (see Extension::State)
+const char kPrefState[] = "state";
+
+// The path to the current version's manifest file.
+const char kPrefPath[] = "path";
+
+// The dictionary containing the extension's manifest.
+const char kPrefManifest[] = "manifest";
+
+// The version number.
+const char kPrefVersion[] = "manifest.version";
+
+// Indicates whether an extension is blacklisted.
+const char kPrefBlacklist[] = "blacklist";
+
+// The count of how many times we prompted the user to acknowledge an
+// extension.
+const char kPrefAcknowledgePromptCount[] = "ack_prompt_count";
+
+// Indicates whether the user has acknowledged various types of extensions.
+const char kPrefExternalAcknowledged[] = "ack_external";
+const char kPrefBlacklistAcknowledged[] = "ack_blacklist";
+const char kPrefWipeoutAcknowledged[] = "ack_wiped";
+
+// Indicates whether the external extension was installed during the first
+// run of this profile.
+const char kPrefExternalInstallFirstRun[] = "external_first_run";
+
+// Indicates whether to show an install warning when the user enables.
+const char kExtensionDidEscalatePermissions[] = "install_warning_on_enable";
+
+// DO NOT USE, use kPrefDisableReasons instead.
+// Indicates whether the extension was updated while it was disabled.
+const char kDeprecatedPrefDisableReason[] = "disable_reason";
+
+// A bitmask of all the reasons an extension is disabled.
+const char kPrefDisableReasons[] = "disable_reasons";
+
+// The key for a serialized Time value indicating the start of the day (from the
+// server's perspective) an extension last included a "ping" parameter during
+// its update check.
+const char kLastPingDay[] = "lastpingday";
+
+// Similar to kLastPingDay, but for "active" instead of "rollcall" pings.
+const char kLastActivePingDay[] = "last_active_pingday";
+
+// A bit we use to keep track of whether we need to do an "active" ping.
+const char kActiveBit[] = "active_bit";
+
+// Path for settings specific to blacklist update.
+const char kExtensionsBlacklistUpdate[] = "extensions.blacklistupdate";
+
+// Path for the delayed install info dictionary preference. The actual string
+// value is a legacy artifact for when delayed installs only pertained to
+// updates that were waiting for idle.
+const char kDelayedInstallInfo[] = "idle_install_info";
+
+// Reason why the extension's install was delayed.
+const char kDelayedInstallReason[] = "delay_install_reason";
+
+// Path for the suggested page ordinal of a delayed extension install.
+const char kPrefSuggestedPageOrdinal[] = "suggested_page_ordinal";
+
+// A preference that, if true, will allow this extension to run in incognito
+// mode.
+const char kPrefIncognitoEnabled[] = "incognito";
+
+// A preference to control whether an extension is allowed to inject script in
+// pages with file URLs.
+const char kPrefAllowFileAccess[] = "newAllowFileAccess";
+// TODO(jstritar): As part of fixing http://crbug.com/91577, we revoked all
+// extension file access by renaming the pref. We should eventually clean up
+// the old flag and possibly go back to that name.
+// const char kPrefAllowFileAccessOld[] = "allowFileAccess";
+
+// A preference specifying if the user dragged the app on the NTP.
+const char kPrefUserDraggedApp[] = "user_dragged_app_ntp";
+
+// Preferences that hold which permissions the user has granted the extension.
+// We explicitly keep track of these so that extensions can contain unknown
+// permissions, for backwards compatibility reasons, and we can still prompt
+// the user to accept them once recognized. We store the active permission
+// permissions because they may differ from those defined in the manifest.
+const char kPrefActivePermissions[] = "active_permissions";
+const char kPrefGrantedPermissions[] = "granted_permissions";
+
+// The preference names for PermissionSet values.
+const char kPrefAPIs[] = "api";
+const char kPrefManifestPermissions[] = "manifest_permissions";
+const char kPrefExplicitHosts[] = "explicit_host";
+const char kPrefScriptableHosts[] = "scriptable_host";
+
+// The preference names for the old granted permissions scheme.
+const char kPrefOldGrantedFullAccess[] = "granted_permissions.full";
+const char kPrefOldGrantedHosts[] = "granted_permissions.host";
+const char kPrefOldGrantedAPIs[] = "granted_permissions.api";
+
+// A preference that indicates when an extension was installed.
+const char kPrefInstallTime[] = "install_time";
+
+// A preference which saves the creation flags for extensions.
+const char kPrefCreationFlags[] = "creation_flags";
+
+// A preference that indicates whether the extension was installed from the
+// Chrome Web Store.
+const char kPrefFromWebStore[] = "from_webstore";
+
+// A preference that indicates whether the extension was installed from a
+// mock App created from a bookmark.
+const char kPrefFromBookmark[] = "from_bookmark";
+
+// A preference that indicates whether the extension was installed as
+// default apps.
+const char kPrefWasInstalledByDefault[] = "was_installed_by_default";
+
+// Key for Geometry Cache preference.
+const char kPrefGeometryCache[] = "geometry_cache";
+
+// A preference that indicates when an extension is last launched.
+const char kPrefLastLaunchTime[] = "last_launch_time";
+
+// A list of installed ids and a signature.
+const char kInstallSignature[] = "extensions.install_signature";
+
+// Provider of write access to a dictionary storing extension prefs.
+class ScopedExtensionPrefUpdate : public DictionaryPrefUpdate {
+ public:
+ ScopedExtensionPrefUpdate(PrefService* service,
+ const std::string& extension_id) :
+ DictionaryPrefUpdate(service, pref_names::kExtensions),
+ extension_id_(extension_id) {}
+
+ virtual ~ScopedExtensionPrefUpdate() {
+ }
+
+ // DictionaryPrefUpdate overrides:
+ virtual base::DictionaryValue* Get() OVERRIDE {
+ base::DictionaryValue* dict = DictionaryPrefUpdate::Get();
+ base::DictionaryValue* extension = NULL;
+ if (!dict->GetDictionary(extension_id_, &extension)) {
+ // Extension pref does not exist, create it.
+ extension = new base::DictionaryValue();
+ dict->SetWithoutPathExpansion(extension_id_, extension);
+ }
+ return extension;
+ }
+
+ private:
+ const std::string extension_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedExtensionPrefUpdate);
+};
+
+std::string JoinPrefs(const std::string& parent, const char* child) {
+ return parent + "." + child;
+}
+
+// Checks if kPrefBlacklist is set to true in the base::DictionaryValue.
+// Return false if the value is false or kPrefBlacklist does not exist.
+// This is used to decide if an extension is blacklisted.
+bool IsBlacklistBitSet(const base::DictionaryValue* ext) {
+ bool bool_value;
+ return ext->GetBoolean(kPrefBlacklist, &bool_value) && bool_value;
+}
+
+} // namespace
+
+//
+// TimeProvider
+//
+
+ExtensionPrefs::TimeProvider::TimeProvider() {
+}
+
+ExtensionPrefs::TimeProvider::~TimeProvider() {
+}
+
+base::Time ExtensionPrefs::TimeProvider::GetCurrentTime() const {
+ return base::Time::Now();
+}
+
+//
+// ScopedUpdate
+//
+template <typename T, base::Value::Type type_enum_value>
+ExtensionPrefs::ScopedUpdate<T, type_enum_value>::ScopedUpdate(
+ ExtensionPrefs* prefs,
+ const std::string& extension_id,
+ const std::string& key)
+ : update_(prefs->pref_service(), pref_names::kExtensions),
+ extension_id_(extension_id),
+ key_(key) {
+ DCHECK(Extension::IdIsValid(extension_id_));
+}
+
+template <typename T, base::Value::Type type_enum_value>
+ExtensionPrefs::ScopedUpdate<T, type_enum_value>::~ScopedUpdate() {
+}
+
+template <typename T, base::Value::Type type_enum_value>
+T* ExtensionPrefs::ScopedUpdate<T, type_enum_value>::Get() {
+ base::DictionaryValue* dict = update_.Get();
+ base::DictionaryValue* extension = NULL;
+ base::Value* key_value = NULL;
+ if (!dict->GetDictionary(extension_id_, &extension) ||
+ !extension->Get(key_, &key_value)) {
+ return NULL;
+ }
+ return key_value->GetType() == type_enum_value ?
+ static_cast<T*>(key_value) :
+ NULL;
+}
+
+template <typename T, base::Value::Type type_enum_value>
+T* ExtensionPrefs::ScopedUpdate<T, type_enum_value>::Create() {
+ base::DictionaryValue* dict = update_.Get();
+ base::DictionaryValue* extension = NULL;
+ base::Value* key_value = NULL;
+ T* value_as_t = NULL;
+ if (!dict->GetDictionary(extension_id_, &extension)) {
+ extension = new base::DictionaryValue;
+ dict->SetWithoutPathExpansion(extension_id_, extension);
+ }
+ if (!extension->Get(key_, &key_value)) {
+ value_as_t = new T;
+ extension->SetWithoutPathExpansion(key_, value_as_t);
+ } else {
+ CHECK(key_value->GetType() == type_enum_value);
+ value_as_t = static_cast<T*>(key_value);
+ }
+ return value_as_t;
+}
+
+// Explicit instantiations for Dictionary and List value types.
+template class ExtensionPrefs::ScopedUpdate<base::DictionaryValue,
+ base::Value::TYPE_DICTIONARY>;
+template class ExtensionPrefs::ScopedUpdate<base::ListValue,
+ base::Value::TYPE_LIST>;
+
+//
+// ExtensionPrefs
+//
+
+// static
+ExtensionPrefs* ExtensionPrefs::Create(
+ PrefService* prefs,
+ const base::FilePath& root_dir,
+ ExtensionPrefValueMap* extension_pref_value_map,
+ scoped_ptr<AppSorting> app_sorting,
+ bool extensions_disabled) {
+ return ExtensionPrefs::Create(prefs,
+ root_dir,
+ extension_pref_value_map,
+ app_sorting.Pass(),
+ extensions_disabled,
+ make_scoped_ptr(new TimeProvider()));
+}
+
+// static
+ExtensionPrefs* ExtensionPrefs::Create(
+ PrefService* pref_service,
+ const base::FilePath& root_dir,
+ ExtensionPrefValueMap* extension_pref_value_map,
+ scoped_ptr<AppSorting> app_sorting,
+ bool extensions_disabled,
+ scoped_ptr<TimeProvider> time_provider) {
+ return new ExtensionPrefs(pref_service,
+ root_dir,
+ extension_pref_value_map,
+ app_sorting.Pass(),
+ time_provider.Pass(),
+ extensions_disabled);
+}
+
+ExtensionPrefs::~ExtensionPrefs() {
+}
+
+// static
+ExtensionPrefs* ExtensionPrefs::Get(content::BrowserContext* context) {
+ return ExtensionPrefsFactory::GetInstance()->GetForBrowserContext(context);
+}
+
+static base::FilePath::StringType MakePathRelative(const base::FilePath& parent,
+ const base::FilePath& child) {
+ if (!parent.IsParent(child))
+ return child.value();
+
+ base::FilePath::StringType retval = child.value().substr(
+ parent.value().length());
+ if (base::FilePath::IsSeparator(retval[0]))
+ return retval.substr(1);
+ else
+ return retval;
+}
+
+void ExtensionPrefs::MakePathsRelative() {
+ const base::DictionaryValue* dict =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ if (!dict || dict->empty())
+ return;
+
+ // Collect all extensions ids with absolute paths in |absolute_keys|.
+ std::set<std::string> absolute_keys;
+ for (base::DictionaryValue::Iterator i(*dict); !i.IsAtEnd(); i.Advance()) {
+ const base::DictionaryValue* extension_dict = NULL;
+ if (!i.value().GetAsDictionary(&extension_dict))
+ continue;
+ int location_value;
+ if (extension_dict->GetInteger(kPrefLocation, &location_value) &&
+ Manifest::IsUnpackedLocation(
+ static_cast<Manifest::Location>(location_value))) {
+ // Unpacked extensions can have absolute paths.
+ continue;
+ }
+ base::FilePath::StringType path_string;
+ if (!extension_dict->GetString(kPrefPath, &path_string))
+ continue;
+ base::FilePath path(path_string);
+ if (path.IsAbsolute())
+ absolute_keys.insert(i.key());
+ }
+ if (absolute_keys.empty())
+ return;
+
+ // Fix these paths.
+ DictionaryPrefUpdate update(prefs_, pref_names::kExtensions);
+ base::DictionaryValue* update_dict = update.Get();
+ for (std::set<std::string>::iterator i = absolute_keys.begin();
+ i != absolute_keys.end(); ++i) {
+ base::DictionaryValue* extension_dict = NULL;
+ if (!update_dict->GetDictionaryWithoutPathExpansion(*i, &extension_dict)) {
+ NOTREACHED() << "Control should never reach here for extension " << *i;
+ continue;
+ }
+ base::FilePath::StringType path_string;
+ extension_dict->GetString(kPrefPath, &path_string);
+ base::FilePath path(path_string);
+ extension_dict->SetString(kPrefPath,
+ MakePathRelative(install_directory_, path));
+ }
+}
+
+const base::DictionaryValue* ExtensionPrefs::GetExtensionPref(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* extensions =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ const base::DictionaryValue* extension_dict = NULL;
+ if (!extensions ||
+ !extensions->GetDictionary(extension_id, &extension_dict)) {
+ return NULL;
+ }
+ return extension_dict;
+}
+
+void ExtensionPrefs::UpdateExtensionPref(const std::string& extension_id,
+ const std::string& key,
+ base::Value* data_value) {
+ if (!Extension::IdIsValid(extension_id)) {
+ NOTREACHED() << "Invalid extension_id " << extension_id;
+ return;
+ }
+ ScopedExtensionPrefUpdate update(prefs_, extension_id);
+ if (data_value)
+ update->Set(key, data_value);
+ else
+ update->Remove(key, NULL);
+}
+
+void ExtensionPrefs::DeleteExtensionPrefs(const std::string& extension_id) {
+ extension_pref_value_map_->UnregisterExtension(extension_id);
+ content_settings_store_->UnregisterExtension(extension_id);
+ DictionaryPrefUpdate update(prefs_, pref_names::kExtensions);
+ base::DictionaryValue* dict = update.Get();
+ dict->Remove(extension_id, NULL);
+}
+
+bool ExtensionPrefs::ReadPrefAsBoolean(const std::string& extension_id,
+ const std::string& pref_key,
+ bool* out_value) const {
+ const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+ if (!ext || !ext->GetBoolean(pref_key, out_value))
+ return false;
+
+ return true;
+}
+
+bool ExtensionPrefs::ReadPrefAsInteger(const std::string& extension_id,
+ const std::string& pref_key,
+ int* out_value) const {
+ const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+ if (!ext || !ext->GetInteger(pref_key, out_value))
+ return false;
+
+ return true;
+}
+
+bool ExtensionPrefs::ReadPrefAsString(const std::string& extension_id,
+ const std::string& pref_key,
+ std::string* out_value) const {
+ const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+ if (!ext || !ext->GetString(pref_key, out_value))
+ return false;
+
+ return true;
+}
+
+bool ExtensionPrefs::ReadPrefAsList(const std::string& extension_id,
+ const std::string& pref_key,
+ const base::ListValue** out_value) const {
+ const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+ const base::ListValue* out = NULL;
+ if (!ext || !ext->GetList(pref_key, &out))
+ return false;
+ if (out_value)
+ *out_value = out;
+
+ return true;
+}
+
+bool ExtensionPrefs::ReadPrefAsDictionary(
+ const std::string& extension_id,
+ const std::string& pref_key,
+ const base::DictionaryValue** out_value) const {
+ const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+ const base::DictionaryValue* out = NULL;
+ if (!ext || !ext->GetDictionary(pref_key, &out))
+ return false;
+ if (out_value)
+ *out_value = out;
+
+ return true;
+}
+
+bool ExtensionPrefs::HasPrefForExtension(
+ const std::string& extension_id) const {
+ return GetExtensionPref(extension_id) != NULL;
+}
+
+bool ExtensionPrefs::ReadPrefAsURLPatternSet(const std::string& extension_id,
+ const std::string& pref_key,
+ URLPatternSet* result,
+ int valid_schemes) {
+ const base::ListValue* value = NULL;
+ if (!ReadPrefAsList(extension_id, pref_key, &value))
+ return false;
+
+ bool allow_file_access = AllowFileAccess(extension_id);
+ return result->Populate(*value, valid_schemes, allow_file_access, NULL);
+}
+
+void ExtensionPrefs::SetExtensionPrefURLPatternSet(
+ const std::string& extension_id,
+ const std::string& pref_key,
+ const URLPatternSet& new_value) {
+ UpdateExtensionPref(extension_id, pref_key, new_value.ToValue().release());
+}
+
+bool ExtensionPrefs::ReadPrefAsBooleanAndReturn(
+ const std::string& extension_id,
+ const std::string& pref_key) const {
+ bool out_value = false;
+ return ReadPrefAsBoolean(extension_id, pref_key, &out_value) && out_value;
+}
+
+PermissionSet* ExtensionPrefs::ReadPrefAsPermissionSet(
+ const std::string& extension_id,
+ const std::string& pref_key) {
+ if (!GetExtensionPref(extension_id))
+ return NULL;
+
+ // Retrieve the API permissions. Please refer SetExtensionPrefPermissionSet()
+ // for api_values format.
+ APIPermissionSet apis;
+ const base::ListValue* api_values = NULL;
+ std::string api_pref = JoinPrefs(pref_key, kPrefAPIs);
+ if (ReadPrefAsList(extension_id, api_pref, &api_values)) {
+ APIPermissionSet::ParseFromJSON(api_values,
+ APIPermissionSet::kAllowInternalPermissions,
+ &apis, NULL, NULL);
+ }
+
+ // Retrieve the Manifest Keys permissions. Please refer to
+ // |SetExtensionPrefPermissionSet| for manifest_permissions_values format.
+ ManifestPermissionSet manifest_permissions;
+ const base::ListValue* manifest_permissions_values = NULL;
+ std::string manifest_permission_pref =
+ JoinPrefs(pref_key, kPrefManifestPermissions);
+ if (ReadPrefAsList(extension_id, manifest_permission_pref,
+ &manifest_permissions_values)) {
+ ManifestPermissionSet::ParseFromJSON(
+ manifest_permissions_values, &manifest_permissions, NULL, NULL);
+ }
+
+ // Retrieve the explicit host permissions.
+ URLPatternSet explicit_hosts;
+ ReadPrefAsURLPatternSet(
+ extension_id, JoinPrefs(pref_key, kPrefExplicitHosts),
+ &explicit_hosts, Extension::kValidHostPermissionSchemes);
+
+ // Retrieve the scriptable host permissions.
+ URLPatternSet scriptable_hosts;
+ ReadPrefAsURLPatternSet(
+ extension_id, JoinPrefs(pref_key, kPrefScriptableHosts),
+ &scriptable_hosts, UserScript::ValidUserScriptSchemes());
+
+ return new PermissionSet(
+ apis, manifest_permissions, explicit_hosts, scriptable_hosts);
+}
+
+// Set the API or Manifest permissions.
+// The format of api_values is:
+// [ "permission_name1", // permissions do not support detail.
+// "permission_name2",
+// {"permission_name3": value },
+// // permission supports detail, permission detail will be stored in value.
+// ...
+// ]
+template<typename T>
+static base::ListValue* CreatePermissionList(const T& permissions) {
+ base::ListValue* values = new base::ListValue();
+ for (typename T::const_iterator i = permissions.begin();
+ i != permissions.end(); ++i) {
+ scoped_ptr<base::Value> detail(i->ToValue());
+ if (detail) {
+ base::DictionaryValue* tmp = new base::DictionaryValue();
+ tmp->Set(i->name(), detail.release());
+ values->Append(tmp);
+ } else {
+ values->Append(new base::StringValue(i->name()));
+ }
+ }
+ return values;
+}
+
+void ExtensionPrefs::SetExtensionPrefPermissionSet(
+ const std::string& extension_id,
+ const std::string& pref_key,
+ const PermissionSet* new_value) {
+ std::string api_pref = JoinPrefs(pref_key, kPrefAPIs);
+ base::ListValue* api_values = CreatePermissionList(new_value->apis());
+ UpdateExtensionPref(extension_id, api_pref, api_values);
+
+ std::string manifest_permissions_pref =
+ JoinPrefs(pref_key, kPrefManifestPermissions);
+ base::ListValue* manifest_permissions_values = CreatePermissionList(
+ new_value->manifest_permissions());
+ UpdateExtensionPref(extension_id,
+ manifest_permissions_pref,
+ manifest_permissions_values);
+
+ // Set the explicit host permissions.
+ if (!new_value->explicit_hosts().is_empty()) {
+ SetExtensionPrefURLPatternSet(extension_id,
+ JoinPrefs(pref_key, kPrefExplicitHosts),
+ new_value->explicit_hosts());
+ }
+
+ // Set the scriptable host permissions.
+ if (!new_value->scriptable_hosts().is_empty()) {
+ SetExtensionPrefURLPatternSet(extension_id,
+ JoinPrefs(pref_key, kPrefScriptableHosts),
+ new_value->scriptable_hosts());
+ }
+}
+
+int ExtensionPrefs::IncrementAcknowledgePromptCount(
+ const std::string& extension_id) {
+ int count = 0;
+ ReadPrefAsInteger(extension_id, kPrefAcknowledgePromptCount, &count);
+ ++count;
+ UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount,
+ new base::FundamentalValue(count));
+ return count;
+}
+
+bool ExtensionPrefs::IsExternalExtensionAcknowledged(
+ const std::string& extension_id) {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalAcknowledged);
+}
+
+void ExtensionPrefs::AcknowledgeExternalExtension(
+ const std::string& extension_id) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ UpdateExtensionPref(extension_id, kPrefExternalAcknowledged,
+ new base::FundamentalValue(true));
+ UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, NULL);
+}
+
+bool ExtensionPrefs::IsBlacklistedExtensionAcknowledged(
+ const std::string& extension_id) {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefBlacklistAcknowledged);
+}
+
+void ExtensionPrefs::AcknowledgeBlacklistedExtension(
+ const std::string& extension_id) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ UpdateExtensionPref(extension_id, kPrefBlacklistAcknowledged,
+ new base::FundamentalValue(true));
+ UpdateExtensionPref(extension_id, kPrefAcknowledgePromptCount, NULL);
+}
+
+bool ExtensionPrefs::IsExternalInstallFirstRun(
+ const std::string& extension_id) {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefExternalInstallFirstRun);
+}
+
+void ExtensionPrefs::SetExternalInstallFirstRun(
+ const std::string& extension_id) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ UpdateExtensionPref(extension_id, kPrefExternalInstallFirstRun,
+ new base::FundamentalValue(true));
+}
+
+bool ExtensionPrefs::HasWipeoutBeenAcknowledged(
+ const std::string& extension_id) {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefWipeoutAcknowledged);
+}
+
+void ExtensionPrefs::SetWipeoutAcknowledged(
+ const std::string& extension_id,
+ bool value) {
+ UpdateExtensionPref(extension_id, kPrefWipeoutAcknowledged,
+ value ? base::Value::CreateBooleanValue(value) : NULL);
+}
+
+bool ExtensionPrefs::SetAlertSystemFirstRun() {
+ if (prefs_->GetBoolean(pref_names::kAlertsInitialized)) {
+ return true;
+ }
+ prefs_->SetBoolean(pref_names::kAlertsInitialized, true);
+ return false;
+}
+
+bool ExtensionPrefs::ExtensionsBlacklistedByDefault() const {
+ return admin_policy::BlacklistedByDefault(
+ prefs_->GetList(pref_names::kInstallDenyList));
+}
+
+bool ExtensionPrefs::DidExtensionEscalatePermissions(
+ const std::string& extension_id) {
+ return ReadPrefAsBooleanAndReturn(extension_id,
+ kExtensionDidEscalatePermissions);
+}
+
+void ExtensionPrefs::SetDidExtensionEscalatePermissions(
+ const Extension* extension, bool did_escalate) {
+ UpdateExtensionPref(extension->id(), kExtensionDidEscalatePermissions,
+ new base::FundamentalValue(did_escalate));
+}
+
+int ExtensionPrefs::GetDisableReasons(const std::string& extension_id) const {
+ int value = -1;
+ if (ReadPrefAsInteger(extension_id, kPrefDisableReasons, &value) &&
+ value >= 0) {
+ return value;
+ }
+ return Extension::DISABLE_NONE;
+}
+
+void ExtensionPrefs::AddDisableReason(const std::string& extension_id,
+ Extension::DisableReason disable_reason) {
+ int new_value = GetDisableReasons(extension_id) |
+ static_cast<int>(disable_reason);
+ UpdateExtensionPref(extension_id, kPrefDisableReasons,
+ new base::FundamentalValue(new_value));
+}
+
+void ExtensionPrefs::RemoveDisableReason(
+ const std::string& extension_id,
+ Extension::DisableReason disable_reason) {
+ int new_value = GetDisableReasons(extension_id) &
+ ~static_cast<int>(disable_reason);
+ if (new_value == Extension::DISABLE_NONE) {
+ UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL);
+ } else {
+ UpdateExtensionPref(extension_id, kPrefDisableReasons,
+ new base::FundamentalValue(new_value));
+ }
+}
+
+void ExtensionPrefs::ClearDisableReasons(const std::string& extension_id) {
+ UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL);
+}
+
+std::set<std::string> ExtensionPrefs::GetBlacklistedExtensions() {
+ std::set<std::string> ids;
+
+ const base::DictionaryValue* extensions =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ if (!extensions)
+ return ids;
+
+ for (base::DictionaryValue::Iterator it(*extensions);
+ !it.IsAtEnd(); it.Advance()) {
+ if (!it.value().IsType(base::Value::TYPE_DICTIONARY)) {
+ NOTREACHED() << "Invalid pref for extension " << it.key();
+ continue;
+ }
+ if (IsBlacklistBitSet(
+ static_cast<const base::DictionaryValue*>(&it.value()))) {
+ ids.insert(it.key());
+ }
+ }
+
+ return ids;
+}
+
+void ExtensionPrefs::SetExtensionBlacklisted(const std::string& extension_id,
+ bool is_blacklisted) {
+ bool currently_blacklisted = IsExtensionBlacklisted(extension_id);
+ if (is_blacklisted == currently_blacklisted) {
+ NOTREACHED() << extension_id << " is " <<
+ (currently_blacklisted ? "already" : "not") <<
+ " blacklisted";
+ return;
+ }
+
+ // Always make sure the "acknowledged" bit is cleared since the blacklist bit
+ // is changing.
+ UpdateExtensionPref(extension_id, kPrefBlacklistAcknowledged, NULL);
+
+ if (is_blacklisted) {
+ UpdateExtensionPref(extension_id,
+ kPrefBlacklist,
+ new base::FundamentalValue(true));
+ } else {
+ UpdateExtensionPref(extension_id, kPrefBlacklist, NULL);
+ const base::DictionaryValue* dict = GetExtensionPref(extension_id);
+ if (dict && dict->empty())
+ DeleteExtensionPrefs(extension_id);
+ }
+}
+
+bool ExtensionPrefs::IsExtensionBlacklisted(const std::string& id) const {
+ const base::DictionaryValue* ext_prefs = GetExtensionPref(id);
+ return ext_prefs && IsBlacklistBitSet(ext_prefs);
+}
+
+namespace {
+
+// Serializes |time| as a string value mapped to |key| in |dictionary|.
+void SaveTime(base::DictionaryValue* dictionary,
+ const char* key,
+ const base::Time& time) {
+ if (!dictionary)
+ return;
+ std::string string_value = base::Int64ToString(time.ToInternalValue());
+ dictionary->SetString(key, string_value);
+}
+
+// The opposite of SaveTime. If |key| is not found, this returns an empty Time
+// (is_null() will return true).
+base::Time ReadTime(const base::DictionaryValue* dictionary, const char* key) {
+ if (!dictionary)
+ return base::Time();
+ std::string string_value;
+ int64 value;
+ if (dictionary->GetString(key, &string_value)) {
+ if (base::StringToInt64(string_value, &value)) {
+ return base::Time::FromInternalValue(value);
+ }
+ }
+ return base::Time();
+}
+
+} // namespace
+
+base::Time ExtensionPrefs::LastPingDay(const std::string& extension_id) const {
+ DCHECK(Extension::IdIsValid(extension_id));
+ return ReadTime(GetExtensionPref(extension_id), kLastPingDay);
+}
+
+void ExtensionPrefs::SetLastPingDay(const std::string& extension_id,
+ const base::Time& time) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ ScopedExtensionPrefUpdate update(prefs_, extension_id);
+ SaveTime(update.Get(), kLastPingDay, time);
+}
+
+base::Time ExtensionPrefs::BlacklistLastPingDay() const {
+ return ReadTime(prefs_->GetDictionary(kExtensionsBlacklistUpdate),
+ kLastPingDay);
+}
+
+void ExtensionPrefs::SetBlacklistLastPingDay(const base::Time& time) {
+ DictionaryPrefUpdate update(prefs_, kExtensionsBlacklistUpdate);
+ SaveTime(update.Get(), kLastPingDay, time);
+}
+
+base::Time ExtensionPrefs::LastActivePingDay(const std::string& extension_id) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ return ReadTime(GetExtensionPref(extension_id), kLastActivePingDay);
+}
+
+void ExtensionPrefs::SetLastActivePingDay(const std::string& extension_id,
+ const base::Time& time) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ ScopedExtensionPrefUpdate update(prefs_, extension_id);
+ SaveTime(update.Get(), kLastActivePingDay, time);
+}
+
+bool ExtensionPrefs::GetActiveBit(const std::string& extension_id) {
+ const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
+ bool result = false;
+ if (dictionary && dictionary->GetBoolean(kActiveBit, &result))
+ return result;
+ return false;
+}
+
+void ExtensionPrefs::SetActiveBit(const std::string& extension_id,
+ bool active) {
+ UpdateExtensionPref(extension_id, kActiveBit,
+ new base::FundamentalValue(active));
+}
+
+void ExtensionPrefs::MigratePermissions(const ExtensionIdList& extension_ids) {
+ PermissionsInfo* info = PermissionsInfo::GetInstance();
+ for (ExtensionIdList::const_iterator ext_id =
+ extension_ids.begin(); ext_id != extension_ids.end(); ++ext_id) {
+
+ // An extension's granted permissions need to be migrated if the
+ // full_access bit is present. This bit was always present in the previous
+ // scheme and is never present now.
+ bool full_access;
+ const base::DictionaryValue* ext = GetExtensionPref(*ext_id);
+ if (!ext || !ext->GetBoolean(kPrefOldGrantedFullAccess, &full_access))
+ continue;
+
+ // Remove the full access bit (empty list will get trimmed).
+ UpdateExtensionPref(
+ *ext_id, kPrefOldGrantedFullAccess, new base::ListValue());
+
+ // Add the plugin permission if the full access bit was set.
+ if (full_access) {
+ const base::ListValue* apis = NULL;
+ base::ListValue* new_apis = NULL;
+
+ std::string granted_apis =
+ JoinPrefs(kPrefGrantedPermissions, kPrefAPIs);
+ if (ext->GetList(kPrefOldGrantedAPIs, &apis))
+ new_apis = apis->DeepCopy();
+ else
+ new_apis = new base::ListValue();
+
+ std::string plugin_name = info->GetByID(
+ APIPermission::kPlugin)->name();
+ new_apis->Append(new base::StringValue(plugin_name));
+ UpdateExtensionPref(*ext_id, granted_apis, new_apis);
+ }
+
+ // The granted permissions originally only held the effective hosts,
+ // which are a combination of host and user script host permissions.
+ // We now maintain these lists separately. For migration purposes, it
+ // does not matter how we treat the old effective hosts as long as the
+ // new effective hosts will be the same, so we move them to explicit
+ // host permissions.
+ const base::ListValue* hosts = NULL;
+ std::string explicit_hosts =
+ JoinPrefs(kPrefGrantedPermissions, kPrefExplicitHosts);
+ if (ext->GetList(kPrefOldGrantedHosts, &hosts)) {
+ UpdateExtensionPref(
+ *ext_id, explicit_hosts, hosts->DeepCopy());
+
+ // We can get rid of the old one by setting it to an empty list.
+ UpdateExtensionPref(*ext_id, kPrefOldGrantedHosts, new base::ListValue());
+ }
+ }
+}
+
+void ExtensionPrefs::MigrateDisableReasons(
+ const ExtensionIdList& extension_ids) {
+ for (ExtensionIdList::const_iterator ext_id =
+ extension_ids.begin(); ext_id != extension_ids.end(); ++ext_id) {
+ int value = -1;
+ if (ReadPrefAsInteger(*ext_id, kDeprecatedPrefDisableReason, &value)) {
+ int new_value = Extension::DISABLE_NONE;
+ switch (value) {
+ case Extension::DEPRECATED_DISABLE_USER_ACTION:
+ new_value = Extension::DISABLE_USER_ACTION;
+ break;
+ case Extension::DEPRECATED_DISABLE_PERMISSIONS_INCREASE:
+ new_value = Extension::DISABLE_PERMISSIONS_INCREASE;
+ break;
+ case Extension::DEPRECATED_DISABLE_RELOAD:
+ new_value = Extension::DISABLE_RELOAD;
+ break;
+ }
+
+ UpdateExtensionPref(*ext_id, kPrefDisableReasons,
+ new base::FundamentalValue(new_value));
+ // Remove the old disable reason.
+ UpdateExtensionPref(*ext_id, kDeprecatedPrefDisableReason, NULL);
+ }
+ }
+}
+
+PermissionSet* ExtensionPrefs::GetGrantedPermissions(
+ const std::string& extension_id) {
+ CHECK(Extension::IdIsValid(extension_id));
+ return ReadPrefAsPermissionSet(extension_id, kPrefGrantedPermissions);
+}
+
+void ExtensionPrefs::AddGrantedPermissions(
+ const std::string& extension_id,
+ const PermissionSet* permissions) {
+ CHECK(Extension::IdIsValid(extension_id));
+
+ scoped_refptr<PermissionSet> granted_permissions(
+ GetGrantedPermissions(extension_id));
+
+ // The new granted permissions are the union of the already granted
+ // permissions and the newly granted permissions.
+ scoped_refptr<PermissionSet> new_perms(
+ PermissionSet::CreateUnion(
+ permissions, granted_permissions.get()));
+
+ SetExtensionPrefPermissionSet(
+ extension_id, kPrefGrantedPermissions, new_perms.get());
+}
+
+void ExtensionPrefs::RemoveGrantedPermissions(
+ const std::string& extension_id,
+ const PermissionSet* permissions) {
+ CHECK(Extension::IdIsValid(extension_id));
+
+ scoped_refptr<PermissionSet> granted_permissions(
+ GetGrantedPermissions(extension_id));
+
+ // The new granted permissions are the difference of the already granted
+ // permissions and the newly ungranted permissions.
+ scoped_refptr<PermissionSet> new_perms(
+ PermissionSet::CreateDifference(
+ granted_permissions.get(), permissions));
+
+ SetExtensionPrefPermissionSet(
+ extension_id, kPrefGrantedPermissions, new_perms.get());
+}
+
+PermissionSet* ExtensionPrefs::GetActivePermissions(
+ const std::string& extension_id) {
+ CHECK(Extension::IdIsValid(extension_id));
+ return ReadPrefAsPermissionSet(extension_id, kPrefActivePermissions);
+}
+
+void ExtensionPrefs::SetActivePermissions(
+ const std::string& extension_id,
+ const PermissionSet* permissions) {
+ SetExtensionPrefPermissionSet(
+ extension_id, kPrefActivePermissions, permissions);
+}
+
+void ExtensionPrefs::SetExtensionRunning(const std::string& extension_id,
+ bool is_running) {
+ base::Value* value = new base::FundamentalValue(is_running);
+ UpdateExtensionPref(extension_id, kPrefRunning, value);
+}
+
+bool ExtensionPrefs::IsExtensionRunning(const std::string& extension_id) {
+ const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+ if (!extension)
+ return false;
+ bool running = false;
+ extension->GetBoolean(kPrefRunning, &running);
+ return running;
+}
+
+void ExtensionPrefs::SetIsActive(const std::string& extension_id,
+ bool is_active) {
+ base::Value* value = new base::FundamentalValue(is_active);
+ UpdateExtensionPref(extension_id, kIsActive, value);
+}
+
+bool ExtensionPrefs::IsActive(const std::string& extension_id) {
+ const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+ if (!extension)
+ return false;
+ bool is_active = false;
+ extension->GetBoolean(kIsActive, &is_active);
+ return is_active;
+}
+
+bool ExtensionPrefs::IsIncognitoEnabled(const std::string& extension_id) const {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefIncognitoEnabled);
+}
+
+void ExtensionPrefs::SetIsIncognitoEnabled(const std::string& extension_id,
+ bool enabled) {
+ UpdateExtensionPref(extension_id, kPrefIncognitoEnabled,
+ new base::FundamentalValue(enabled));
+}
+
+bool ExtensionPrefs::AllowFileAccess(const std::string& extension_id) const {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefAllowFileAccess);
+}
+
+void ExtensionPrefs::SetAllowFileAccess(const std::string& extension_id,
+ bool allow) {
+ UpdateExtensionPref(extension_id, kPrefAllowFileAccess,
+ new base::FundamentalValue(allow));
+}
+
+bool ExtensionPrefs::HasAllowFileAccessSetting(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+ return ext && ext->HasKey(kPrefAllowFileAccess);
+}
+
+bool ExtensionPrefs::DoesExtensionHaveState(
+ const std::string& id, Extension::State check_state) const {
+ const base::DictionaryValue* extension = GetExtensionPref(id);
+ int state = -1;
+ if (!extension || !extension->GetInteger(kPrefState, &state))
+ return false;
+
+ if (state < 0 || state >= Extension::NUM_STATES) {
+ LOG(ERROR) << "Bad pref 'state' for extension '" << id << "'";
+ return false;
+ }
+
+ return state == check_state;
+}
+
+bool ExtensionPrefs::IsExternalExtensionUninstalled(
+ const std::string& id) const {
+ return DoesExtensionHaveState(id, Extension::EXTERNAL_EXTENSION_UNINSTALLED);
+}
+
+bool ExtensionPrefs::IsExtensionDisabled(
+ const std::string& id) const {
+ return DoesExtensionHaveState(id, Extension::DISABLED);
+}
+
+ExtensionIdList ExtensionPrefs::GetToolbarOrder() {
+ ExtensionIdList id_list_out;
+ GetUserExtensionPrefIntoContainer(pref_names::kToolbar, &id_list_out);
+ return id_list_out;
+}
+
+void ExtensionPrefs::SetToolbarOrder(const ExtensionIdList& extension_ids) {
+ SetExtensionPrefFromContainer(pref_names::kToolbar, extension_ids);
+}
+
+bool ExtensionPrefs::GetKnownDisabled(ExtensionIdSet* id_set_out) {
+ return GetUserExtensionPrefIntoContainer(pref_names::kKnownDisabled,
+ id_set_out);
+}
+
+void ExtensionPrefs::SetKnownDisabled(const ExtensionIdSet& extension_ids) {
+ SetExtensionPrefFromContainer(pref_names::kKnownDisabled, extension_ids);
+}
+
+void ExtensionPrefs::OnExtensionInstalled(
+ const Extension* extension,
+ Extension::State initial_state,
+ bool blacklisted_for_malware,
+ const syncer::StringOrdinal& page_ordinal) {
+ ScopedExtensionPrefUpdate update(prefs_, extension->id());
+ base::DictionaryValue* extension_dict = update.Get();
+ const base::Time install_time = time_provider_->GetCurrentTime();
+ PopulateExtensionInfoPrefs(extension, install_time, initial_state,
+ blacklisted_for_malware, extension_dict);
+ FinishExtensionInfoPrefs(extension->id(), install_time,
+ extension->RequiresSortOrdinal(),
+ page_ordinal, extension_dict);
+}
+
+void ExtensionPrefs::OnExtensionUninstalled(const std::string& extension_id,
+ const Manifest::Location& location,
+ bool external_uninstall) {
+ app_sorting_->ClearOrdinals(extension_id);
+
+ // For external extensions, we save a preference reminding ourself not to try
+ // and install the extension anymore (except when |external_uninstall| is
+ // true, which signifies that the registry key was deleted or the pref file
+ // no longer lists the extension).
+ if (!external_uninstall && Manifest::IsExternalLocation(location)) {
+ UpdateExtensionPref(extension_id, kPrefState,
+ new base::FundamentalValue(
+ Extension::EXTERNAL_EXTENSION_UNINSTALLED));
+ extension_pref_value_map_->SetExtensionState(extension_id, false);
+ content_settings_store_->SetExtensionState(extension_id, false);
+ } else {
+ DeleteExtensionPrefs(extension_id);
+ }
+}
+
+void ExtensionPrefs::SetExtensionState(const std::string& extension_id,
+ Extension::State state) {
+ UpdateExtensionPref(extension_id, kPrefState,
+ new base::FundamentalValue(state));
+ bool enabled = (state == Extension::ENABLED);
+ extension_pref_value_map_->SetExtensionState(extension_id, enabled);
+ content_settings_store_->SetExtensionState(extension_id, enabled);
+}
+
+std::string ExtensionPrefs::GetVersionString(const std::string& extension_id) {
+ const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+ if (!extension)
+ return std::string();
+
+ std::string version;
+ extension->GetString(kPrefVersion, &version);
+
+ return version;
+}
+
+void ExtensionPrefs::UpdateManifest(const Extension* extension) {
+ if (!Manifest::IsUnpackedLocation(extension->location())) {
+ const base::DictionaryValue* extension_dict =
+ GetExtensionPref(extension->id());
+ if (!extension_dict)
+ return;
+ const base::DictionaryValue* old_manifest = NULL;
+ bool update_required =
+ !extension_dict->GetDictionary(kPrefManifest, &old_manifest) ||
+ !extension->manifest()->value()->Equals(old_manifest);
+ if (update_required) {
+ UpdateExtensionPref(extension->id(), kPrefManifest,
+ extension->manifest()->value()->DeepCopy());
+ }
+ }
+}
+
+base::FilePath ExtensionPrefs::GetExtensionPath(
+ const std::string& extension_id) {
+ const base::DictionaryValue* dict = GetExtensionPref(extension_id);
+ if (!dict)
+ return base::FilePath();
+
+ std::string path;
+ if (!dict->GetString(kPrefPath, &path))
+ return base::FilePath();
+
+ return install_directory_.Append(base::FilePath::FromUTF8Unsafe(path));
+}
+
+scoped_ptr<ExtensionInfo> ExtensionPrefs::GetInstalledInfoHelper(
+ const std::string& extension_id,
+ const base::DictionaryValue* extension) const {
+ int location_value;
+ if (!extension->GetInteger(kPrefLocation, &location_value))
+ return scoped_ptr<ExtensionInfo>();
+
+ base::FilePath::StringType path;
+ if (!extension->GetString(kPrefPath, &path))
+ return scoped_ptr<ExtensionInfo>();
+
+ // Make path absolute. Unpacked extensions will already have absolute paths,
+ // otherwise make it so.
+ Manifest::Location location = static_cast<Manifest::Location>(location_value);
+ if (!Manifest::IsUnpackedLocation(location)) {
+ DCHECK(location == Manifest::COMPONENT ||
+ !base::FilePath(path).IsAbsolute());
+ path = install_directory_.Append(path).value();
+ }
+
+ // Only the following extension types have data saved in the preferences.
+ if (location != Manifest::INTERNAL &&
+ !Manifest::IsUnpackedLocation(location) &&
+ !Manifest::IsExternalLocation(location)) {
+ NOTREACHED();
+ return scoped_ptr<ExtensionInfo>();
+ }
+
+ const base::DictionaryValue* manifest = NULL;
+ if (!Manifest::IsUnpackedLocation(location) &&
+ !extension->GetDictionary(kPrefManifest, &manifest)) {
+ LOG(WARNING) << "Missing manifest for extension " << extension_id;
+ // Just a warning for now.
+ }
+
+ return scoped_ptr<ExtensionInfo>(new ExtensionInfo(
+ manifest, extension_id, base::FilePath(path), location));
+}
+
+scoped_ptr<ExtensionInfo> ExtensionPrefs::GetInstalledExtensionInfo(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* ext = NULL;
+ const base::DictionaryValue* extensions =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ if (!extensions ||
+ !extensions->GetDictionaryWithoutPathExpansion(extension_id, &ext))
+ return scoped_ptr<ExtensionInfo>();
+ int state_value;
+ if (!ext->GetInteger(kPrefState, &state_value) ||
+ state_value == Extension::ENABLED_COMPONENT) {
+ // Old preferences files may not have kPrefState for component extensions.
+ return scoped_ptr<ExtensionInfo>();
+ }
+
+ if (state_value == Extension::EXTERNAL_EXTENSION_UNINSTALLED) {
+ LOG(WARNING) << "External extension with id " << extension_id
+ << " has been uninstalled by the user";
+ return scoped_ptr<ExtensionInfo>();
+ }
+
+ return GetInstalledInfoHelper(extension_id, ext);
+}
+
+scoped_ptr<ExtensionPrefs::ExtensionsInfo>
+ExtensionPrefs::GetInstalledExtensionsInfo() const {
+ scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
+
+ const base::DictionaryValue* extensions =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ for (base::DictionaryValue::Iterator extension_id(*extensions);
+ !extension_id.IsAtEnd(); extension_id.Advance()) {
+ if (!Extension::IdIsValid(extension_id.key()))
+ continue;
+
+ scoped_ptr<ExtensionInfo> info =
+ GetInstalledExtensionInfo(extension_id.key());
+ if (info)
+ extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
+ }
+
+ return extensions_info.Pass();
+}
+
+scoped_ptr<ExtensionPrefs::ExtensionsInfo>
+ExtensionPrefs::GetUninstalledExtensionsInfo() const {
+ scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
+
+ const base::DictionaryValue* extensions =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ for (base::DictionaryValue::Iterator extension_id(*extensions);
+ !extension_id.IsAtEnd(); extension_id.Advance()) {
+ const base::DictionaryValue* ext = NULL;
+ if (!Extension::IdIsValid(extension_id.key()) ||
+ !IsExternalExtensionUninstalled(extension_id.key()) ||
+ !extension_id.value().GetAsDictionary(&ext))
+ continue;
+
+ scoped_ptr<ExtensionInfo> info =
+ GetInstalledInfoHelper(extension_id.key(), ext);
+ if (info)
+ extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
+ }
+
+ return extensions_info.Pass();
+}
+
+void ExtensionPrefs::SetDelayedInstallInfo(
+ const Extension* extension,
+ Extension::State initial_state,
+ bool blacklisted_for_malware,
+ DelayReason delay_reason,
+ const syncer::StringOrdinal& page_ordinal) {
+ base::DictionaryValue* extension_dict = new base::DictionaryValue();
+ PopulateExtensionInfoPrefs(extension, time_provider_->GetCurrentTime(),
+ initial_state, blacklisted_for_malware,
+ extension_dict);
+
+ // Add transient data that is needed by FinishDelayedInstallInfo(), but
+ // should not be in the final extension prefs. All entries here should have
+ // a corresponding Remove() call in FinishDelayedInstallInfo().
+ if (extension->RequiresSortOrdinal()) {
+ extension_dict->SetString(
+ kPrefSuggestedPageOrdinal,
+ page_ordinal.IsValid() ? page_ordinal.ToInternalValue()
+ : std::string());
+ }
+ extension_dict->SetInteger(kDelayedInstallReason,
+ static_cast<int>(delay_reason));
+
+ UpdateExtensionPref(extension->id(), kDelayedInstallInfo, extension_dict);
+}
+
+bool ExtensionPrefs::RemoveDelayedInstallInfo(
+ const std::string& extension_id) {
+ if (!GetExtensionPref(extension_id))
+ return false;
+ ScopedExtensionPrefUpdate update(prefs_, extension_id);
+ bool result = update->Remove(kDelayedInstallInfo, NULL);
+ return result;
+}
+
+bool ExtensionPrefs::FinishDelayedInstallInfo(
+ const std::string& extension_id) {
+ CHECK(Extension::IdIsValid(extension_id));
+ ScopedExtensionPrefUpdate update(prefs_, extension_id);
+ base::DictionaryValue* extension_dict = update.Get();
+ base::DictionaryValue* pending_install_dict = NULL;
+ if (!extension_dict->GetDictionary(kDelayedInstallInfo,
+ &pending_install_dict)) {
+ return false;
+ }
+
+ // Retrieve and clear transient values populated by SetDelayedInstallInfo().
+ // Also do any other data cleanup that makes sense.
+ std::string serialized_ordinal;
+ syncer::StringOrdinal suggested_page_ordinal;
+ bool needs_sort_ordinal = false;
+ if (pending_install_dict->GetString(kPrefSuggestedPageOrdinal,
+ &serialized_ordinal)) {
+ suggested_page_ordinal = syncer::StringOrdinal(serialized_ordinal);
+ needs_sort_ordinal = true;
+ pending_install_dict->Remove(kPrefSuggestedPageOrdinal, NULL);
+ }
+ pending_install_dict->Remove(kDelayedInstallReason, NULL);
+
+ const base::Time install_time = time_provider_->GetCurrentTime();
+ pending_install_dict->Set(
+ kPrefInstallTime,
+ new base::StringValue(
+ base::Int64ToString(install_time.ToInternalValue())));
+
+ // Commit the delayed install data.
+ for (base::DictionaryValue::Iterator it(*pending_install_dict); !it.IsAtEnd();
+ it.Advance()) {
+ extension_dict->Set(it.key(), it.value().DeepCopy());
+ }
+ FinishExtensionInfoPrefs(extension_id, install_time, needs_sort_ordinal,
+ suggested_page_ordinal, extension_dict);
+ return true;
+}
+
+scoped_ptr<ExtensionInfo> ExtensionPrefs::GetDelayedInstallInfo(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* extension_prefs =
+ GetExtensionPref(extension_id);
+ if (!extension_prefs)
+ return scoped_ptr<ExtensionInfo>();
+
+ const base::DictionaryValue* ext = NULL;
+ if (!extension_prefs->GetDictionary(kDelayedInstallInfo, &ext))
+ return scoped_ptr<ExtensionInfo>();
+
+ return GetInstalledInfoHelper(extension_id, ext);
+}
+
+ExtensionPrefs::DelayReason ExtensionPrefs::GetDelayedInstallReason(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* extension_prefs =
+ GetExtensionPref(extension_id);
+ if (!extension_prefs)
+ return DELAY_REASON_NONE;
+
+ const base::DictionaryValue* ext = NULL;
+ if (!extension_prefs->GetDictionary(kDelayedInstallInfo, &ext))
+ return DELAY_REASON_NONE;
+
+ int delay_reason;
+ if (!ext->GetInteger(kDelayedInstallReason, &delay_reason))
+ return DELAY_REASON_NONE;
+
+ return static_cast<DelayReason>(delay_reason);
+}
+
+scoped_ptr<ExtensionPrefs::ExtensionsInfo> ExtensionPrefs::
+ GetAllDelayedInstallInfo() const {
+ scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
+
+ const base::DictionaryValue* extensions =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ for (base::DictionaryValue::Iterator extension_id(*extensions);
+ !extension_id.IsAtEnd(); extension_id.Advance()) {
+ if (!Extension::IdIsValid(extension_id.key()))
+ continue;
+
+ scoped_ptr<ExtensionInfo> info = GetDelayedInstallInfo(extension_id.key());
+ if (info)
+ extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
+ }
+
+ return extensions_info.Pass();
+}
+
+bool ExtensionPrefs::WasAppDraggedByUser(const std::string& extension_id) {
+ return ReadPrefAsBooleanAndReturn(extension_id, kPrefUserDraggedApp);
+}
+
+void ExtensionPrefs::SetAppDraggedByUser(const std::string& extension_id) {
+ UpdateExtensionPref(extension_id, kPrefUserDraggedApp,
+ new base::FundamentalValue(true));
+}
+
+bool ExtensionPrefs::IsFromWebStore(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
+ bool result = false;
+ if (dictionary && dictionary->GetBoolean(kPrefFromWebStore, &result))
+ return result;
+ return false;
+}
+
+bool ExtensionPrefs::IsFromBookmark(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
+ bool result = false;
+ if (dictionary && dictionary->GetBoolean(kPrefFromBookmark, &result))
+ return result;
+ return false;
+}
+
+int ExtensionPrefs::GetCreationFlags(const std::string& extension_id) const {
+ int creation_flags = Extension::NO_FLAGS;
+ if (!ReadPrefAsInteger(extension_id, kPrefCreationFlags, &creation_flags)) {
+ // Since kPrefCreationFlags was added later, it will be missing for
+ // previously installed extensions.
+ if (IsFromBookmark(extension_id))
+ creation_flags |= Extension::FROM_BOOKMARK;
+ if (IsFromWebStore(extension_id))
+ creation_flags |= Extension::FROM_WEBSTORE;
+ if (WasInstalledByDefault(extension_id))
+ creation_flags |= Extension::WAS_INSTALLED_BY_DEFAULT;
+ }
+ return creation_flags;
+}
+
+int ExtensionPrefs::GetDelayedInstallCreationFlags(
+ const std::string& extension_id) const {
+ int creation_flags = Extension::NO_FLAGS;
+ const base::DictionaryValue* delayed_info = NULL;
+ if (ReadPrefAsDictionary(extension_id, kDelayedInstallInfo, &delayed_info)) {
+ delayed_info->GetInteger(kPrefCreationFlags, &creation_flags);
+ }
+ return creation_flags;
+}
+
+bool ExtensionPrefs::WasInstalledByDefault(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
+ bool result = false;
+ if (dictionary &&
+ dictionary->GetBoolean(kPrefWasInstalledByDefault, &result))
+ return result;
+ return false;
+}
+
+base::Time ExtensionPrefs::GetInstallTime(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+ if (!extension) {
+ NOTREACHED();
+ return base::Time();
+ }
+ std::string install_time_str;
+ if (!extension->GetString(kPrefInstallTime, &install_time_str))
+ return base::Time();
+ int64 install_time_i64 = 0;
+ if (!base::StringToInt64(install_time_str, &install_time_i64))
+ return base::Time();
+ return base::Time::FromInternalValue(install_time_i64);
+}
+
+base::Time ExtensionPrefs::GetLastLaunchTime(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+ if (!extension)
+ return base::Time();
+
+ std::string launch_time_str;
+ if (!extension->GetString(kPrefLastLaunchTime, &launch_time_str))
+ return base::Time();
+ int64 launch_time_i64 = 0;
+ if (!base::StringToInt64(launch_time_str, &launch_time_i64))
+ return base::Time();
+ return base::Time::FromInternalValue(launch_time_i64);
+}
+
+void ExtensionPrefs::SetLastLaunchTime(const std::string& extension_id,
+ const base::Time& time) {
+ DCHECK(Extension::IdIsValid(extension_id));
+ ScopedExtensionPrefUpdate update(prefs_, extension_id);
+ SaveTime(update.Get(), kPrefLastLaunchTime, time);
+}
+
+void ExtensionPrefs::GetExtensions(ExtensionIdList* out) {
+ CHECK(out);
+
+ scoped_ptr<ExtensionsInfo> extensions_info(GetInstalledExtensionsInfo());
+
+ for (size_t i = 0; i < extensions_info->size(); ++i) {
+ ExtensionInfo* info = extensions_info->at(i).get();
+ out->push_back(info->extension_id);
+ }
+}
+
+// static
+ExtensionIdList ExtensionPrefs::GetExtensionsFrom(
+ const PrefService* pref_service) {
+ ExtensionIdList result;
+
+ const base::DictionaryValue* extension_prefs = NULL;
+ const base::Value* extension_prefs_value =
+ pref_service->GetUserPrefValue(pref_names::kExtensions);
+ if (!extension_prefs_value ||
+ !extension_prefs_value->GetAsDictionary(&extension_prefs)) {
+ return result; // Empty set
+ }
+
+ for (base::DictionaryValue::Iterator it(*extension_prefs); !it.IsAtEnd();
+ it.Advance()) {
+ const base::DictionaryValue* ext = NULL;
+ if (!it.value().GetAsDictionary(&ext)) {
+ NOTREACHED() << "Invalid pref for extension " << it.key();
+ continue;
+ }
+ if (!IsBlacklistBitSet(ext))
+ result.push_back(it.key());
+ }
+ return result;
+}
+
+void ExtensionPrefs::FixMissingPrefs(const ExtensionIdList& extension_ids) {
+ // Fix old entries that did not get an installation time entry when they
+ // were installed or don't have a preferences field.
+ for (ExtensionIdList::const_iterator ext_id = extension_ids.begin();
+ ext_id != extension_ids.end(); ++ext_id) {
+ if (GetInstallTime(*ext_id) == base::Time()) {
+ VLOG(1) << "Could not parse installation time of extension "
+ << *ext_id << ". It was probably installed before setting "
+ << kPrefInstallTime << " was introduced. Updating "
+ << kPrefInstallTime << " to the current time.";
+ const base::Time install_time = time_provider_->GetCurrentTime();
+ UpdateExtensionPref(*ext_id,
+ kPrefInstallTime,
+ new base::StringValue(base::Int64ToString(
+ install_time.ToInternalValue())));
+ }
+ }
+}
+
+void ExtensionPrefs::InitPrefStore() {
+ if (extensions_disabled_) {
+ extension_pref_value_map_->NotifyInitializationCompleted();
+ return;
+ }
+
+ // When this is called, the PrefService is initialized and provides access
+ // to the user preferences stored in a JSON file.
+ ExtensionIdList extension_ids;
+ GetExtensions(&extension_ids);
+ // Create empty preferences dictionary for each extension (these dictionaries
+ // are pruned when persisting the preferences to disk).
+ for (ExtensionIdList::iterator ext_id = extension_ids.begin();
+ ext_id != extension_ids.end(); ++ext_id) {
+ ScopedExtensionPrefUpdate update(prefs_, *ext_id);
+ // This creates an empty dictionary if none is stored.
+ update.Get();
+ }
+
+ FixMissingPrefs(extension_ids);
+ MigratePermissions(extension_ids);
+ MigrateDisableReasons(extension_ids);
+ app_sorting_->Initialize(extension_ids);
+
+ PreferenceAPI::InitExtensionControlledPrefs(this, extension_pref_value_map_);
+
+ extension_pref_value_map_->NotifyInitializationCompleted();
+}
+
+bool ExtensionPrefs::HasIncognitoPrefValue(const std::string& pref_key) {
+ bool has_incognito_pref_value = false;
+ extension_pref_value_map_->GetEffectivePrefValue(pref_key,
+ true,
+ &has_incognito_pref_value);
+ return has_incognito_pref_value;
+}
+
+URLPatternSet ExtensionPrefs::GetAllowedInstallSites() {
+ URLPatternSet result;
+ const base::ListValue* list =
+ prefs_->GetList(pref_names::kAllowedInstallSites);
+ CHECK(list);
+
+ for (size_t i = 0; i < list->GetSize(); ++i) {
+ std::string entry_string;
+ URLPattern entry(URLPattern::SCHEME_ALL);
+ if (!list->GetString(i, &entry_string) ||
+ entry.Parse(entry_string) != URLPattern::PARSE_SUCCESS) {
+ LOG(ERROR) << "Invalid value for preference: "
+ << pref_names::kAllowedInstallSites << "." << i;
+ continue;
+ }
+ result.AddPattern(entry);
+ }
+
+ return result;
+}
+
+const base::DictionaryValue* ExtensionPrefs::GetGeometryCache(
+ const std::string& extension_id) const {
+ const base::DictionaryValue* extension_prefs = GetExtensionPref(extension_id);
+ if (!extension_prefs)
+ return NULL;
+
+ const base::DictionaryValue* ext = NULL;
+ if (!extension_prefs->GetDictionary(kPrefGeometryCache, &ext))
+ return NULL;
+
+ return ext;
+}
+
+void ExtensionPrefs::SetGeometryCache(
+ const std::string& extension_id,
+ scoped_ptr<base::DictionaryValue> cache) {
+ UpdateExtensionPref(extension_id, kPrefGeometryCache, cache.release());
+}
+
+const base::DictionaryValue* ExtensionPrefs::GetInstallSignature() {
+ return prefs_->GetDictionary(kInstallSignature);
+}
+
+void ExtensionPrefs::SetInstallSignature(
+ const base::DictionaryValue* signature) {
+ if (signature) {
+ prefs_->Set(kInstallSignature, *signature);
+ DVLOG(1) << "SetInstallSignature - saving";
+ } else {
+ DVLOG(1) << "SetInstallSignature - clearing";
+ prefs_->ClearPref(kInstallSignature);
+ }
+}
+
+
+ExtensionPrefs::ExtensionPrefs(
+ PrefService* prefs,
+ const base::FilePath& root_dir,
+ ExtensionPrefValueMap* extension_pref_value_map,
+ scoped_ptr<AppSorting> app_sorting,
+ scoped_ptr<TimeProvider> time_provider,
+ bool extensions_disabled)
+ : prefs_(prefs),
+ install_directory_(root_dir),
+ extension_pref_value_map_(extension_pref_value_map),
+ app_sorting_(app_sorting.Pass()),
+ content_settings_store_(new ContentSettingsStore()),
+ time_provider_(time_provider.Pass()),
+ extensions_disabled_(extensions_disabled) {
+ app_sorting_->SetExtensionScopedPrefs(this);
+ MakePathsRelative();
+ InitPrefStore();
+}
+
+void ExtensionPrefs::SetNeedsStorageGarbageCollection(bool value) {
+ prefs_->SetBoolean(pref_names::kStorageGarbageCollect, value);
+}
+
+bool ExtensionPrefs::NeedsStorageGarbageCollection() {
+ return prefs_->GetBoolean(pref_names::kStorageGarbageCollect);
+}
+
+// static
+void ExtensionPrefs::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterDictionaryPref(
+ pref_names::kExtensions,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kToolbar,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+ registry->RegisterIntegerPref(
+ pref_names::kToolbarSize,
+ -1, // default value
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterDictionaryPref(
+ kExtensionsBlacklistUpdate,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kInstallAllowList,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kInstallDenyList,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterDictionaryPref(
+ pref_names::kInstallForceList,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kAllowedTypes,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterBooleanPref(
+ pref_names::kStorageGarbageCollect,
+ false, // default value
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterInt64Pref(
+ pref_names::kLastUpdateCheck,
+ 0, // default value
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterInt64Pref(
+ pref_names::kNextUpdateCheck,
+ 0, // default value
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kAllowedInstallSites,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterStringPref(
+ pref_names::kLastChromeVersion,
+ std::string(), // default value
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kKnownDisabled,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+#if defined(TOOLKIT_VIEWS)
+ registry->RegisterIntegerPref(
+ pref_names::kBrowserActionContainerWidth,
+ 0,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+#endif
+ registry->RegisterDictionaryPref(
+ kInstallSignature,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+
+ registry->RegisterListPref(pref_names::kNativeMessagingBlacklist,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(pref_names::kNativeMessagingWhitelist,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+}
+
+template <class ExtensionIdContainer>
+bool ExtensionPrefs::GetUserExtensionPrefIntoContainer(
+ const char* pref,
+ ExtensionIdContainer* id_container_out) {
+ DCHECK(id_container_out->empty());
+
+ const base::Value* user_pref_value = prefs_->GetUserPrefValue(pref);
+ const base::ListValue* user_pref_as_list;
+ if (!user_pref_value || !user_pref_value->GetAsList(&user_pref_as_list))
+ return false;
+
+ std::insert_iterator<ExtensionIdContainer> insert_iterator(
+ *id_container_out, id_container_out->end());
+ std::string extension_id;
+ for (base::ListValue::const_iterator value_it = user_pref_as_list->begin();
+ value_it != user_pref_as_list->end(); ++value_it) {
+ if (!(*value_it)->GetAsString(&extension_id)) {
+ NOTREACHED();
+ continue;
+ }
+ insert_iterator = extension_id;
+ }
+ return true;
+}
+
+template <class ExtensionIdContainer>
+void ExtensionPrefs::SetExtensionPrefFromContainer(
+ const char* pref,
+ const ExtensionIdContainer& strings) {
+ ListPrefUpdate update(prefs_, pref);
+ base::ListValue* list_of_values = update.Get();
+ list_of_values->Clear();
+ for (typename ExtensionIdContainer::const_iterator iter = strings.begin();
+ iter != strings.end(); ++iter) {
+ list_of_values->Append(new base::StringValue(*iter));
+ }
+}
+
+void ExtensionPrefs::PopulateExtensionInfoPrefs(
+ const Extension* extension,
+ const base::Time install_time,
+ Extension::State initial_state,
+ bool blacklisted_for_malware,
+ base::DictionaryValue* extension_dict) {
+ // Leave the state blank for component extensions so that old chrome versions
+ // loading new profiles do not fail in GetInstalledExtensionInfo. Older
+ // Chrome versions would only check for an omitted state.
+ if (initial_state != Extension::ENABLED_COMPONENT)
+ extension_dict->Set(kPrefState, new base::FundamentalValue(initial_state));
+
+ extension_dict->Set(kPrefLocation,
+ new base::FundamentalValue(extension->location()));
+ extension_dict->Set(kPrefCreationFlags,
+ new base::FundamentalValue(extension->creation_flags()));
+ extension_dict->Set(kPrefFromWebStore,
+ new base::FundamentalValue(extension->from_webstore()));
+ extension_dict->Set(kPrefFromBookmark,
+ new base::FundamentalValue(extension->from_bookmark()));
+ extension_dict->Set(
+ kPrefWasInstalledByDefault,
+ new base::FundamentalValue(extension->was_installed_by_default()));
+ extension_dict->Set(kPrefInstallTime,
+ new base::StringValue(
+ base::Int64ToString(install_time.ToInternalValue())));
+ if (blacklisted_for_malware)
+ extension_dict->Set(kPrefBlacklist, new base::FundamentalValue(true));
+
+ base::FilePath::StringType path = MakePathRelative(install_directory_,
+ extension->path());
+ extension_dict->Set(kPrefPath, new base::StringValue(path));
+ // We store prefs about LOAD extensions, but don't cache their manifest
+ // since it may change on disk.
+ if (!Manifest::IsUnpackedLocation(extension->location())) {
+ extension_dict->Set(kPrefManifest,
+ extension->manifest()->value()->DeepCopy());
+ }
+}
+
+void ExtensionPrefs::FinishExtensionInfoPrefs(
+ const std::string& extension_id,
+ const base::Time install_time,
+ bool needs_sort_ordinal,
+ const syncer::StringOrdinal& suggested_page_ordinal,
+ base::DictionaryValue* extension_dict) {
+ // Reinitializes various preferences with empty dictionaries.
+ if (!extension_dict->HasKey(pref_names::kPrefPreferences)) {
+ extension_dict->Set(pref_names::kPrefPreferences,
+ new base::DictionaryValue);
+ }
+
+ if (!extension_dict->HasKey(pref_names::kPrefIncognitoPreferences)) {
+ extension_dict->Set(pref_names::kPrefIncognitoPreferences,
+ new base::DictionaryValue);
+ }
+
+ if (!extension_dict->HasKey(pref_names::kPrefRegularOnlyPreferences)) {
+ extension_dict->Set(pref_names::kPrefRegularOnlyPreferences,
+ new base::DictionaryValue);
+ }
+
+ if (!extension_dict->HasKey(pref_names::kPrefContentSettings))
+ extension_dict->Set(pref_names::kPrefContentSettings, new base::ListValue);
+
+ if (!extension_dict->HasKey(pref_names::kPrefIncognitoContentSettings)) {
+ extension_dict->Set(pref_names::kPrefIncognitoContentSettings,
+ new base::ListValue);
+ }
+
+ // If this point has been reached, any pending installs should be considered
+ // out of date.
+ extension_dict->Remove(kDelayedInstallInfo, NULL);
+
+ // Clear state that may be registered from a previous install.
+ extension_dict->Remove(EventRouter::kRegisteredEvents, NULL);
+
+ // FYI, all code below here races on sudden shutdown because |extension_dict|,
+ // |app_sorting_|, |extension_pref_value_map_|, and |content_settings_store_|
+ // are updated non-transactionally. This is probably not fixable without
+ // nested transactional updates to pref dictionaries.
+ if (needs_sort_ordinal)
+ app_sorting_->EnsureValidOrdinals(extension_id, suggested_page_ordinal);
+
+ bool is_enabled = false;
+ int initial_state;
+ if (extension_dict->GetInteger(kPrefState, &initial_state)) {
+ is_enabled = initial_state == Extension::ENABLED;
+ }
+
+ extension_pref_value_map_->RegisterExtension(extension_id, install_time,
+ is_enabled);
+ content_settings_store_->RegisterExtension(extension_id, install_time,
+ is_enabled);
+}
+
+} // namespace extensions