| 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 | 8 |
| 9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
| 10 #include "base/file_util.h" |
| 11 #include "base/json/json_writer.h" |
| 12 #include "base/message_loop.h" |
| 10 #include "base/memory/ref_counted.h" | 13 #include "base/memory/ref_counted.h" |
| 11 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
| 15 #include "base/path_service.h" |
| 12 #include "base/values.h" | 16 #include "base/values.h" |
| 17 #include "chrome/common/chrome_paths.h" |
| 13 #include "chrome/common/extensions/extension.h" | 18 #include "chrome/common/extensions/extension.h" |
| 19 #include "content/test/test_browser_thread.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 15 | 21 |
| 22 using content::BrowserThread; |
| 23 |
| 16 namespace extensions { | 24 namespace extensions { |
| 17 namespace { | 25 namespace { |
| 18 | 26 |
| 27 class TestFeatureProvider : public FeatureProvider { |
| 28 public: |
| 29 explicit TestFeatureProvider(Feature::Context context) |
| 30 : context_(context) { |
| 31 } |
| 32 |
| 33 virtual scoped_ptr<Feature> GetFeature(const std::string& name) OVERRIDE { |
| 34 scoped_ptr<Feature> result(new Feature()); |
| 35 result->set_name(name); |
| 36 result->extension_types()->insert(Extension::TYPE_EXTENSION); |
| 37 result->contexts()->insert(context_); |
| 38 return result.Pass(); |
| 39 } |
| 40 |
| 41 private: |
| 42 Feature::Context context_; |
| 43 }; |
| 44 |
| 45 TEST(ExtensionAPI, Creation) { |
| 46 MessageLoop loop(MessageLoop::TYPE_DEFAULT); |
| 47 content::TestBrowserThread ui_thread(BrowserThread::UI, &loop); |
| 48 |
| 49 ExtensionAPI* shared_instance = ExtensionAPI::GetSharedInstance(); |
| 50 EXPECT_EQ(shared_instance, ExtensionAPI::GetSharedInstance()); |
| 51 |
| 52 scoped_ptr<ExtensionAPI> new_instance( |
| 53 ExtensionAPI::CreateWithDefaultConfiguration()); |
| 54 EXPECT_NE(new_instance.get(), |
| 55 scoped_ptr<ExtensionAPI>( |
| 56 ExtensionAPI::CreateWithDefaultConfiguration()).get()); |
| 57 |
| 58 ExtensionAPI empty_instance; |
| 59 |
| 60 struct { |
| 61 ExtensionAPI* api; |
| 62 bool expect_populated; |
| 63 } test_data[] = { |
| 64 { shared_instance, true }, |
| 65 { new_instance.get(), true }, |
| 66 { &empty_instance, false } |
| 67 }; |
| 68 |
| 69 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
| 70 EXPECT_EQ(test_data[i].expect_populated, |
| 71 test_data[i].api->GetSchema("bookmarks.create") != NULL); |
| 72 } |
| 73 } |
| 74 |
| 75 TEST(ExtensionAPI, SplitDependencyName) { |
| 76 struct { |
| 77 std::string input; |
| 78 std::string expected_feature_type; |
| 79 std::string expected_feature_name; |
| 80 } test_data[] = { |
| 81 { "", "api", "" }, // assumes "api" when no type is present |
| 82 { "foo", "api", "foo" }, |
| 83 { "foo:", "foo", "" }, |
| 84 { ":foo", "", "foo" }, |
| 85 { "foo:bar", "foo", "bar" }, |
| 86 { "foo:bar.baz", "foo", "bar.baz" } |
| 87 }; |
| 88 |
| 89 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
| 90 std::string feature_type; |
| 91 std::string feature_name; |
| 92 ExtensionAPI::SplitDependencyName(test_data[i].input, &feature_type, |
| 93 &feature_name); |
| 94 EXPECT_EQ(test_data[i].expected_feature_type, feature_type) << i; |
| 95 EXPECT_EQ(test_data[i].expected_feature_name, feature_name) << i; |
| 96 } |
| 97 } |
| 98 |
| 19 TEST(ExtensionAPI, IsPrivileged) { | 99 TEST(ExtensionAPI, IsPrivileged) { |
| 20 ExtensionAPI extension_api; | 100 scoped_ptr<ExtensionAPI> extension_api( |
| 101 ExtensionAPI::CreateWithDefaultConfiguration()); |
| 21 | 102 |
| 22 EXPECT_FALSE(extension_api.IsPrivileged("extension.connect")); | 103 EXPECT_FALSE(extension_api->IsPrivileged("extension.connect")); |
| 23 EXPECT_FALSE(extension_api.IsPrivileged("extension.onConnect")); | 104 EXPECT_FALSE(extension_api->IsPrivileged("extension.onConnect")); |
| 24 | 105 |
| 25 // Properties are not supported yet. | 106 // Properties are not supported yet. |
| 26 EXPECT_TRUE(extension_api.IsPrivileged("extension.lastError")); | 107 EXPECT_TRUE(extension_api->IsPrivileged("extension.lastError")); |
| 27 | 108 |
| 28 // Default unknown names to privileged for paranoia's sake. | 109 // Default unknown names to privileged for paranoia's sake. |
| 29 EXPECT_TRUE(extension_api.IsPrivileged("<unknown-namespace>")); | 110 EXPECT_TRUE(extension_api->IsPrivileged("")); |
| 30 EXPECT_TRUE(extension_api.IsPrivileged("extension.<unknown-member>")); | 111 EXPECT_TRUE(extension_api->IsPrivileged("<unknown-namespace>")); |
| 112 EXPECT_TRUE(extension_api->IsPrivileged("extension.<unknown-member>")); |
| 31 | 113 |
| 32 // Exists, but privileged. | 114 // Exists, but privileged. |
| 33 EXPECT_TRUE(extension_api.IsPrivileged("extension.getViews")); | 115 EXPECT_TRUE(extension_api->IsPrivileged("extension.getViews")); |
| 34 EXPECT_TRUE(extension_api.IsPrivileged("history.search")); | 116 EXPECT_TRUE(extension_api->IsPrivileged("history.search")); |
| 35 | 117 |
| 36 // Whole APIs that are unprivileged. | 118 // Whole APIs that are unprivileged. |
| 37 EXPECT_FALSE(extension_api.IsPrivileged("app.getDetails")); | 119 EXPECT_FALSE(extension_api->IsPrivileged("app.getDetails")); |
| 38 EXPECT_FALSE(extension_api.IsPrivileged("app.isInstalled")); | 120 EXPECT_FALSE(extension_api->IsPrivileged("app.isInstalled")); |
| 39 EXPECT_FALSE(extension_api.IsPrivileged("storage.local")); | 121 EXPECT_FALSE(extension_api->IsPrivileged("storage.local")); |
| 40 EXPECT_FALSE(extension_api.IsPrivileged("storage.local.onChanged")); | 122 EXPECT_FALSE(extension_api->IsPrivileged("storage.local.onChanged")); |
| 41 EXPECT_FALSE(extension_api.IsPrivileged("storage.local.set")); | 123 EXPECT_FALSE(extension_api->IsPrivileged("storage.local.set")); |
| 42 EXPECT_FALSE(extension_api.IsPrivileged("storage.local.MAX_ITEMS")); | 124 EXPECT_FALSE(extension_api->IsPrivileged("storage.local.MAX_ITEMS")); |
| 43 EXPECT_FALSE(extension_api.IsPrivileged("storage.set")); | 125 EXPECT_FALSE(extension_api->IsPrivileged("storage.set")); |
| 126 } |
| 127 |
| 128 TEST(ExtensionAPI, IsPrivilegedFeatures) { |
| 129 struct { |
| 130 std::string filename; |
| 131 std::string api_full_name; |
| 132 bool expect_is_privilged; |
| 133 Feature::Context test2_contexts; |
| 134 } test_data[] = { |
| 135 { "is_privileged_features_1.json", "test", false, |
| 136 Feature::UNSPECIFIED_CONTEXT }, |
| 137 { "is_privileged_features_2.json", "test", true, |
| 138 Feature::UNSPECIFIED_CONTEXT }, |
| 139 { "is_privileged_features_3.json", "test", false, |
| 140 Feature::UNSPECIFIED_CONTEXT }, |
| 141 { "is_privileged_features_4.json", "test.bar", false, |
| 142 Feature::UNSPECIFIED_CONTEXT }, |
| 143 { "is_privileged_features_5.json", "test.bar", true, |
| 144 Feature::BLESSED_EXTENSION_CONTEXT }, |
| 145 { "is_privileged_features_5.json", "test.bar", false, |
| 146 Feature::UNBLESSED_EXTENSION_CONTEXT } |
| 147 }; |
| 148 |
| 149 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
| 150 FilePath manifest_path; |
| 151 PathService::Get(chrome::DIR_TEST_DATA, &manifest_path); |
| 152 manifest_path = manifest_path.AppendASCII("extensions") |
| 153 .AppendASCII("extension_api_unittest") |
| 154 .AppendASCII(test_data[i].filename); |
| 155 |
| 156 std::string manifest_str; |
| 157 ASSERT_TRUE(file_util::ReadFileToString(manifest_path, &manifest_str)) |
| 158 << test_data[i].filename; |
| 159 |
| 160 ExtensionAPI api; |
| 161 api.RegisterSchema("test", manifest_str); |
| 162 |
| 163 TestFeatureProvider test2_provider(test_data[i].test2_contexts); |
| 164 if (test_data[i].test2_contexts != Feature::UNSPECIFIED_CONTEXT) { |
| 165 api.RegisterDependencyProvider("test2", &test2_provider); |
| 166 } |
| 167 |
| 168 api.LoadAllSchemas(); |
| 169 EXPECT_EQ(test_data[i].expect_is_privilged, |
| 170 api.IsPrivileged(test_data[i].api_full_name)) << i; |
| 171 } |
| 44 } | 172 } |
| 45 | 173 |
| 46 TEST(ExtensionAPI, LazyGetSchema) { | 174 TEST(ExtensionAPI, LazyGetSchema) { |
| 47 ExtensionAPI apis; | 175 scoped_ptr<ExtensionAPI> apis(ExtensionAPI::CreateWithDefaultConfiguration()); |
| 48 | 176 |
| 49 EXPECT_EQ(NULL, apis.GetSchema("")); | 177 EXPECT_EQ(NULL, apis->GetSchema("")); |
| 50 EXPECT_EQ(NULL, apis.GetSchema("")); | 178 EXPECT_EQ(NULL, apis->GetSchema("")); |
| 51 EXPECT_EQ(NULL, apis.GetSchema("experimental")); | 179 EXPECT_EQ(NULL, apis->GetSchema("experimental")); |
| 52 EXPECT_EQ(NULL, apis.GetSchema("experimental")); | 180 EXPECT_EQ(NULL, apis->GetSchema("experimental")); |
| 53 EXPECT_EQ(NULL, apis.GetSchema("foo")); | 181 EXPECT_EQ(NULL, apis->GetSchema("foo")); |
| 54 EXPECT_EQ(NULL, apis.GetSchema("foo")); | 182 EXPECT_EQ(NULL, apis->GetSchema("foo")); |
| 55 | 183 |
| 56 EXPECT_TRUE(apis.GetSchema("experimental.dns")); | 184 EXPECT_TRUE(apis->GetSchema("experimental.dns")); |
| 57 EXPECT_TRUE(apis.GetSchema("experimental.dns")); | 185 EXPECT_TRUE(apis->GetSchema("experimental.dns")); |
| 58 EXPECT_TRUE(apis.GetSchema("experimental.infobars")); | 186 EXPECT_TRUE(apis->GetSchema("experimental.infobars")); |
| 59 EXPECT_TRUE(apis.GetSchema("experimental.infobars")); | 187 EXPECT_TRUE(apis->GetSchema("experimental.infobars")); |
| 60 EXPECT_TRUE(apis.GetSchema("extension")); | 188 EXPECT_TRUE(apis->GetSchema("extension")); |
| 61 EXPECT_TRUE(apis.GetSchema("extension")); | 189 EXPECT_TRUE(apis->GetSchema("extension")); |
| 62 EXPECT_TRUE(apis.GetSchema("omnibox")); | 190 EXPECT_TRUE(apis->GetSchema("omnibox")); |
| 63 EXPECT_TRUE(apis.GetSchema("omnibox")); | 191 EXPECT_TRUE(apis->GetSchema("omnibox")); |
| 64 EXPECT_TRUE(apis.GetSchema("storage")); | 192 EXPECT_TRUE(apis->GetSchema("storage")); |
| 65 EXPECT_TRUE(apis.GetSchema("storage")); | 193 EXPECT_TRUE(apis->GetSchema("storage")); |
| 66 } | 194 } |
| 67 | 195 |
| 68 scoped_refptr<Extension> CreateExtensionWithPermissions( | 196 scoped_refptr<Extension> CreateExtensionWithPermissions( |
| 69 const std::set<std::string>& permissions) { | 197 const std::set<std::string>& permissions) { |
| 70 DictionaryValue manifest; | 198 DictionaryValue manifest; |
| 71 manifest.SetString("name", "extension"); | 199 manifest.SetString("name", "extension"); |
| 72 manifest.SetString("version", "1.0"); | 200 manifest.SetString("version", "1.0"); |
| 73 manifest.SetInteger("manifest_version", 2); | 201 manifest.SetInteger("manifest_version", 2); |
| 74 { | 202 { |
| 75 scoped_ptr<ListValue> permissions_list(new ListValue()); | 203 scoped_ptr<ListValue> permissions_list(new ListValue()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 98 | 226 |
| 99 TEST(ExtensionAPI, ExtensionWithUnprivilegedAPIs) { | 227 TEST(ExtensionAPI, ExtensionWithUnprivilegedAPIs) { |
| 100 scoped_refptr<Extension> extension; | 228 scoped_refptr<Extension> extension; |
| 101 { | 229 { |
| 102 std::set<std::string> permissions; | 230 std::set<std::string> permissions; |
| 103 permissions.insert("storage"); | 231 permissions.insert("storage"); |
| 104 permissions.insert("history"); | 232 permissions.insert("history"); |
| 105 extension = CreateExtensionWithPermissions(permissions); | 233 extension = CreateExtensionWithPermissions(permissions); |
| 106 } | 234 } |
| 107 | 235 |
| 108 ExtensionAPI extension_api; | 236 scoped_ptr<ExtensionAPI> extension_api( |
| 237 ExtensionAPI::CreateWithDefaultConfiguration()); |
| 109 | 238 |
| 110 scoped_ptr<std::set<std::string> > privileged_apis = | 239 scoped_ptr<std::set<std::string> > privileged_apis = |
| 111 extension_api.GetAPIsForContext( | 240 extension_api->GetAPIsForContext( |
| 112 Feature::BLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); | 241 Feature::BLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); |
| 113 | 242 |
| 114 scoped_ptr<std::set<std::string> > unprivileged_apis = | 243 scoped_ptr<std::set<std::string> > unprivileged_apis = |
| 115 extension_api.GetAPIsForContext( | 244 extension_api->GetAPIsForContext( |
| 116 Feature::UNBLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); | 245 Feature::UNBLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); |
| 117 | 246 |
| 118 scoped_ptr<std::set<std::string> > content_script_apis = | 247 scoped_ptr<std::set<std::string> > content_script_apis = |
| 119 extension_api.GetAPIsForContext( | 248 extension_api->GetAPIsForContext( |
| 120 Feature::CONTENT_SCRIPT_CONTEXT, extension.get(), GURL()); | 249 Feature::CONTENT_SCRIPT_CONTEXT, extension.get(), GURL()); |
| 121 | 250 |
| 122 // "storage" is completely unprivileged. | 251 // "storage" is completely unprivileged. |
| 123 EXPECT_EQ(1u, privileged_apis->count("storage")); | 252 EXPECT_EQ(1u, privileged_apis->count("storage")); |
| 124 EXPECT_EQ(1u, unprivileged_apis->count("storage")); | 253 EXPECT_EQ(1u, unprivileged_apis->count("storage")); |
| 125 EXPECT_EQ(1u, content_script_apis->count("storage")); | 254 EXPECT_EQ(1u, content_script_apis->count("storage")); |
| 126 | 255 |
| 127 // "extension" is partially unprivileged. | 256 // "extension" is partially unprivileged. |
| 128 EXPECT_EQ(1u, privileged_apis->count("extension")); | 257 EXPECT_EQ(1u, privileged_apis->count("extension")); |
| 129 EXPECT_EQ(1u, unprivileged_apis->count("extension")); | 258 EXPECT_EQ(1u, unprivileged_apis->count("extension")); |
| 130 EXPECT_EQ(1u, content_script_apis->count("extension")); | 259 EXPECT_EQ(1u, content_script_apis->count("extension")); |
| 131 | 260 |
| 132 // "history" is entirely privileged. | 261 // "history" is entirely privileged. |
| 133 EXPECT_EQ(1u, privileged_apis->count("history")); | 262 EXPECT_EQ(1u, privileged_apis->count("history")); |
| 134 EXPECT_EQ(0u, unprivileged_apis->count("history")); | 263 EXPECT_EQ(0u, unprivileged_apis->count("history")); |
| 135 EXPECT_EQ(0u, content_script_apis->count("history")); | 264 EXPECT_EQ(0u, content_script_apis->count("history")); |
| 136 } | 265 } |
| 137 | 266 |
| 138 TEST(ExtensionAPI, ExtensionWithDependencies) { | 267 TEST(ExtensionAPI, ExtensionWithDependencies) { |
| 139 // Extension with the "ttsEngine" permission but not the "tts" permission; it | 268 // Extension with the "ttsEngine" permission but not the "tts" permission; it |
| 140 // must load TTS. | 269 // must load TTS. |
| 141 { | 270 { |
| 142 scoped_refptr<Extension> extension = | 271 scoped_refptr<Extension> extension = |
| 143 CreateExtensionWithPermission("ttsEngine"); | 272 CreateExtensionWithPermission("ttsEngine"); |
| 144 scoped_ptr<std::set<std::string> > apis = | 273 scoped_ptr<ExtensionAPI> api( |
| 145 ExtensionAPI().GetAPIsForContext( | 274 ExtensionAPI::CreateWithDefaultConfiguration()); |
| 146 Feature::BLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); | 275 scoped_ptr<std::set<std::string> > apis = api->GetAPIsForContext( |
| 276 Feature::BLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); |
| 147 EXPECT_EQ(1u, apis->count("ttsEngine")); | 277 EXPECT_EQ(1u, apis->count("ttsEngine")); |
| 148 EXPECT_EQ(1u, apis->count("tts")); | 278 EXPECT_EQ(1u, apis->count("tts")); |
| 149 } | 279 } |
| 150 | 280 |
| 151 // Conversely, extension with the "tts" permission but not the "ttsEngine" | 281 // Conversely, extension with the "tts" permission but not the "ttsEngine" |
| 152 // permission shouldn't get the "ttsEngine" permission. | 282 // permission shouldn't get the "ttsEngine" permission. |
| 153 { | 283 { |
| 154 scoped_refptr<Extension> extension = | 284 scoped_refptr<Extension> extension = |
| 155 CreateExtensionWithPermission("tts"); | 285 CreateExtensionWithPermission("tts"); |
| 156 scoped_ptr<std::set<std::string> > apis = | 286 scoped_ptr<ExtensionAPI> api( |
| 157 ExtensionAPI().GetAPIsForContext( | 287 ExtensionAPI::CreateWithDefaultConfiguration()); |
| 158 Feature::BLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); | 288 scoped_ptr<std::set<std::string> > apis = api->GetAPIsForContext( |
| 289 Feature::BLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); |
| 159 EXPECT_EQ(0u, apis->count("ttsEngine")); | 290 EXPECT_EQ(0u, apis->count("ttsEngine")); |
| 160 EXPECT_EQ(1u, apis->count("tts")); | 291 EXPECT_EQ(1u, apis->count("tts")); |
| 161 } | 292 } |
| 162 } | 293 } |
| 163 | 294 |
| 164 bool MatchesURL( | 295 bool MatchesURL( |
| 165 ExtensionAPI* api, const std::string& api_name, const std::string& url) { | 296 ExtensionAPI* api, const std::string& api_name, const std::string& url) { |
| 166 scoped_ptr<std::set<std::string> > apis = | 297 scoped_ptr<std::set<std::string> > apis = |
| 167 api->GetAPIsForContext(Feature::WEB_PAGE_CONTEXT, NULL, GURL(url)); | 298 api->GetAPIsForContext(Feature::WEB_PAGE_CONTEXT, NULL, GURL(url)); |
| 168 return apis->count(api_name); | 299 return apis->count(api_name); |
| 169 } | 300 } |
| 170 | 301 |
| 171 TEST(ExtensionAPI, URLMatching) { | 302 TEST(ExtensionAPI, URLMatching) { |
| 172 ExtensionAPI api; | 303 scoped_ptr<ExtensionAPI> api(ExtensionAPI::CreateWithDefaultConfiguration()); |
| 173 | 304 |
| 174 // "app" API is available to all URLs that content scripts can be injected. | 305 // "app" API is available to all URLs that content scripts can be injected. |
| 175 EXPECT_TRUE(MatchesURL(&api, "app", "http://example.com/example.html")); | 306 EXPECT_TRUE(MatchesURL(api.get(), "app", "http://example.com/example.html")); |
| 176 EXPECT_TRUE(MatchesURL(&api, "app", "https://blah.net")); | 307 EXPECT_TRUE(MatchesURL(api.get(), "app", "https://blah.net")); |
| 177 EXPECT_TRUE(MatchesURL(&api, "app", "file://somefile.html")); | 308 EXPECT_TRUE(MatchesURL(api.get(), "app", "file://somefile.html")); |
| 178 | 309 |
| 179 // But not internal URLs (for chrome-extension:// the app API is injected by | 310 // But not internal URLs (for chrome-extension:// the app API is injected by |
| 180 // GetSchemasForExtension). | 311 // GetSchemasForExtension). |
| 181 EXPECT_FALSE(MatchesURL(&api, "app", "about:flags")); | 312 EXPECT_FALSE(MatchesURL(api.get(), "app", "about:flags")); |
| 182 EXPECT_FALSE(MatchesURL(&api, "app", "chrome://flags")); | 313 EXPECT_FALSE(MatchesURL(api.get(), "app", "chrome://flags")); |
| 183 EXPECT_FALSE(MatchesURL(&api, "app", "chrome-extension://fakeextension")); | 314 EXPECT_FALSE(MatchesURL(api.get(), "app", |
| 315 "chrome-extension://fakeextension")); |
| 184 | 316 |
| 185 // "storage" API (for example) isn't available to any URLs. | 317 // "storage" API (for example) isn't available to any URLs. |
| 186 EXPECT_FALSE(MatchesURL(&api, "storage", "http://example.com/example.html")); | 318 EXPECT_FALSE(MatchesURL(api.get(), "storage", |
| 187 EXPECT_FALSE(MatchesURL(&api, "storage", "https://blah.net")); | 319 "http://example.com/example.html")); |
| 188 EXPECT_FALSE(MatchesURL(&api, "storage", "file://somefile.html")); | 320 EXPECT_FALSE(MatchesURL(api.get(), "storage", "https://blah.net")); |
| 189 EXPECT_FALSE(MatchesURL(&api, "storage", "about:flags")); | 321 EXPECT_FALSE(MatchesURL(api.get(), "storage", "file://somefile.html")); |
| 190 EXPECT_FALSE(MatchesURL(&api, "storage", "chrome://flags")); | 322 EXPECT_FALSE(MatchesURL(api.get(), "storage", "about:flags")); |
| 191 EXPECT_FALSE(MatchesURL(&api, "storage", "chrome-extension://fakeextension")); | 323 EXPECT_FALSE(MatchesURL(api.get(), "storage", "chrome://flags")); |
| 324 EXPECT_FALSE(MatchesURL(api.get(), "storage", |
| 325 "chrome-extension://fakeextension")); |
| 326 } |
| 327 |
| 328 TEST(ExtensionAPI, GetAPINameFromFullName) { |
| 329 struct { |
| 330 std::string input; |
| 331 std::string api_name; |
| 332 std::string child_name; |
| 333 } test_data[] = { |
| 334 { "", "", "" }, |
| 335 { "unknown", "", "" }, |
| 336 { "bookmarks", "bookmarks", "" }, |
| 337 { "bookmarks.", "bookmarks", "" }, |
| 338 { ".bookmarks", "", "" }, |
| 339 { "bookmarks.create", "bookmarks", "create" }, |
| 340 { "bookmarks.create.", "bookmarks", "create." }, |
| 341 { "bookmarks.create.monkey", "bookmarks", "create.monkey" }, |
| 342 { "experimental.bookmarkManager", "experimental.bookmarkManager", "" }, |
| 343 { "experimental.bookmarkManager.copy", "experimental.bookmarkManager", |
| 344 "copy" } |
| 345 }; |
| 346 |
| 347 scoped_ptr<ExtensionAPI> api(ExtensionAPI::CreateWithDefaultConfiguration()); |
| 348 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
| 349 std::string child_name; |
| 350 std::string api_name = api->GetAPINameFromFullName(test_data[i].input, |
| 351 &child_name); |
| 352 EXPECT_EQ(test_data[i].api_name, api_name) << test_data[i].input; |
| 353 EXPECT_EQ(test_data[i].child_name, child_name) << test_data[i].input; |
| 354 } |
| 355 } |
| 356 |
| 357 TEST(ExtensionAPI, DefaultConfigurationFeatures) { |
| 358 scoped_ptr<ExtensionAPI> api(ExtensionAPI::CreateWithDefaultConfiguration()); |
| 359 |
| 360 scoped_ptr<Feature> bookmarks(api->GetFeature("bookmarks")); |
| 361 scoped_ptr<Feature> bookmarks_create(api->GetFeature("bookmarks.create")); |
| 362 |
| 363 struct { |
| 364 Feature* feature; |
| 365 // TODO(aa): More stuff to test over time. |
| 366 } test_data[] = { |
| 367 { bookmarks.get() }, |
| 368 { bookmarks_create.get() } |
| 369 }; |
| 370 |
| 371 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
| 372 Feature* feature = test_data[i].feature; |
| 373 ASSERT_TRUE(feature) << i; |
| 374 |
| 375 EXPECT_TRUE(feature->whitelist()->empty()); |
| 376 EXPECT_TRUE(feature->extension_types()->empty()); |
| 377 |
| 378 EXPECT_EQ(1u, feature->contexts()->size()); |
| 379 EXPECT_TRUE(feature->contexts()->count( |
| 380 Feature::BLESSED_EXTENSION_CONTEXT)); |
| 381 |
| 382 EXPECT_EQ(Feature::UNSPECIFIED_LOCATION, feature->location()); |
| 383 EXPECT_EQ(Feature::UNSPECIFIED_PLATFORM, feature->platform()); |
| 384 EXPECT_EQ(0, feature->min_manifest_version()); |
| 385 EXPECT_EQ(0, feature->max_manifest_version()); |
| 386 } |
| 387 } |
| 388 |
| 389 TEST(ExtensionAPI, FeaturesRequireContexts) { |
| 390 scoped_ptr<ListValue> schema1(new ListValue()); |
| 391 DictionaryValue* feature_definition = new DictionaryValue(); |
| 392 schema1->Append(feature_definition); |
| 393 feature_definition->SetString("namespace", "test"); |
| 394 feature_definition->SetBoolean("uses_feature_system", true); |
| 395 |
| 396 scoped_ptr<ListValue> schema2(schema1->DeepCopy()); |
| 397 |
| 398 ListValue* contexts = new ListValue(); |
| 399 contexts->Append(Value::CreateStringValue("content_script")); |
| 400 feature_definition->Set("contexts", contexts); |
| 401 |
| 402 struct { |
| 403 ListValue* schema; |
| 404 bool expect_success; |
| 405 } test_data[] = { |
| 406 { schema1.get(), true }, |
| 407 { schema2.get(), false } |
| 408 }; |
| 409 |
| 410 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { |
| 411 std::string schema_source; |
| 412 base::JSONWriter::Write(test_data[i].schema, &schema_source); |
| 413 |
| 414 ExtensionAPI api; |
| 415 api.RegisterSchema("test", base::StringPiece(schema_source)); |
| 416 api.LoadAllSchemas(); |
| 417 |
| 418 scoped_ptr<Feature> feature(api.GetFeature("test")); |
| 419 EXPECT_EQ(test_data[i].expect_success, feature.get() != NULL) << i; |
| 420 } |
| 192 } | 421 } |
| 193 | 422 |
| 194 } // namespace | 423 } // namespace |
| 195 } // namespace extensions | 424 } // namespace extensions |
| OLD | NEW |