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..be19b0936b82c1bf8bd9f0d8e2c3f39419311800 100644 |
| --- a/chrome/browser/extensions/extension_management.cc |
| +++ b/chrome/browser/extensions/extension_management.cc |
| @@ -8,6 +8,7 @@ |
| #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/external_policy_loader.h" |
| #include "chrome/browser/extensions/external_provider_impl.h" |
| #include "chrome/browser/extensions/standard_management_policy_provider.h" |
| @@ -21,6 +22,89 @@ |
| namespace extensions { |
| +namespace schema_constants { |
| + |
| +const char kAllOtherExtension[] = "*"; |
|
Joao da Silva
2014/09/18 12:08:21
Rename this to kWildcard
binjin
2014/09/18 14:37:27
Done.
|
| + |
| +const char kInstallationMode[] = "installation_mode"; |
| +const char kAllowed[] = "allowed"; |
| +const char kBlocked[] = "blocked"; |
| +const char kForceInstalled[] = "force_installed"; |
| +const char kNormalInstalled[] = "normal_installed"; |
| + |
| +const char kUpdateUrl[] = "update_url"; |
| +const char kInstallSources[] = "install_sources"; |
| +const char kAllowedTypes[] = "allowed_types"; |
| + |
| +const char kUpdateUrlPrefix[] = "update_url:"; |
| + |
| +const AllowedTypesMapType kAllowedTypesMap[] = { |
| + { "extension", Manifest::TYPE_EXTENSION }, |
| + { "theme", Manifest::TYPE_THEME }, |
| + { "user_script", Manifest::TYPE_USER_SCRIPT }, |
| + { "hosted_app", Manifest::TYPE_HOSTED_APP }, |
| + { "legacy_packaged_app", Manifest::TYPE_LEGACY_PACKAGED_APP }, |
| + { "platform_app", Manifest::TYPE_PLATFORM_APP }, |
|
Joao da Silva
2014/09/18 12:08:21
Align the types in the same column
binjin
2014/09/18 14:37:27
Done.
|
| + // TODO(binjin): Add shared_module type here and update ExtensionAllowedTypes |
| + // policy. |
| + { NULL, Manifest::TYPE_UNKNOWN } |
|
Joao da Silva
2014/09/18 12:08:21
Remove the NULL entry
binjin
2014/09/18 14:37:26
Done.
|
| +}; |
|
Joao da Silva
2014/09/18 12:08:21
Add the size constant:
const size_t kAllowedTypes
binjin
2014/09/18 14:37:27
Done.
|
| + |
| +} // namespace schema_constants |
| + |
| +bool ExtensionManagement::IndividualSettings::Parse( |
| + const base::DictionaryValue* dict, |
| + Scope scope) { |
| + Reset(); |
| + |
| + std::string installation_mode; |
| + if (dict->GetStringWithoutPathExpansion(schema_constants::kInstallationMode, |
| + &installation_mode)) { |
| + if (installation_mode == schema_constants::kAllowed) { |
| + this->installation_mode = INSTALLATION_ALLOWED; |
| + } else if (installation_mode == schema_constants::kBlocked) { |
| + this->installation_mode = INSTALLATION_BLOCKED; |
| + } else if (installation_mode == schema_constants::kForceInstalled) { |
| + this->installation_mode = INSTALLATION_FORCED; |
| + } else if (installation_mode == schema_constants::kNormalInstalled) { |
| + this->installation_mode = INSTALLATION_RECOMMENDED; |
| + } else { |
| + LOG(WARNING) << "Invalid value for 'installation_modes'."; |
|
Joao da Silva
2014/09/18 12:08:21
installation_mode
binjin
2014/09/18 14:37:27
Done.
|
| + return false; |
| + } |
| + } |
| + |
| + std::string update_url; |
| + if (dict->GetStringWithoutPathExpansion(schema_constants::kUpdateUrl, |
| + &update_url)) { |
|
Joao da Silva
2014/09/18 12:08:21
The update_url only matters for FORCED and RECOMME
binjin
2014/09/18 14:37:26
Done with further simplification.
|
| + if (scope != SCOPE_INDIVIDUAL) { |
| + LOG(WARNING) |
| + << "Only individual extensions are allowed to have an update URL."; |
| + return false; |
| + } |
| + if (!GURL(update_url).is_valid()) { |
| + LOG(WARNING) << "No valid update URL for this extension."; |
| + return false; |
| + } |
| + this->update_url = update_url; |
| + } |
| + |
| + if (this->installation_mode == INSTALLATION_FORCED || |
| + this->installation_mode == INSTALLATION_RECOMMENDED) { |
| + if (scope != SCOPE_INDIVIDUAL) { |
| + LOG(WARNING) << "Only individual extensions are allowed to be " |
| + "automatically installed."; |
| + return false; |
| + } |
| + if (this->update_url.empty()) { |
| + LOG(WARNING) << "No valid update URL for this extension."; |
| + return false; |
| + } |
| + } |
| + |
| + return true; |
| +} |
| + |
| void ExtensionManagement::IndividualSettings::Reset() { |
| installation_mode = ExtensionManagement::INSTALLATION_ALLOWED; |
| update_url.clear(); |
| @@ -54,6 +138,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 +231,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 +249,21 @@ void ExtensionManagement::Refresh() { |
| default_settings_.installation_mode = INSTALLATION_BLOCKED; |
| } |
| + const base::DictionaryValue* subdict = NULL; |
| + if (dict_pref && |
| + dict_pref->GetDictionary(schema_constants::kAllOtherExtension, |
| + &subdict)) { |
| + if (!default_settings_.Parse(subdict, IndividualSettings::SCOPE_DEFAULT)) |
| + LOG(WARNING) << "Default extension management settings parsing error."; |
|
Joao da Silva
2014/09/18 12:08:21
Reset() default_settings_ in this case?
binjin
2014/09/18 14:37:26
Done.
|
| + |
| + // Settings from new preference have higher priority over legacy ones. |
| + const base::ListValue* list_value; |
|
Joao da Silva
2014/09/18 12:08:21
= NULL
binjin
2014/09/18 14:37:26
Done.
|
| + 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 +302,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 +323,52 @@ 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)) { |
| + for (const schema_constants::AllowedTypesMapType* iter = |
| + schema_constants::kAllowedTypesMap; |
| + iter->name; |
| + ++iter) { |
| + if (iter->name == string_value) { |
| + global_settings_.allowed_types.push_back(iter->manifest_type); |
| + break; |
|
Joao da Silva
2014/09/18 12:08:21
Make a helper for this:
bool GetManifestType(cons
binjin
2014/09/18 14:37:27
Done. I tried to avoid passing pointer here, and r
|
| + } |
| + } |
| } |
| } |
| } |
| - // 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::kAllOtherExtension) |
| + continue; |
| + if (!iter.value().GetAsDictionary(&subdict)) { |
| + LOG(WARNING) << "Malformed extension management preference."; |
| + continue; |
| + } |
| + if (!StartsWithASCII( |
| + iter.key(), schema_constants::kUpdateUrlPrefix, true)) { |
|
Joao da Silva
2014/09/18 12:08:21
if (StartsWithASCII(...))
continue;
binjin
2014/09/18 14:37:27
Done.
|
| + 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 (!by_id.Parse(subdict, IndividualSettings::SCOPE_INDIVIDUAL)) { |
| + LOG(WARNING) << "Malformed extension management preference."; |
| + continue; |
| + } else { |
| + *AccessById(extension_id) = by_id; |
| + } |
| + } |
| + } |
| + } |
| } |
| const base::Value* ExtensionManagement::LoadPreference( |