summaryrefslogtreecommitdiffstats
path: root/extensions/common/features
diff options
context:
space:
mode:
authorkalman <kalman@chromium.org>2014-12-12 14:04:23 -0800
committerCommit bot <commit-bot@chromium.org>2014-12-12 22:04:50 +0000
commitae342c9a0fa8a3c55bc89bf9a1543ad85f7d404f (patch)
tree55eaca44eec5fb3bad91de53987b5b701d8119ea /extensions/common/features
parent7547705543d6b711a166e513a43a4e43f93fd254 (diff)
downloadchromium_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.cc8
-rw-r--r--extensions/common/features/feature.h12
-rw-r--r--extensions/common/features/simple_feature.cc22
-rw-r--r--extensions/common/features/simple_feature.h17
-rw-r--r--extensions/common/features/simple_feature_unittest.cc50
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