| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/common/extensions/api/extension_api.h" | 5 #include "chrome/common/extensions/api/extension_api.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| 11 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
| 12 #include "base/json/json_reader.h" |
| 12 #include "base/json/json_writer.h" | 13 #include "base/json/json_writer.h" |
| 13 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
| 14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 15 #include "base/path_service.h" | 16 #include "base/path_service.h" |
| 16 #include "base/values.h" | 17 #include "base/values.h" |
| 17 #include "chrome/common/chrome_paths.h" | 18 #include "chrome/common/chrome_paths.h" |
| 18 #include "chrome/common/extensions/extension.h" | 19 #include "chrome/common/extensions/extension.h" |
| 20 #include "chrome/common/extensions/features/api_feature.h" |
| 21 #include "chrome/common/extensions/features/base_feature_provider.h" |
| 19 #include "chrome/common/extensions/features/simple_feature.h" | 22 #include "chrome/common/extensions/features/simple_feature.h" |
| 20 #include "chrome/common/extensions/manifest.h" | 23 #include "chrome/common/extensions/manifest.h" |
| 21 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 22 | 25 |
| 23 namespace extensions { | 26 namespace extensions { |
| 24 namespace { | 27 namespace { |
| 25 | 28 |
| 29 SimpleFeature* CreateAPIFeature() { |
| 30 return new APIFeature(); |
| 31 } |
| 32 |
| 26 class TestFeatureProvider : public FeatureProvider { | 33 class TestFeatureProvider : public FeatureProvider { |
| 27 public: | 34 public: |
| 28 explicit TestFeatureProvider(Feature::Context context) | 35 explicit TestFeatureProvider(Feature::Context context) |
| 29 : context_(context) { | 36 : context_(context) { |
| 30 } | 37 } |
| 31 | 38 |
| 32 virtual Feature* GetFeature(const std::string& name) OVERRIDE { | 39 virtual Feature* GetFeature(const std::string& name) OVERRIDE { |
| 33 SimpleFeature* result = new SimpleFeature(); | 40 SimpleFeature* result = new SimpleFeature(); |
| 34 result->set_name(name); | 41 result->set_name(name); |
| 35 result->extension_types()->insert(Manifest::TYPE_EXTENSION); | 42 result->extension_types()->insert(Manifest::TYPE_EXTENSION); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 EXPECT_FALSE(extension_api->IsPrivileged("app.isInstalled")); | 125 EXPECT_FALSE(extension_api->IsPrivileged("app.isInstalled")); |
| 119 EXPECT_FALSE(extension_api->IsPrivileged("storage.local")); | 126 EXPECT_FALSE(extension_api->IsPrivileged("storage.local")); |
| 120 EXPECT_FALSE(extension_api->IsPrivileged("storage.local.onChanged")); | 127 EXPECT_FALSE(extension_api->IsPrivileged("storage.local.onChanged")); |
| 121 EXPECT_FALSE(extension_api->IsPrivileged("storage.local.set")); | 128 EXPECT_FALSE(extension_api->IsPrivileged("storage.local.set")); |
| 122 EXPECT_FALSE(extension_api->IsPrivileged("storage.local.MAX_ITEMS")); | 129 EXPECT_FALSE(extension_api->IsPrivileged("storage.local.MAX_ITEMS")); |
| 123 EXPECT_FALSE(extension_api->IsPrivileged("storage.set")); | 130 EXPECT_FALSE(extension_api->IsPrivileged("storage.set")); |
| 124 } | 131 } |
| 125 | 132 |
| 126 TEST(ExtensionAPI, IsPrivilegedFeatures) { | 133 TEST(ExtensionAPI, IsPrivilegedFeatures) { |
| 127 struct { | 134 struct { |
| 128 std::string filename; | |
| 129 std::string api_full_name; | 135 std::string api_full_name; |
| 130 bool expect_is_privilged; | 136 bool expect_is_privilged; |
| 131 Feature::Context test2_contexts; | 137 Feature::Context test2_contexts; |
| 132 } test_data[] = { | 138 } test_data[] = { |
| 133 { "is_privileged_features_1.json", "test", false, | 139 { "test1", false, Feature::UNSPECIFIED_CONTEXT }, |
| 134 Feature::UNSPECIFIED_CONTEXT }, | 140 { "test2", true, Feature::UNSPECIFIED_CONTEXT }, |
| 135 { "is_privileged_features_2.json", "test", true, | 141 { "test3", false, Feature::UNSPECIFIED_CONTEXT }, |
| 136 Feature::UNSPECIFIED_CONTEXT }, | 142 { "test4.bar", false, Feature::UNSPECIFIED_CONTEXT }, |
| 137 { "is_privileged_features_3.json", "test", false, | 143 { "test5.foo", true, Feature::BLESSED_EXTENSION_CONTEXT }, |
| 138 Feature::UNSPECIFIED_CONTEXT }, | 144 { "test5.foo", false, Feature::UNBLESSED_EXTENSION_CONTEXT }, |
| 139 { "is_privileged_features_4.json", "test.bar", false, | 145 { "test5.bar", true, Feature::BLESSED_EXTENSION_CONTEXT }, |
| 140 Feature::UNSPECIFIED_CONTEXT }, | 146 { "test5.bar", false, Feature::UNBLESSED_EXTENSION_CONTEXT } |
| 141 { "is_privileged_features_5.json", "test.bar", true, | |
| 142 Feature::BLESSED_EXTENSION_CONTEXT }, | |
| 143 { "is_privileged_features_5.json", "test.bar", false, | |
| 144 Feature::UNBLESSED_EXTENSION_CONTEXT } | |
| 145 }; | 147 }; |
| 146 | 148 |
| 149 base::FilePath api_features_path; |
| 150 PathService::Get(chrome::DIR_TEST_DATA, &api_features_path); |
| 151 api_features_path = api_features_path.AppendASCII("extensions") |
| 152 .AppendASCII("extension_api_unittest") |
| 153 .AppendASCII("api_features.json"); |
| 154 |
| 155 std::string api_features_str; |
| 156 ASSERT_TRUE(file_util::ReadFileToString( |
| 157 api_features_path, &api_features_str)) << "api_features.json"; |
| 158 |
| 159 base::DictionaryValue* value = static_cast<DictionaryValue*>( |
| 160 base::JSONReader::Read(api_features_str)); |
| 161 BaseFeatureProvider api_feature_provider(*value, NULL); |
| 162 |
| 147 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { | 163 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
| 148 base::FilePath manifest_path; | |
| 149 PathService::Get(chrome::DIR_TEST_DATA, &manifest_path); | |
| 150 manifest_path = manifest_path.AppendASCII("extensions") | |
| 151 .AppendASCII("extension_api_unittest") | |
| 152 .AppendASCII(test_data[i].filename); | |
| 153 | |
| 154 std::string manifest_str; | |
| 155 ASSERT_TRUE(file_util::ReadFileToString(manifest_path, &manifest_str)) | |
| 156 << test_data[i].filename; | |
| 157 | |
| 158 ExtensionAPI api; | 164 ExtensionAPI api; |
| 159 api.RegisterSchema("test", manifest_str); | 165 api.RegisterDependencyProvider("api", &api_feature_provider); |
| 160 | 166 |
| 161 TestFeatureProvider test2_provider(test_data[i].test2_contexts); | 167 TestFeatureProvider test2_provider(test_data[i].test2_contexts); |
| 168 |
| 162 if (test_data[i].test2_contexts != Feature::UNSPECIFIED_CONTEXT) { | 169 if (test_data[i].test2_contexts != Feature::UNSPECIFIED_CONTEXT) { |
| 163 api.RegisterDependencyProvider("test2", &test2_provider); | 170 api.RegisterDependencyProvider("test2", &test2_provider); |
| 164 } | 171 } |
| 165 | 172 |
| 166 EXPECT_EQ(test_data[i].expect_is_privilged, | 173 EXPECT_EQ(test_data[i].expect_is_privilged, |
| 167 api.IsPrivileged(test_data[i].api_full_name)) << i; | 174 api.IsPrivileged(test_data[i].api_full_name)) << i; |
| 168 } | 175 } |
| 169 } | 176 } |
| 170 | 177 |
| 171 TEST(ExtensionAPI, LazyGetSchema) { | 178 TEST(ExtensionAPI, LazyGetSchema) { |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 std::string api_name = api->GetAPINameFromFullName(test_data[i].input, | 376 std::string api_name = api->GetAPINameFromFullName(test_data[i].input, |
| 370 &child_name); | 377 &child_name); |
| 371 EXPECT_EQ(test_data[i].api_name, api_name) << test_data[i].input; | 378 EXPECT_EQ(test_data[i].api_name, api_name) << test_data[i].input; |
| 372 EXPECT_EQ(test_data[i].child_name, child_name) << test_data[i].input; | 379 EXPECT_EQ(test_data[i].child_name, child_name) << test_data[i].input; |
| 373 } | 380 } |
| 374 } | 381 } |
| 375 | 382 |
| 376 TEST(ExtensionAPI, DefaultConfigurationFeatures) { | 383 TEST(ExtensionAPI, DefaultConfigurationFeatures) { |
| 377 scoped_ptr<ExtensionAPI> api(ExtensionAPI::CreateWithDefaultConfiguration()); | 384 scoped_ptr<ExtensionAPI> api(ExtensionAPI::CreateWithDefaultConfiguration()); |
| 378 | 385 |
| 379 SimpleFeature* bookmarks = | 386 SimpleFeature* bookmarks = static_cast<SimpleFeature*>( |
| 380 static_cast<SimpleFeature*>(api->GetFeature("bookmarks")); | 387 api->GetFeatureDependency("api:bookmarks")); |
| 381 SimpleFeature* bookmarks_create = | 388 SimpleFeature* bookmarks_create = static_cast<SimpleFeature*>( |
| 382 static_cast<SimpleFeature*>(api->GetFeature("bookmarks.create")); | 389 api->GetFeatureDependency("api:bookmarks.create")); |
| 383 | 390 |
| 384 struct { | 391 struct { |
| 385 SimpleFeature* feature; | 392 SimpleFeature* feature; |
| 386 // TODO(aa): More stuff to test over time. | 393 // TODO(aa): More stuff to test over time. |
| 387 } test_data[] = { | 394 } test_data[] = { |
| 388 { bookmarks }, | 395 { bookmarks }, |
| 389 { bookmarks_create } | 396 { bookmarks_create } |
| 390 }; | 397 }; |
| 391 | 398 |
| 392 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { | 399 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
| 393 SimpleFeature* feature = test_data[i].feature; | 400 SimpleFeature* feature = test_data[i].feature; |
| 394 ASSERT_TRUE(feature) << i; | 401 ASSERT_TRUE(feature) << i; |
| 395 | 402 |
| 396 EXPECT_TRUE(feature->whitelist()->empty()); | 403 EXPECT_TRUE(feature->whitelist()->empty()); |
| 397 EXPECT_TRUE(feature->extension_types()->empty()); | 404 EXPECT_TRUE(feature->extension_types()->empty()); |
| 398 | 405 |
| 399 EXPECT_EQ(1u, feature->GetContexts()->size()); | 406 EXPECT_EQ(1u, feature->GetContexts()->size()); |
| 400 EXPECT_TRUE(feature->GetContexts()->count( | 407 EXPECT_TRUE(feature->GetContexts()->count( |
| 401 Feature::BLESSED_EXTENSION_CONTEXT)); | 408 Feature::BLESSED_EXTENSION_CONTEXT)); |
| 402 | 409 |
| 403 EXPECT_EQ(Feature::UNSPECIFIED_LOCATION, feature->location()); | 410 EXPECT_EQ(Feature::UNSPECIFIED_LOCATION, feature->location()); |
| 404 EXPECT_EQ(Feature::UNSPECIFIED_PLATFORM, feature->platform()); | 411 EXPECT_EQ(Feature::UNSPECIFIED_PLATFORM, feature->platform()); |
| 405 EXPECT_EQ(0, feature->min_manifest_version()); | 412 EXPECT_EQ(0, feature->min_manifest_version()); |
| 406 EXPECT_EQ(0, feature->max_manifest_version()); | 413 EXPECT_EQ(0, feature->max_manifest_version()); |
| 407 } | 414 } |
| 408 } | 415 } |
| 409 | 416 |
| 410 TEST(ExtensionAPI, FeaturesRequireContexts) { | 417 TEST(ExtensionAPI, FeaturesRequireContexts) { |
| 411 scoped_ptr<base::ListValue> schema1(new base::ListValue()); | 418 // TODO(cduvall): Make this check API featues. |
| 412 base::DictionaryValue* feature_definition = new base::DictionaryValue(); | 419 scoped_ptr<base::DictionaryValue> api_features1(new base::DictionaryValue()); |
| 413 schema1->Append(feature_definition); | 420 scoped_ptr<base::DictionaryValue> api_features2(new base::DictionaryValue()); |
| 414 feature_definition->SetString("namespace", "test"); | 421 base::DictionaryValue* test1 = new base::DictionaryValue(); |
| 415 feature_definition->SetBoolean("uses_feature_system", true); | 422 base::DictionaryValue* test2 = new base::DictionaryValue(); |
| 416 | |
| 417 scoped_ptr<base::ListValue> schema2(schema1->DeepCopy()); | |
| 418 | |
| 419 base::ListValue* contexts = new base::ListValue(); | 423 base::ListValue* contexts = new base::ListValue(); |
| 420 contexts->Append(new base::StringValue("content_script")); | 424 contexts->Append(new base::StringValue("content_script")); |
| 421 feature_definition->Set("contexts", contexts); | 425 test1->Set("contexts", contexts); |
| 426 api_features1->Set("test", test1); |
| 427 api_features2->Set("test", test2); |
| 422 | 428 |
| 423 struct { | 429 struct { |
| 424 base::ListValue* schema; | 430 base::DictionaryValue* api_features; |
| 425 bool expect_success; | 431 bool expect_success; |
| 426 } test_data[] = { | 432 } test_data[] = { |
| 427 { schema1.get(), true }, | 433 { api_features1.get(), true }, |
| 428 { schema2.get(), false } | 434 { api_features2.get(), false } |
| 429 }; | 435 }; |
| 430 | 436 |
| 437 |
| 431 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { | 438 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
| 432 std::string schema_source; | 439 BaseFeatureProvider api_feature_provider(*test_data[i].api_features, |
| 433 base::JSONWriter::Write(test_data[i].schema, &schema_source); | 440 CreateAPIFeature); |
| 434 | 441 Feature* feature = api_feature_provider.GetFeature("test"); |
| 435 ExtensionAPI api; | |
| 436 api.RegisterSchema("test", base::StringPiece(schema_source)); | |
| 437 | |
| 438 Feature* feature = api.GetFeature("test"); | |
| 439 EXPECT_EQ(test_data[i].expect_success, feature != NULL) << i; | 442 EXPECT_EQ(test_data[i].expect_success, feature != NULL) << i; |
| 440 } | 443 } |
| 441 } | 444 } |
| 442 | 445 |
| 443 static void GetDictionaryFromList(const base::DictionaryValue* schema, | 446 static void GetDictionaryFromList(const base::DictionaryValue* schema, |
| 444 const std::string& list_name, | 447 const std::string& list_name, |
| 445 const int list_index, | 448 const int list_index, |
| 446 const base::DictionaryValue** out) { | 449 const base::DictionaryValue** out) { |
| 447 const base::ListValue* list; | 450 const base::ListValue* list; |
| 448 EXPECT_TRUE(schema->GetList(list_name, &list)); | 451 EXPECT_TRUE(schema->GetList(list_name, &list)); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 GetDictionaryFromList(dict, "parameters", 0, &sub_dict); | 506 GetDictionaryFromList(dict, "parameters", 0, &sub_dict); |
| 504 EXPECT_TRUE(sub_dict->GetString("$ref", &type)); | 507 EXPECT_TRUE(sub_dict->GetString("$ref", &type)); |
| 505 EXPECT_EQ("test.foo.TestType", type); | 508 EXPECT_EQ("test.foo.TestType", type); |
| 506 GetDictionaryFromList(dict, "parameters", 1, &sub_dict); | 509 GetDictionaryFromList(dict, "parameters", 1, &sub_dict); |
| 507 EXPECT_TRUE(sub_dict->GetString("$ref", &type)); | 510 EXPECT_TRUE(sub_dict->GetString("$ref", &type)); |
| 508 EXPECT_EQ("fully.qualified.Type", type); | 511 EXPECT_EQ("fully.qualified.Type", type); |
| 509 } | 512 } |
| 510 | 513 |
| 511 } // namespace | 514 } // namespace |
| 512 } // namespace extensions | 515 } // namespace extensions |
| OLD | NEW |