| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "extensions/common/features/simple_feature.h" | 5 #include "extensions/common/features/simple_feature.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 14 #include "base/test/scoped_command_line.h" | 14 #include "base/test/scoped_command_line.h" |
| 15 #include "base/values.h" | 15 #include "base/values.h" |
| 16 #include "extensions/common/features/api_feature.h" |
| 16 #include "extensions/common/features/complex_feature.h" | 17 #include "extensions/common/features/complex_feature.h" |
| 17 #include "extensions/common/features/feature_channel.h" | 18 #include "extensions/common/features/feature_channel.h" |
| 18 #include "extensions/common/features/json_feature_provider.h" | 19 #include "extensions/common/features/json_feature_provider.h" |
| 19 #include "extensions/common/features/permission_feature.h" | 20 #include "extensions/common/features/permission_feature.h" |
| 20 #include "extensions/common/manifest.h" | 21 #include "extensions/common/manifest.h" |
| 21 #include "extensions/common/value_builder.h" | 22 #include "extensions/common/value_builder.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 23 | 24 |
| 24 namespace extensions { | 25 namespace extensions { |
| 25 | 26 |
| (...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 837 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | 838 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, |
| 838 IsAvailableInChannel("trunk", version_info::Channel::DEV)); | 839 IsAvailableInChannel("trunk", version_info::Channel::DEV)); |
| 839 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | 840 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, |
| 840 IsAvailableInChannel("trunk", version_info::Channel::BETA)); | 841 IsAvailableInChannel("trunk", version_info::Channel::BETA)); |
| 841 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | 842 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, |
| 842 IsAvailableInChannel("trunk", version_info::Channel::STABLE)); | 843 IsAvailableInChannel("trunk", version_info::Channel::STABLE)); |
| 843 } | 844 } |
| 844 | 845 |
| 845 // Tests the validation of features with channel entries. | 846 // Tests the validation of features with channel entries. |
| 846 TEST_F(SimpleFeatureTest, FeatureValidation) { | 847 TEST_F(SimpleFeatureTest, FeatureValidation) { |
| 847 std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue()); | 848 std::string error; |
| 848 | 849 { |
| 849 base::DictionaryValue* feature1 = new base::DictionaryValue(); | 850 PermissionFeature feature; |
| 850 feature1->SetString("channel", "trunk"); | 851 feature.channel_.reset( |
| 851 value->Set("feature1", feature1); | 852 new version_info::Channel(version_info::Channel::UNKNOWN)); |
| 852 | 853 // The feature won't validate because it lacks an extension type. |
| 853 base::DictionaryValue* feature2 = new base::DictionaryValue(); | 854 EXPECT_FALSE(feature.Validate(&error)); |
| 854 feature2->SetString("channel", "trunk"); | 855 // If we add one, it works. |
| 855 base::ListValue* extension_types = new base::ListValue(); | 856 feature.extension_types_.push_back(Manifest::TYPE_EXTENSION); |
| 856 extension_types->AppendString("extension"); | 857 EXPECT_TRUE(feature.Validate(&error)); |
| 857 feature2->Set("extension_types", extension_types); | 858 // Remove the channel, and feature1 won't validate. |
| 858 base::ListValue* contexts = new base::ListValue(); | 859 feature.channel_.reset(); |
| 859 contexts->AppendString("blessed_extension"); | 860 EXPECT_FALSE(feature.Validate(&error)); |
| 860 feature2->Set("contexts", contexts); | 861 } |
| 861 value->Set("feature2", feature2); | 862 { |
| 862 | 863 PermissionFeature feature; |
| 863 std::unique_ptr<JSONFeatureProvider> provider( | 864 feature.channel_.reset( |
| 864 new JSONFeatureProvider(*value, CreateFeature<PermissionFeature>)); | 865 new version_info::Channel(version_info::Channel::UNKNOWN)); |
| 865 | 866 feature.extension_types_.push_back(Manifest::TYPE_EXTENSION); |
| 866 // feature1 won't validate because it lacks an extension type. | 867 feature.contexts_.push_back(Feature::BLESSED_EXTENSION_CONTEXT); |
| 867 EXPECT_FALSE(provider->GetFeature("feature1")); | 868 // The feature won't validate because of the presence of "contexts". |
| 868 | 869 EXPECT_FALSE(feature.Validate(&error)); |
| 869 // If we add one, it works. | 870 feature.contexts_.clear(); |
| 870 feature1->Set("extension_types", extension_types->DeepCopy()); | 871 EXPECT_TRUE(feature.Validate(&error)); |
| 871 provider.reset( | 872 } |
| 872 new JSONFeatureProvider(*value, CreateFeature<PermissionFeature>)); | 873 { |
| 873 EXPECT_TRUE(provider->GetFeature("feature1")); | 874 APIFeature feature; |
| 874 | 875 feature.channel_.reset( |
| 875 // Remove the channel, and feature1 won't validate. | 876 new version_info::Channel(version_info::Channel::STABLE)); |
| 876 feature1->Remove("channel", NULL); | 877 // API features require contexts. |
| 877 provider.reset( | 878 EXPECT_FALSE(feature.Validate(&error)); |
| 878 new JSONFeatureProvider(*value, CreateFeature<PermissionFeature>)); | 879 feature.contexts_.push_back(Feature::CONTENT_SCRIPT_CONTEXT); |
| 879 EXPECT_FALSE(provider->GetFeature("feature1")); | 880 EXPECT_TRUE(feature.Validate(&error)); |
| 880 | 881 } |
| 881 // feature2 won't validate because of the presence of "contexts". | |
| 882 EXPECT_FALSE(provider->GetFeature("feature2")); | |
| 883 | |
| 884 // If we remove it, it works. | |
| 885 feature2->Remove("contexts", NULL); | |
| 886 provider.reset( | |
| 887 new JSONFeatureProvider(*value, CreateFeature<PermissionFeature>)); | |
| 888 EXPECT_TRUE(provider->GetFeature("feature2")); | |
| 889 } | 882 } |
| 890 | 883 |
| 891 // Tests simple feature availability across channels. | 884 // Tests simple feature availability across channels. |
| 892 TEST_F(SimpleFeatureTest, SimpleFeatureAvailability) { | 885 TEST_F(SimpleFeatureTest, SimpleFeatureAvailability) { |
| 893 std::unique_ptr<base::DictionaryValue> rule( | 886 std::unique_ptr<ComplexFeature> complex_feature; |
| 894 DictionaryBuilder() | 887 { |
| 895 .Set("feature1", | 888 std::unique_ptr<SimpleFeature> feature1(CreateFeature<SimpleFeature>()); |
| 896 ListBuilder() | 889 feature1->channel_.reset( |
| 897 .Append(DictionaryBuilder() | 890 new version_info::Channel(version_info::Channel::BETA)); |
| 898 .Set("channel", "beta") | 891 feature1->extension_types_.push_back(Manifest::TYPE_EXTENSION); |
| 899 .Set("extension_types", | 892 std::unique_ptr<SimpleFeature> feature2(CreateFeature<SimpleFeature>()); |
| 900 ListBuilder().Append("extension").Build()) | 893 feature2->channel_.reset( |
| 901 .Build()) | 894 new version_info::Channel(version_info::Channel::BETA)); |
| 902 .Append(DictionaryBuilder() | 895 feature2->extension_types_.push_back(Manifest::TYPE_LEGACY_PACKAGED_APP); |
| 903 .Set("channel", "beta") | 896 std::unique_ptr<ComplexFeature::FeatureList> list( |
| 904 .Set("extension_types", | 897 new ComplexFeature::FeatureList()); |
| 905 ListBuilder() | 898 list->push_back(std::move(feature1)); |
| 906 .Append("legacy_packaged_app") | 899 list->push_back(std::move(feature2)); |
| 907 .Build()) | 900 complex_feature.reset(new ComplexFeature(std::move(list))); |
| 908 .Build()) | 901 } |
| 909 .Build()) | |
| 910 .Build()); | |
| 911 | 902 |
| 912 std::unique_ptr<JSONFeatureProvider> provider( | 903 Feature* feature = static_cast<Feature*>(complex_feature.get()); |
| 913 new JSONFeatureProvider(*rule, CreateFeature<SimpleFeature>)); | |
| 914 | |
| 915 Feature* feature = provider->GetFeature("feature1"); | |
| 916 EXPECT_TRUE(feature); | |
| 917 | |
| 918 // Make sure both rules are applied correctly. | 904 // Make sure both rules are applied correctly. |
| 919 { | 905 { |
| 920 ScopedCurrentChannel current_channel(version_info::Channel::BETA); | 906 ScopedCurrentChannel current_channel(version_info::Channel::BETA); |
| 921 EXPECT_EQ( | 907 EXPECT_EQ( |
| 922 Feature::IS_AVAILABLE, | 908 Feature::IS_AVAILABLE, |
| 923 feature->IsAvailableToManifest("1", | 909 feature->IsAvailableToManifest("1", |
| 924 Manifest::TYPE_EXTENSION, | 910 Manifest::TYPE_EXTENSION, |
| 925 Manifest::INVALID_LOCATION, | 911 Manifest::INVALID_LOCATION, |
| 926 Feature::UNSPECIFIED_PLATFORM).result()); | 912 Feature::UNSPECIFIED_PLATFORM).result()); |
| 927 EXPECT_EQ( | 913 EXPECT_EQ( |
| (...skipping 15 matching lines...) Expand all Loading... |
| 943 Feature::IS_AVAILABLE, | 929 Feature::IS_AVAILABLE, |
| 944 feature->IsAvailableToManifest("2", | 930 feature->IsAvailableToManifest("2", |
| 945 Manifest::TYPE_LEGACY_PACKAGED_APP, | 931 Manifest::TYPE_LEGACY_PACKAGED_APP, |
| 946 Manifest::INVALID_LOCATION, | 932 Manifest::INVALID_LOCATION, |
| 947 Feature::UNSPECIFIED_PLATFORM).result()); | 933 Feature::UNSPECIFIED_PLATFORM).result()); |
| 948 } | 934 } |
| 949 } | 935 } |
| 950 | 936 |
| 951 // Tests complex feature availability across channels. | 937 // Tests complex feature availability across channels. |
| 952 TEST_F(SimpleFeatureTest, ComplexFeatureAvailability) { | 938 TEST_F(SimpleFeatureTest, ComplexFeatureAvailability) { |
| 953 std::unique_ptr<ComplexFeature::FeatureList> features( | 939 std::unique_ptr<ComplexFeature> complex_feature; |
| 954 new ComplexFeature::FeatureList()); | 940 { |
| 941 // Rule: "extension", channel trunk. |
| 942 std::unique_ptr<SimpleFeature> feature1(CreateFeature<SimpleFeature>()); |
| 943 feature1->channel_.reset( |
| 944 new version_info::Channel(version_info::Channel::UNKNOWN)); |
| 945 feature1->extension_types_.push_back(Manifest::TYPE_EXTENSION); |
| 946 std::unique_ptr<SimpleFeature> feature2(CreateFeature<SimpleFeature>()); |
| 947 // Rule: "legacy_packaged_app", channel stable. |
| 948 feature2->channel_.reset( |
| 949 new version_info::Channel(version_info::Channel::STABLE)); |
| 950 feature2->extension_types_.push_back(Manifest::TYPE_LEGACY_PACKAGED_APP); |
| 951 std::unique_ptr<ComplexFeature::FeatureList> list( |
| 952 new ComplexFeature::FeatureList()); |
| 953 list->push_back(std::move(feature1)); |
| 954 list->push_back(std::move(feature2)); |
| 955 complex_feature.reset(new ComplexFeature(std::move(list))); |
| 956 } |
| 955 | 957 |
| 956 // Rule: "extension", channel trunk. | 958 Feature* feature = static_cast<Feature*>(complex_feature.get()); |
| 957 std::unique_ptr<SimpleFeature> simple_feature(CreateFeature<SimpleFeature>()); | |
| 958 std::unique_ptr<base::DictionaryValue> rule( | |
| 959 DictionaryBuilder() | |
| 960 .Set("channel", "trunk") | |
| 961 .Set("extension_types", ListBuilder().Append("extension").Build()) | |
| 962 .Build()); | |
| 963 simple_feature->Parse(rule.get()); | |
| 964 features->push_back(std::move(simple_feature)); | |
| 965 | |
| 966 // Rule: "legacy_packaged_app", channel stable. | |
| 967 simple_feature.reset(CreateFeature<SimpleFeature>()); | |
| 968 rule = DictionaryBuilder() | |
| 969 .Set("channel", "stable") | |
| 970 .Set("extension_types", | |
| 971 ListBuilder().Append("legacy_packaged_app").Build()) | |
| 972 .Build(); | |
| 973 simple_feature->Parse(rule.get()); | |
| 974 features->push_back(std::move(simple_feature)); | |
| 975 | |
| 976 std::unique_ptr<ComplexFeature> feature( | |
| 977 new ComplexFeature(std::move(features))); | |
| 978 | |
| 979 // Test match 1st rule. | |
| 980 { | 959 { |
| 981 ScopedCurrentChannel current_channel(version_info::Channel::UNKNOWN); | 960 ScopedCurrentChannel current_channel(version_info::Channel::UNKNOWN); |
| 982 EXPECT_EQ( | 961 EXPECT_EQ(Feature::IS_AVAILABLE, |
| 983 Feature::IS_AVAILABLE, | 962 feature |
| 984 feature->IsAvailableToManifest("1", | 963 ->IsAvailableToManifest("1", Manifest::TYPE_EXTENSION, |
| 985 Manifest::TYPE_EXTENSION, | 964 Manifest::INVALID_LOCATION, |
| 986 Manifest::INVALID_LOCATION, | 965 Feature::UNSPECIFIED_PLATFORM) |
| 987 Feature::UNSPECIFIED_PLATFORM, | 966 .result()); |
| 988 Feature::GetCurrentPlatform()).result()); | |
| 989 } | 967 } |
| 990 | |
| 991 // Test match 2nd rule. | |
| 992 { | 968 { |
| 993 ScopedCurrentChannel current_channel(version_info::Channel::BETA); | 969 ScopedCurrentChannel current_channel(version_info::Channel::BETA); |
| 994 EXPECT_EQ( | 970 EXPECT_EQ(Feature::IS_AVAILABLE, |
| 995 Feature::IS_AVAILABLE, | 971 feature |
| 996 feature->IsAvailableToManifest("2", | 972 ->IsAvailableToManifest( |
| 997 Manifest::TYPE_LEGACY_PACKAGED_APP, | 973 "2", Manifest::TYPE_LEGACY_PACKAGED_APP, |
| 998 Manifest::INVALID_LOCATION, | 974 Manifest::INVALID_LOCATION, Feature::UNSPECIFIED_PLATFORM) |
| 999 Feature::UNSPECIFIED_PLATFORM, | 975 .result()); |
| 1000 Feature::GetCurrentPlatform()).result()); | |
| 1001 } | 976 } |
| 1002 | |
| 1003 // Test feature not available to extensions above channel unknown. | |
| 1004 { | 977 { |
| 1005 ScopedCurrentChannel current_channel(version_info::Channel::BETA); | 978 ScopedCurrentChannel current_channel(version_info::Channel::BETA); |
| 1006 EXPECT_NE( | 979 EXPECT_NE(Feature::IS_AVAILABLE, |
| 1007 Feature::IS_AVAILABLE, | 980 feature |
| 1008 feature->IsAvailableToManifest("1", | 981 ->IsAvailableToManifest("1", Manifest::TYPE_EXTENSION, |
| 1009 Manifest::TYPE_EXTENSION, | 982 Manifest::INVALID_LOCATION, |
| 1010 Manifest::INVALID_LOCATION, | 983 Feature::UNSPECIFIED_PLATFORM) |
| 1011 Feature::UNSPECIFIED_PLATFORM, | 984 .result()); |
| 1012 Feature::GetCurrentPlatform()).result()); | |
| 1013 } | 985 } |
| 1014 } | 986 } |
| 1015 | 987 |
| 1016 } // namespace extensions | 988 } // namespace extensions |
| OLD | NEW |