Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1087)

Unified Diff: extensions/common/features/simple_feature.cc

Issue 1010973013: Refactor Uses of std::set to std::vector in SimpleFeature (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove Unsigned From Checks with STLCount Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: extensions/common/features/simple_feature.cc
diff --git a/extensions/common/features/simple_feature.cc b/extensions/common/features/simple_feature.cc
index 7d1e06e35b11dffe0a7f4b469fc35bc61cb60e96..6a5bece485df46b7ccc9db8ef21c5d62a521ba93 100644
--- a/extensions/common/features/simple_feature.cc
+++ b/extensions/common/features/simple_feature.cc
@@ -4,13 +4,13 @@
#include "extensions/common/features/simple_feature.h"
+#include <algorithm>
#include <map>
#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/alias.h"
-#include "base/lazy_instance.h"
#include "base/sha1.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
@@ -43,56 +43,23 @@ Feature::Availability IsAvailableToContextForBind(const Extension* extension,
return feature->IsAvailableToContext(extension, context, url, platform);
}
-struct Mappings {
- Mappings() {
- extension_types["extension"] = Manifest::TYPE_EXTENSION;
- extension_types["theme"] = Manifest::TYPE_THEME;
- extension_types["legacy_packaged_app"] = Manifest::TYPE_LEGACY_PACKAGED_APP;
- extension_types["hosted_app"] = Manifest::TYPE_HOSTED_APP;
- extension_types["platform_app"] = Manifest::TYPE_PLATFORM_APP;
- extension_types["shared_module"] = Manifest::TYPE_SHARED_MODULE;
-
- contexts["blessed_extension"] = Feature::BLESSED_EXTENSION_CONTEXT;
- contexts["unblessed_extension"] = Feature::UNBLESSED_EXTENSION_CONTEXT;
- contexts["content_script"] = Feature::CONTENT_SCRIPT_CONTEXT;
- contexts["web_page"] = Feature::WEB_PAGE_CONTEXT;
- contexts["blessed_web_page"] = Feature::BLESSED_WEB_PAGE_CONTEXT;
- contexts["webui"] = Feature::WEBUI_CONTEXT;
-
- locations["component"] = SimpleFeature::COMPONENT_LOCATION;
- locations["external_component"] =
- SimpleFeature::EXTERNAL_COMPONENT_LOCATION;
- locations["policy"] = SimpleFeature::POLICY_LOCATION;
-
- platforms["chromeos"] = Feature::CHROMEOS_PLATFORM;
- platforms["linux"] = Feature::LINUX_PLATFORM;
- platforms["mac"] = Feature::MACOSX_PLATFORM;
- platforms["win"] = Feature::WIN_PLATFORM;
- }
-
- std::map<std::string, Manifest::Type> extension_types;
- std::map<std::string, Feature::Context> contexts;
- std::map<std::string, SimpleFeature::Location> locations;
- std::map<std::string, Feature::Platform> platforms;
-};
-
-base::LazyInstance<Mappings> g_mappings = LAZY_INSTANCE_INITIALIZER;
-
// TODO(aa): Can we replace all this manual parsing with JSON schema stuff?
-void ParseSet(const base::DictionaryValue* value,
- const std::string& property,
- std::set<std::string>* set) {
+void ParseVector(const base::Value* value,
+ std::vector<std::string>* vector) {
const base::ListValue* list_value = NULL;
- if (!value->GetList(property, &list_value))
+ if (!value->GetAsList(&list_value))
return;
- set->clear();
- for (size_t i = 0; i < list_value->GetSize(); ++i) {
+ vector->clear();
+ size_t list_size = list_value->GetSize();
+ vector->reserve(list_size);
+ for (size_t i = 0; i < list_size; ++i) {
std::string str_val;
- CHECK(list_value->GetString(i, &str_val)) << property << " " << i;
- set->insert(str_val);
+ CHECK(list_value->GetString(i, &str_val));
+ vector->push_back(str_val);
}
+ std::sort(vector->begin(), vector->end());
}
template<typename T>
@@ -124,31 +91,30 @@ void ParseEnum(const base::DictionaryValue* value,
}
template<typename T>
-void ParseEnumSet(const base::DictionaryValue* value,
- const std::string& property,
- std::set<T>* enum_set,
- const std::map<std::string, T>& mapping) {
- if (!value->HasKey(property))
- return;
-
- enum_set->clear();
-
+void ParseEnumVector(const base::Value* value,
+ std::vector<T>* enum_vector,
+ const std::map<std::string, T>& mapping) {
+ enum_vector->clear();
std::string property_string;
- if (value->GetString(property, &property_string)) {
+ if (value->GetAsString(&property_string)) {
if (property_string == "all") {
+ enum_vector->reserve(mapping.size());
for (const auto& it : mapping)
- enum_set->insert(it.second);
+ enum_vector->push_back(it.second);
}
+ std::sort(enum_vector->begin(), enum_vector->end());
return;
}
- std::set<std::string> string_set;
- ParseSet(value, property, &string_set);
- for (const auto& str : string_set) {
+ std::vector<std::string> string_vector;
+ ParseVector(value, &string_vector);
+ enum_vector->reserve(string_vector.size());
+ for (const auto& str : string_vector) {
T enum_value = static_cast<T>(0);
ParseEnum(str, &enum_value, mapping);
- enum_set->insert(enum_value);
+ enum_vector->push_back(enum_value);
}
+ std::sort(enum_vector->begin(), enum_vector->end());
}
void ParseURLPatterns(const base::DictionaryValue* value,
@@ -258,6 +224,39 @@ bool IsCommandLineSwitchEnabled(const std::string& switch_name) {
} // namespace
+struct SimpleFeature::Mappings {
+ Mappings() {
+ extension_types["extension"] = Manifest::TYPE_EXTENSION;
+ extension_types["theme"] = Manifest::TYPE_THEME;
+ extension_types["legacy_packaged_app"] = Manifest::TYPE_LEGACY_PACKAGED_APP;
+ extension_types["hosted_app"] = Manifest::TYPE_HOSTED_APP;
+ extension_types["platform_app"] = Manifest::TYPE_PLATFORM_APP;
+ extension_types["shared_module"] = Manifest::TYPE_SHARED_MODULE;
+
+ contexts["blessed_extension"] = Feature::BLESSED_EXTENSION_CONTEXT;
+ contexts["unblessed_extension"] = Feature::UNBLESSED_EXTENSION_CONTEXT;
+ contexts["content_script"] = Feature::CONTENT_SCRIPT_CONTEXT;
+ contexts["web_page"] = Feature::WEB_PAGE_CONTEXT;
+ contexts["blessed_web_page"] = Feature::BLESSED_WEB_PAGE_CONTEXT;
+ contexts["webui"] = Feature::WEBUI_CONTEXT;
+
+ locations["component"] = SimpleFeature::COMPONENT_LOCATION;
+ locations["external_component"] =
+ SimpleFeature::EXTERNAL_COMPONENT_LOCATION;
+ locations["policy"] = SimpleFeature::POLICY_LOCATION;
+
+ platforms["chromeos"] = Feature::CHROMEOS_PLATFORM;
+ platforms["linux"] = Feature::LINUX_PLATFORM;
+ platforms["mac"] = Feature::MACOSX_PLATFORM;
+ platforms["win"] = Feature::WIN_PLATFORM;
+ }
+
+ std::map<std::string, Manifest::Type> extension_types;
+ std::map<std::string, Feature::Context> contexts;
+ std::map<std::string, SimpleFeature::Location> locations;
+ std::map<std::string, Feature::Platform> platforms;
+};
+
SimpleFeature::SimpleFeature()
: location_(UNSPECIFIED_LOCATION),
min_manifest_version_(0),
@@ -274,29 +273,49 @@ void SimpleFeature::AddFilter(scoped_ptr<SimpleFeatureFilter> filter) {
filters_.push_back(filter.release());
}
-std::string SimpleFeature::Parse(const base::DictionaryValue* value) {
- ParseURLPatterns(value, "matches", &matches_);
- ParseSet(value, "blacklist", &blacklist_);
- ParseSet(value, "whitelist", &whitelist_);
- ParseSet(value, "dependencies", &dependencies_);
- ParseEnumSet<Manifest::Type>(value, "extension_types", &extension_types_,
- g_mappings.Get().extension_types);
- ParseEnumSet<Context>(value, "contexts", &contexts_,
- g_mappings.Get().contexts);
- ParseEnum<Location>(value, "location", &location_,
- g_mappings.Get().locations);
- ParseEnumSet<Platform>(value, "platforms", &platforms_,
- g_mappings.Get().platforms);
- value->GetInteger("min_manifest_version", &min_manifest_version_);
- value->GetInteger("max_manifest_version", &max_manifest_version_);
+std::string SimpleFeature::Parse(const base::DictionaryValue* dictionary) {
+ static base::LazyInstance<SimpleFeature::Mappings> mappings =
+ LAZY_INSTANCE_INITIALIZER;
no_parent_ = false;
- value->GetBoolean("noparent", &no_parent_);
-
- value->GetBoolean("component_extensions_auto_granted",
- &component_extensions_auto_granted_);
-
- value->GetString("command_line_switch", &command_line_switch_);
+ for (base::DictionaryValue::Iterator it(*dictionary);
+ !it.IsAtEnd();
+ it.Advance()) {
+ std::string key = it.key();
+ const base::Value* value = &it.value();
+ if (key == "matches") {
+ ParseURLPatterns(dictionary, "matches", &matches_);
+ } else if (key == "blacklist") {
+ ParseVector(value, &blacklist_);
+ } else if (key == "whitelist") {
+ ParseVector(value, &whitelist_);
+ } else if (key == "dependencies") {
+ ParseVector(value, &dependencies_);
+ } else if (key == "extension_types") {
+ ParseEnumVector<Manifest::Type>(value, &extension_types_,
+ mappings.Get().extension_types);
+ } else if (key == "contexts") {
+ ParseEnumVector<Context>(value, &contexts_,
+ mappings.Get().contexts);
+ } else if (key == "location") {
+ ParseEnum<Location>(dictionary, "location", &location_,
+ mappings.Get().locations);
+ } else if (key == "platforms") {
+ ParseEnumVector<Platform>(value, &platforms_,
+ mappings.Get().platforms);
+ } else if (key == "min_manifest_version") {
+ dictionary->GetInteger("min_manifest_version", &min_manifest_version_);
+ } else if (key == "max_manifest_version") {
+ dictionary->GetInteger("max_manifest_version", &max_manifest_version_);
+ } else if (key == "noparent") {
+ dictionary->GetBoolean("noparent", &no_parent_);
+ } else if (key == "component_extensions_auto_granted") {
+ dictionary->GetBoolean("component_extensions_auto_granted",
+ &component_extensions_auto_granted_);
+ } else if (key == "command_line_switch") {
+ dictionary->GetString("command_line_switch", &command_line_switch_);
+ }
+ }
// NOTE: ideally we'd sanity check that "matches" can be specified if and
// only if there's a "web_page" or "webui" context, but without
@@ -309,7 +328,7 @@ std::string SimpleFeature::Parse(const base::DictionaryValue* value) {
std::string result;
for (const auto& filter : filters_) {
- result = filter->Parse(value);
+ result = filter->Parse(dictionary);
if (!result.empty())
break;
}
@@ -330,7 +349,7 @@ Feature::Availability SimpleFeature::IsAvailableToManifest(
Manifest::Type type_to_check = (type == Manifest::TYPE_USER_SCRIPT) ?
Manifest::TYPE_EXTENSION : type;
if (!extension_types_.empty() &&
- !ContainsKey(extension_types_, type_to_check)) {
+ !ContainsValue(extension_types_, type_to_check)) {
return CreateAvailability(INVALID_TYPE, type);
}
@@ -363,7 +382,7 @@ Feature::Availability SimpleFeature::IsAvailableToManifest(
if (!MatchesManifestLocation(location))
return CreateAvailability(INVALID_LOCATION, type);
- if (!platforms_.empty() && !ContainsKey(platforms_, platform))
+ if (!platforms_.empty() && !ContainsValue(platforms_, platform))
return CreateAvailability(INVALID_PLATFORM, type);
if (min_manifest_version_ != 0 && manifest_version < min_manifest_version_)
@@ -407,7 +426,7 @@ Feature::Availability SimpleFeature::IsAvailableToContext(
return result;
}
- if (!contexts_.empty() && !ContainsKey(contexts_, context))
+ if (!contexts_.empty() && !ContainsValue(contexts_, context))
return CreateAvailability(INVALID_CONTEXT, context);
// TODO(kalman): Consider checking |matches_| regardless of context type.
@@ -539,17 +558,27 @@ bool SimpleFeature::IsIdInWhitelist(const std::string& extension_id) const {
}
// static
+bool SimpleFeature::IsIdInArray(const std::string& extension_id,
+ const char* const array[],
+ size_t array_length) {
+ if (!IsValidExtensionId(extension_id))
+ return false;
+
+ const char* const* start = array;
+ const char* const* end = array + array_length;
+
+ return ((std::find(start, end, extension_id) != end) ||
+ (std::find(start, end, HashExtensionId(extension_id)) != end));
+}
+
+// static
bool SimpleFeature::IsIdInList(const std::string& extension_id,
- const std::set<std::string>& list) {
- // Belt-and-suspenders philosophy here. We should be pretty confident by this
- // point that we've validated the extension ID format, but in case something
- // slips through, we avoid a class of attack where creative ID manipulation
- // leads to hash collisions.
- if (extension_id.length() != 32) // 128 bits / 4 = 32 mpdecimal characters
+ const std::vector<std::string>& list) {
+ if (!IsValidExtensionId(extension_id))
return false;
- return (ContainsKey(list, extension_id) ||
- ContainsKey(list, HashExtensionId(extension_id)));
+ return (ContainsValue(list, extension_id) ||
+ ContainsValue(list, HashExtensionId(extension_id)));
}
bool SimpleFeature::MatchesManifestLocation(
@@ -583,4 +612,14 @@ Feature::Availability SimpleFeature::CheckDependencies(
return CreateAvailability(IS_AVAILABLE);
}
+// static
+bool SimpleFeature::IsValidExtensionId(const std::string& extension_id) {
+ // Belt-and-suspenders philosophy here. We should be pretty confident by this
+ // point that we've validated the extension ID format, but in case something
+ // slips through, we avoid a class of attack where creative ID manipulation
+ // leads to hash collisions.
+ // 128 bits / 4 = 32 mpdecimal characters
+ return (extension_id.length() == 32);
+}
+
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698