// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef EXTENSIONS_COMMON_FEATURES_SIMPLE_FEATURE_H_ #define EXTENSIONS_COMMON_FEATURES_SIMPLE_FEATURE_H_ #include #include #include #include #include #include #include "base/callback_forward.h" #include "base/gtest_prod_util.h" #include "base/lazy_instance.h" #include "base/macros.h" #include "base/optional.h" #include "base/values.h" #include "components/version_info/version_info.h" #include "extensions/common/extension.h" #include "extensions/common/features/feature.h" #include "extensions/common/features/feature_session_type.h" #include "extensions/common/manifest.h" namespace extensions { class FeatureProviderTest; class ExtensionAPITest; class SimpleFeature : public Feature { public: // Used by tests to override the cached --whitelisted-extension-id. // NOTE: Not thread-safe! This is because it sets extension id on global // singleton during its construction and destruction. class ScopedThreadUnsafeWhitelistForTest { public: explicit ScopedThreadUnsafeWhitelistForTest(const std::string& id); ~ScopedThreadUnsafeWhitelistForTest(); private: std::string previous_id_; DISALLOW_COPY_AND_ASSIGN(ScopedThreadUnsafeWhitelistForTest); }; SimpleFeature(); ~SimpleFeature() override; Availability IsAvailableToContext(const Extension* extension, Context context) const { return IsAvailableToContext(extension, context, GURL()); } Availability IsAvailableToContext(const Extension* extension, Context context, Platform platform) const { return IsAvailableToContext(extension, context, GURL(), platform); } Availability IsAvailableToContext(const Extension* extension, Context context, const GURL& url) const { return IsAvailableToContext(extension, context, url, GetCurrentPlatform()); } // extension::Feature: Availability IsAvailableToManifest(const HashedExtensionId& hashed_id, Manifest::Type type, Manifest::Location location, int manifest_version, Platform platform) const override; Availability IsAvailableToContext(const Extension* extension, Context context, const GURL& url, Platform platform) const override; Availability IsAvailableToEnvironment() const override; bool IsInternal() const override; bool IsIdInBlacklist(const HashedExtensionId& hashed_id) const override; bool IsIdInWhitelist(const HashedExtensionId& hashed_id) const override; static bool IsIdInArray(const std::string& extension_id, const char* const array[], size_t array_length); // Similar to Manifest::Location, these are the classes of locations // supported in feature files. These should only be used in this class and in // generated files. enum Location { COMPONENT_LOCATION, EXTERNAL_COMPONENT_LOCATION, POLICY_LOCATION, }; // Setters used by generated code to create the feature. // NOTE: These setters use base::StringPiece and std::initalizer_list rather // than std::string and std::vector for binary size reasons. Using STL types // directly in the header means that code that doesn't already have that exact // type ends up triggering many implicit conversions which are all inlined. void set_blacklist(std::initializer_list blacklist); void set_channel(version_info::Channel channel) { channel_ = channel; } void set_command_line_switch(base::StringPiece command_line_switch); void set_component_extensions_auto_granted(bool granted) { component_extensions_auto_granted_ = granted; } void set_contexts(std::initializer_list contexts); void set_dependencies(std::initializer_list dependencies); void set_extension_types(std::initializer_list types); void set_session_types(std::initializer_list types); void set_internal(bool is_internal) { is_internal_ = is_internal; } void set_location(Location location) { location_ = location; } // set_matches() is an exception to pass-by-value since we construct an // URLPatternSet from the vector of strings. // TODO(devlin): Pass in an URLPatternSet directly. void set_matches(std::initializer_list matches); void set_max_manifest_version(int max_manifest_version) { max_manifest_version_ = max_manifest_version; } void set_min_manifest_version(int min_manifest_version) { min_manifest_version_ = min_manifest_version; } void set_noparent(bool no_parent) { no_parent_ = no_parent; } void set_platforms(std::initializer_list platforms); void set_whitelist(std::initializer_list whitelist); protected: // Accessors used by subclasses in feature verification. const std::vector& blacklist() const { return blacklist_; } const std::vector& whitelist() const { return whitelist_; } const std::vector& extension_types() const { return extension_types_; } const std::vector& platforms() const { return platforms_; } const std::vector& contexts() const { return contexts_; } const std::vector& dependencies() const { return dependencies_; } const base::Optional channel() const { return channel_; } const base::Optional location() const { return location_; } const base::Optional min_manifest_version() const { return min_manifest_version_; } const base::Optional max_manifest_version() const { return max_manifest_version_; } const base::Optional& command_line_switch() const { return command_line_switch_; } bool component_extensions_auto_granted() const { return component_extensions_auto_granted_; } const URLPatternSet& matches() const { return matches_; } std::string GetAvailabilityMessage(AvailabilityResult result, Manifest::Type type, const GURL& url, Context context, version_info::Channel channel, FeatureSessionType session_type) const; // Handy utilities which construct the correct availability message. Availability CreateAvailability(AvailabilityResult result) const; Availability CreateAvailability(AvailabilityResult result, Manifest::Type type) const; Availability CreateAvailability(AvailabilityResult result, const GURL& url) const; Availability CreateAvailability(AvailabilityResult result, Context context) const; Availability CreateAvailability(AvailabilityResult result, version_info::Channel channel) const; Availability CreateAvailability(AvailabilityResult result, FeatureSessionType session_type) const; private: friend struct FeatureComparator; FRIEND_TEST_ALL_PREFIXES(FeatureProviderTest, ManifestFeatureTypes); FRIEND_TEST_ALL_PREFIXES(FeatureProviderTest, PermissionFeatureTypes); FRIEND_TEST_ALL_PREFIXES(ExtensionAPITest, DefaultConfigurationFeatures); FRIEND_TEST_ALL_PREFIXES(FeaturesGenerationTest, FeaturesTest); // Holds String to Enum value mappings. struct Mappings; static bool IsIdInList(const HashedExtensionId& hashed_id, const std::vector& list); bool MatchesManifestLocation(Manifest::Location manifest_location) const; // Checks if the feature is allowed in a session of type |session_type| // (based on session type feature restrictions). bool MatchesSessionTypes(FeatureSessionType session_type) const; Availability CheckDependencies( const base::Callback& checker) const; static bool IsValidExtensionId(const std::string& extension_id); static bool IsValidHashedExtensionId(const HashedExtensionId& hashed_id); // Returns the availability of the feature with respect to the basic // environment Chrome is running in. Availability GetEnvironmentAvailability( Platform platform, version_info::Channel channel, FeatureSessionType session_type) const; // Returns the availability of the feature with respect to a given extension's // properties. Availability GetManifestAvailability(const HashedExtensionId& hashed_id, Manifest::Type type, Manifest::Location location, int manifest_version) const; // Returns the availability of the feature with respect to a given context. Availability GetContextAvailability(Context context, const GURL& url) const; // For clarity and consistency, we handle the default value of each of these // members the same way: it matches everything. It is up to the higher level // code that reads Features out of static data to validate that data and set // sensible defaults. std::vector blacklist_; std::vector whitelist_; std::vector dependencies_; std::vector extension_types_; std::vector session_types_; std::vector contexts_; std::vector platforms_; URLPatternSet matches_; base::Optional location_; base::Optional min_manifest_version_; base::Optional max_manifest_version_; base::Optional command_line_switch_; base::Optional channel_; // Whether to ignore channel-based restrictions (such as because the user has // enabled experimental extension APIs). Note: this is lazily calculated, and // then cached. mutable base::Optional ignore_channel_; bool component_extensions_auto_granted_; bool is_internal_; DISALLOW_COPY_AND_ASSIGN(SimpleFeature); }; } // namespace extensions #endif // EXTENSIONS_COMMON_FEATURES_SIMPLE_FEATURE_H_