summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/extension_management.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions/extension_management.cc')
-rw-r--r--chrome/browser/extensions/extension_management.cc139
1 files changed, 135 insertions, 4 deletions
diff --git a/chrome/browser/extensions/extension_management.cc b/chrome/browser/extensions/extension_management.cc
index 186e4b4..1c07ebb 100644
--- a/chrome/browser/extensions/extension_management.cc
+++ b/chrome/browser/extensions/extension_management.cc
@@ -8,6 +8,8 @@
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"
+#include "base/strings/string_util.h"
+#include "chrome/browser/extensions/extension_management_constants.h"
#include "chrome/browser/extensions/external_policy_loader.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/browser/extensions/standard_management_policy_provider.h"
@@ -15,12 +17,80 @@
#include "chrome/browser/profiles/profile.h"
#include "components/crx_file/id_util.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/pref_registry/pref_registry_syncable.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/url_pattern.h"
#include "url/gurl.h"
namespace extensions {
+namespace {
+
+const char kMalformedPreferenceWarning[] =
+ "Malformed extension management preference.";
+
+enum Scope {
+ // Parses the default settings.
+ SCOPE_DEFAULT = 0,
+ // Parses the settings for an extension with specified extension ID.
+ SCOPE_INDIVIDUAL,
+};
+
+// Parse the individual settings for |settings|. |dict| is the a
+// sub-dictionary in extension management preference and |scope| represents
+// the applicable range of the settings, a single extension, a group of
+// extensions or default settings.
+// Note that in case of parsing errors, |settings| will NOT be left untouched.
+bool ParseIndividualSettings(
+ const base::DictionaryValue* dict,
+ Scope scope,
+ ExtensionManagement::IndividualSettings* settings) {
+ settings->Reset();
+
+ std::string installation_mode;
+ if (dict->GetStringWithoutPathExpansion(schema_constants::kInstallationMode,
+ &installation_mode)) {
+ if (installation_mode == schema_constants::kAllowed) {
+ settings->installation_mode = ExtensionManagement::INSTALLATION_ALLOWED;
+ } else if (installation_mode == schema_constants::kBlocked) {
+ settings->installation_mode = ExtensionManagement::INSTALLATION_BLOCKED;
+ } else if (installation_mode == schema_constants::kForceInstalled) {
+ settings->installation_mode = ExtensionManagement::INSTALLATION_FORCED;
+ } else if (installation_mode == schema_constants::kNormalInstalled) {
+ settings->installation_mode =
+ ExtensionManagement::INSTALLATION_RECOMMENDED;
+ } else {
+ // Invalid value for 'installation_mode'.
+ LOG(WARNING) << kMalformedPreferenceWarning;
+ return false;
+ }
+ }
+
+ if (settings->installation_mode == ExtensionManagement::INSTALLATION_FORCED ||
+ settings->installation_mode ==
+ ExtensionManagement::INSTALLATION_RECOMMENDED) {
+ if (scope != SCOPE_INDIVIDUAL) {
+ // Only individual extensions are allowed to be automatically installed.
+ LOG(WARNING) << kMalformedPreferenceWarning;
+ return false;
+ }
+ std::string update_url;
+ if (dict->GetStringWithoutPathExpansion(schema_constants::kUpdateUrl,
+ &update_url) &&
+ GURL(update_url).is_valid()) {
+ settings->update_url = update_url;
+ } else {
+ // No valid update URL for extension.
+ LOG(WARNING) << kMalformedPreferenceWarning;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace
+
void ExtensionManagement::IndividualSettings::Reset() {
installation_mode = ExtensionManagement::INSTALLATION_ALLOWED;
update_url.clear();
@@ -54,6 +124,8 @@ ExtensionManagement::ExtensionManagement(PrefService* pref_service)
pref_change_registrar_.Add(pref_names::kAllowedInstallSites,
pref_change_callback);
pref_change_registrar_.Add(pref_names::kAllowedTypes, pref_change_callback);
+ pref_change_registrar_.Add(pref_names::kExtensionManagement,
+ pref_change_callback);
Refresh();
provider_.reset(new StandardManagementPolicyProvider(this));
}
@@ -145,6 +217,11 @@ void ExtensionManagement::Refresh() {
const base::ListValue* allowed_types_pref =
static_cast<const base::ListValue*>(LoadPreference(
pref_names::kAllowedTypes, true, base::Value::TYPE_LIST));
+ const base::DictionaryValue* dict_pref =
+ static_cast<const base::DictionaryValue*>(
+ LoadPreference(pref_names::kExtensionManagement,
+ true,
+ base::Value::TYPE_DICTIONARY));
// Reset all settings.
global_settings_.Reset();
@@ -158,6 +235,22 @@ void ExtensionManagement::Refresh() {
default_settings_.installation_mode = INSTALLATION_BLOCKED;
}
+ const base::DictionaryValue* subdict = NULL;
+ if (dict_pref &&
+ dict_pref->GetDictionary(schema_constants::kWildcard, &subdict)) {
+ if (!ParseIndividualSettings(subdict, SCOPE_DEFAULT, &default_settings_)) {
+ LOG(WARNING) << "Default extension management settings parsing error.";
+ default_settings_.Reset();
+ }
+
+ // Settings from new preference have higher priority over legacy ones.
+ const base::ListValue* list_value = NULL;
+ if (subdict->GetList(schema_constants::kInstallSources, &list_value))
+ install_sources_pref = list_value;
+ if (subdict->GetList(schema_constants::kAllowedTypes, &list_value))
+ allowed_types_pref = list_value;
+ }
+
// Parse legacy preferences.
ExtensionId id;
@@ -196,11 +289,11 @@ void ExtensionManagement::Refresh() {
if (install_sources_pref) {
global_settings_.has_restricted_install_sources = true;
- std::string url_pattern;
for (base::ListValue::const_iterator it = install_sources_pref->begin();
it != install_sources_pref->end(); ++it) {
- URLPattern entry(URLPattern::SCHEME_ALL);
+ std::string url_pattern;
if ((*it)->GetAsString(&url_pattern)) {
+ URLPattern entry(URLPattern::SCHEME_ALL);
if (entry.Parse(url_pattern) == URLPattern::PARSE_SUCCESS) {
global_settings_.install_sources.AddPattern(entry);
} else {
@@ -217,16 +310,47 @@ void ExtensionManagement::Refresh() {
for (base::ListValue::const_iterator it = allowed_types_pref->begin();
it != allowed_types_pref->end(); ++it) {
int int_value;
+ std::string string_value;
if ((*it)->GetAsInteger(&int_value) && int_value >= 0 &&
int_value < Manifest::Type::NUM_LOAD_TYPES) {
global_settings_.allowed_types.push_back(
static_cast<Manifest::Type>(int_value));
+ } else if ((*it)->GetAsString(&string_value)) {
+ Manifest::Type manifest_type =
+ schema_constants::GetManifestType(string_value);
+ if (manifest_type != Manifest::TYPE_UNKNOWN)
+ global_settings_.allowed_types.push_back(manifest_type);
}
}
}
- // TODO(binjin): Add parsing of new ExtensionManagement preference after the
- // new ExtensionManagement policy is added.
+ if (dict_pref) {
+ // Parse new extension management preference.
+ for (base::DictionaryValue::Iterator iter(*dict_pref); !iter.IsAtEnd();
+ iter.Advance()) {
+ if (iter.key() == schema_constants::kWildcard)
+ continue;
+ if (!iter.value().GetAsDictionary(&subdict)) {
+ LOG(WARNING) << kMalformedPreferenceWarning;
+ continue;
+ }
+ if (StartsWithASCII(
+ iter.key(), schema_constants::kUpdateUrlPrefix, true))
+ continue;
+ const std::string& extension_id = iter.key();
+ if (!crx_file::id_util::IdIsValid(extension_id)) {
+ LOG(WARNING) << kMalformedPreferenceWarning;
+ continue;
+ }
+ IndividualSettings by_id;
+ if (ParseIndividualSettings(subdict, SCOPE_INDIVIDUAL, &by_id)) {
+ *AccessById(extension_id) = by_id;
+ } else {
+ LOG(WARNING) << "Malformed Extension Management settings for "
+ << iter.key() << ".";
+ }
+ }
+ }
}
const base::Value* ExtensionManagement::LoadPreference(
@@ -293,4 +417,11 @@ content::BrowserContext* ExtensionManagementFactory::GetBrowserContextToUse(
return chrome::GetBrowserContextRedirectedInIncognito(context);
}
+void ExtensionManagementFactory::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* user_prefs) {
+ user_prefs->RegisterDictionaryPref(
+ pref_names::kExtensionManagement,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+}
+
} // namespace extensions