diff options
author | kalman <kalman@chromium.org> | 2014-12-12 14:04:23 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-12-12 22:04:50 +0000 |
commit | ae342c9a0fa8a3c55bc89bf9a1543ad85f7d404f (patch) | |
tree | 55eaca44eec5fb3bad91de53987b5b701d8119ea /extensions/common/features | |
parent | 7547705543d6b711a166e513a43a4e43f93fd254 (diff) | |
download | chromium_src-ae342c9a0fa8a3c55bc89bf9a1543ad85f7d404f.zip chromium_src-ae342c9a0fa8a3c55bc89bf9a1543ad85f7d404f.tar.gz chromium_src-ae342c9a0fa8a3c55bc89bf9a1543ad85f7d404f.tar.bz2 |
Add support for command line switches to Features, and as proof that it works,
use it for the experimental permission.
BUG=440194
R=rockot@chromium.org
Review URL: https://codereview.chromium.org/801603002
Cr-Commit-Position: refs/heads/master@{#308176}
Diffstat (limited to 'extensions/common/features')
-rw-r--r-- | extensions/common/features/feature.cc | 8 | ||||
-rw-r--r-- | extensions/common/features/feature.h | 12 | ||||
-rw-r--r-- | extensions/common/features/simple_feature.cc | 22 | ||||
-rw-r--r-- | extensions/common/features/simple_feature.h | 17 | ||||
-rw-r--r-- | extensions/common/features/simple_feature_unittest.cc | 50 |
5 files changed, 101 insertions, 8 deletions
diff --git a/extensions/common/features/feature.cc b/extensions/common/features/feature.cc index e06a44a..48d384a 100644 --- a/extensions/common/features/feature.cc +++ b/extensions/common/features/feature.cc @@ -11,6 +11,7 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "extensions/common/extension.h" +#include "extensions/common/manifest.h" namespace extensions { @@ -43,6 +44,13 @@ Feature::Availability Feature::IsAvailableToExtension( extension->manifest_version()); } +Feature::Availability Feature::IsAvailableToEnvironment() const { + return IsAvailableToManifest("", // extension_id + Manifest::TYPE_UNKNOWN, + Manifest::INVALID_LOCATION, + -1); // manifest_version +} + Feature::Feature() : no_parent_(false) {} Feature::~Feature() {} diff --git a/extensions/common/features/feature.h b/extensions/common/features/feature.h index 0300ed0..6d3c8c5 100644 --- a/extensions/common/features/feature.h +++ b/extensions/common/features/feature.h @@ -73,6 +73,7 @@ class Feature { NOT_PRESENT, UNSUPPORTED_CHANNEL, FOUND_IN_BLACKLIST, + MISSING_COMMAND_LINE_SWITCH, }; // Container for AvailabiltyResult that also exposes a user-visible error @@ -149,6 +150,17 @@ class Feature { const GURL& url, Context context) const = 0; + // Returns true if the feature is available to the current environment, + // without needing to know information about an Extension or any other + // contextual information. Typically used when the Feature is purely + // configured by command line flags and/or Chrome channel. + // + // Generally try not to use this function. Even if you don't think a Feature + // relies on an Extension now - maybe it will, one day, so if there's an + // Extension available (or a runtime context, etc) then use the more targeted + // method instead. + Availability IsAvailableToEnvironment() const; + virtual bool IsIdInBlacklist(const std::string& extension_id) const = 0; virtual bool IsIdInWhitelist(const std::string& extension_id) const = 0; diff --git a/extensions/common/features/simple_feature.cc b/extensions/common/features/simple_feature.cc index e623bcf..c472ae8 100644 --- a/extensions/common/features/simple_feature.cc +++ b/extensions/common/features/simple_feature.cc @@ -248,13 +248,21 @@ std::string HashExtensionId(const std::string& extension_id) { return base::HexEncode(id_hash.c_str(), id_hash.length()); } +bool IsCommandLineSwitchEnabled(const std::string& switch_name) { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switch_name + "=1")) + return true; + if (command_line->HasSwitch(std::string("enable-") + switch_name)) + return true; + return false; +} + } // namespace SimpleFeature::SimpleFeature() : location_(UNSPECIFIED_LOCATION), min_manifest_version_(0), max_manifest_version_(0), - has_parent_(false), component_extensions_auto_granted_(true) {} SimpleFeature::~SimpleFeature() {} @@ -286,10 +294,11 @@ std::string SimpleFeature::Parse(const base::DictionaryValue* value) { no_parent_ = false; value->GetBoolean("noparent", &no_parent_); - component_extensions_auto_granted_ = true; value->GetBoolean("component_extensions_auto_granted", &component_extensions_auto_granted_); + value->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 // (Simple)Features being aware of their own heirarchy this is impossible. @@ -367,6 +376,11 @@ Feature::Availability SimpleFeature::IsAvailableToManifest( if (max_manifest_version_ != 0 && manifest_version > max_manifest_version_) return CreateAvailability(INVALID_MAX_MANIFEST_VERSION, type); + if (!command_line_switch_.empty() && + !IsCommandLineSwitchEnabled(command_line_switch_)) { + return CreateAvailability(MISSING_COMMAND_LINE_SWITCH, type); + } + for (FilterList::const_iterator filter_iter = filters_.begin(); filter_iter != filters_.end(); ++filter_iter) { @@ -481,6 +495,10 @@ std::string SimpleFeature::GetAvailabilityMessage( return base::StringPrintf( "'%s' is unsupported in this version of the platform.", name().c_str()); + case MISSING_COMMAND_LINE_SWITCH: + return base::StringPrintf( + "'%s' requires the '%s' command line switch to be enabled.", + name().c_str(), command_line_switch_.c_str()); } NOTREACHED(); diff --git a/extensions/common/features/simple_feature.h b/extensions/common/features/simple_feature.h index cb34108..27213de 100644 --- a/extensions/common/features/simple_feature.h +++ b/extensions/common/features/simple_feature.h @@ -41,6 +41,10 @@ class SimpleFeature : public Feature { // Accessors defined for testing. See comment above about not directly using // SimpleFeature in production code. + std::set<std::string>* blacklist() { return &blacklist_; } + std::set<std::string>* whitelist() { return &whitelist_; } + std::set<Manifest::Type>* extension_types() { return &extension_types_; } + std::set<Context>* contexts() { return &contexts_; } Location location() const { return location_; } void set_location(Location location) { location_ = location; } int min_manifest_version() const { return min_manifest_version_; } @@ -51,11 +55,12 @@ class SimpleFeature : public Feature { void set_max_manifest_version(int max_manifest_version) { max_manifest_version_ = max_manifest_version; } - - std::set<std::string>* blacklist() { return &blacklist_; } - std::set<std::string>* whitelist() { return &whitelist_; } - std::set<Manifest::Type>* extension_types() { return &extension_types_; } - std::set<Context>* contexts() { return &contexts_; } + const std::string& command_line_switch() const { + return command_line_switch_; + } + void set_command_line_switch(const std::string& command_line_switch) { + command_line_switch_ = command_line_switch; + } // Dependency resolution is a property of Features that is preferrably // handled internally to avoid temptation, but FeatureFilters may need @@ -141,8 +146,8 @@ class SimpleFeature : public Feature { std::set<Platform> platforms_; int min_manifest_version_; int max_manifest_version_; - bool has_parent_; bool component_extensions_auto_granted_; + std::string command_line_switch_; typedef std::vector<linked_ptr<SimpleFeatureFilter> > FilterList; FilterList filters_; diff --git a/extensions/common/features/simple_feature_unittest.cc b/extensions/common/features/simple_feature_unittest.cc index 40e1e2a..9f723fa 100644 --- a/extensions/common/features/simple_feature_unittest.cc +++ b/extensions/common/features/simple_feature_unittest.cc @@ -6,6 +6,7 @@ #include <string> +#include "base/command_line.h" #include "base/values.h" #include "extensions/common/manifest.h" #include "extensions/common/value_builder.h" @@ -37,6 +38,21 @@ bool LocationIsAvailable(SimpleFeature::Location feature_location, return availability_result == Feature::IS_AVAILABLE; } +class ScopedCommandLineSwitch { + public: + explicit ScopedCommandLineSwitch(const std::string& arg) + : original_command_line_(*base::CommandLine::ForCurrentProcess()) { + base::CommandLine::ForCurrentProcess()->AppendSwitch(arg); + } + + ~ScopedCommandLineSwitch() { + *base::CommandLine::ForCurrentProcess() = original_command_line_; + } + + private: + base::CommandLine original_command_line_; +}; + } // namespace TEST(SimpleFeatureTest, IsAvailableNullCase) { @@ -649,4 +665,38 @@ TEST(SimpleFeatureTest, Inheritance) { EXPECT_EQ(3, feature.max_manifest_version()); } +TEST(SimpleFeatureTest, CommandLineSwitch) { + SimpleFeature feature; + feature.set_command_line_switch("laser-beams"); + { + EXPECT_EQ(Feature::MISSING_COMMAND_LINE_SWITCH, + feature.IsAvailableToEnvironment().result()); + } + { + ScopedCommandLineSwitch scoped_switch("laser-beams"); + EXPECT_EQ(Feature::MISSING_COMMAND_LINE_SWITCH, + feature.IsAvailableToEnvironment().result()); + } + { + ScopedCommandLineSwitch scoped_switch("enable-laser-beams"); + EXPECT_EQ(Feature::IS_AVAILABLE, + feature.IsAvailableToEnvironment().result()); + } + { + ScopedCommandLineSwitch scoped_switch("disable-laser-beams"); + EXPECT_EQ(Feature::MISSING_COMMAND_LINE_SWITCH, + feature.IsAvailableToEnvironment().result()); + } + { + ScopedCommandLineSwitch scoped_switch("laser-beams=1"); + EXPECT_EQ(Feature::IS_AVAILABLE, + feature.IsAvailableToEnvironment().result()); + } + { + ScopedCommandLineSwitch scoped_switch("laser-beams=0"); + EXPECT_EQ(Feature::MISSING_COMMAND_LINE_SWITCH, + feature.IsAvailableToEnvironment().result()); + } +} + } // namespace extensions |