Chromium Code Reviews| Index: chrome/browser/extensions/extension_management.cc |
| diff --git a/chrome/browser/extensions/extension_management.cc b/chrome/browser/extensions/extension_management.cc |
| index 186e4b49d08eb6a2dfcd601f83b6b9e1c898a1f7..ed6697f968c423fab33cef6ce9a84c427d251fa8 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,75 @@ |
| #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 { |
| + |
| +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 { |
| + LOG(WARNING) << "Invalid value for 'installation_mode'."; |
|
scheib
2014/09/19 16:22:13
http://dev.chromium.org/developers/coding-style#TO
binjin
2014/09/22 13:53:54
Thanks, I simplified the warning messages in LOG t
|
| + return false; |
| + } |
| + } |
| + |
| + if (settings->installation_mode == ExtensionManagement::INSTALLATION_FORCED || |
| + settings->installation_mode == |
| + ExtensionManagement::INSTALLATION_RECOMMENDED) { |
| + if (scope != SCOPE_INDIVIDUAL) { |
| + LOG(WARNING) << "Only individual extensions are allowed to be " |
| + "automatically installed."; |
| + 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 { |
| + LOG(WARNING) << "No valid update URL for extension."; |
| + return false; |
| + } |
| + } |
| + |
| + return true; |
| +} |
| + |
| +} // namespace |
| + |
| void ExtensionManagement::IndividualSettings::Reset() { |
| installation_mode = ExtensionManagement::INSTALLATION_ALLOWED; |
| update_url.clear(); |
| @@ -54,6 +119,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 +212,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 +230,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 +284,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 +305,48 @@ 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) << "Malformed extension management preference."; |
| + 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) << "Malformed extension management preference."; |
| + continue; |
| + } |
| + IndividualSettings by_id; |
| + if (!ParseIndividualSettings(subdict, SCOPE_INDIVIDUAL, &by_id)) { |
| + LOG(WARNING) << "Malformed extension management preference."; |
| + continue; |
| + } else { |
| + *AccessById(extension_id) = by_id; |
| + } |
| + } |
| + } |
| } |
| const base::Value* ExtensionManagement::LoadPreference( |
| @@ -293,4 +413,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 |