15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "extensions/common/extension_api.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/json/json_reader.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension_builder.h"
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/features/api_feature.h"
23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/features/base_feature_provider.h"
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/features/simple_feature.h"
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h"
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest_constants.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/test_util.h"
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/value_builder.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using test_util::BuildExtension;
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SimpleFeature* CreateAPIFeature() {
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return new APIFeature();
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(ExtensionAPITest, Creation) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionAPI* shared_instance = ExtensionAPI::GetSharedInstance();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(shared_instance, ExtensionAPI::GetSharedInstance());
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ExtensionAPI> new_instance(
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionAPI::CreateWithDefaultConfiguration());
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(new_instance.get(),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            scoped_ptr<ExtensionAPI>(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ExtensionAPI::CreateWithDefaultConfiguration()).get());
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionAPI empty_instance;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionAPI* api;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool expect_populated;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } test_data[] = {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { shared_instance, true },
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { new_instance.get(), true },
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { &empty_instance, false }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(test_data[i].expect_populated,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              test_data[i].api->GetSchema("bookmarks.create") != NULL);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(ExtensionAPITest, SplitDependencyName) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string input;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string expected_feature_type;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string expected_feature_name;
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } test_data[] = {{"", "api", ""},  // assumes "api" when no type is present
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"foo", "api", "foo"},
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"foo:", "foo", ""},
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {":foo", "", "foo"},
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"foo:bar", "foo", "bar"},
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"foo:bar.baz", "foo", "bar.baz"}};
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string feature_type;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string feature_name;
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ExtensionAPI::SplitDependencyName(
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        test_data[i].input, &feature_type, &feature_name);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(test_data[i].expected_feature_type, feature_type) << i;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(test_data[i].expected_feature_name, feature_name) << i;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
88116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST(ExtensionAPITest, IsAvailableInUntrustedContext) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ExtensionAPI> extension_api(
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionAPI::CreateWithDefaultConfiguration());
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<const Extension> extension =
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ExtensionBuilder()
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          .SetManifest(DictionaryBuilder()
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                           .Set("name", "extension")
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                           .Set("version", "1")
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                           .Set("permissions", ListBuilder().Append("storage"))
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                           .Set("manifest_version", 2))
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          .Build();
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(extension_api->IsAvailableInUntrustedContext("runtime.connect",
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                           extension.get()));
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(extension_api->IsAvailableInUntrustedContext("runtime.onConnect",
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                           extension.get()));
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(extension_api->IsAvailableInUntrustedContext("runtime.lastError",
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                           extension.get()));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Exists, but privileged.
108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(extension_api->IsAvailableInUntrustedContext(
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      "extension.getViews", extension.get()));
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(extension_api->IsAvailableInUntrustedContext("history.search",
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                            extension.get()));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whole APIs that are unprivileged.
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      extension_api->IsAvailableInUntrustedContext("app", extension.get()));
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(extension_api->IsAvailableInUntrustedContext("app.getDetails",
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                           extension.get()));
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // There is no feature "app.isInstalled" (it's "app.getIsInstalled") but
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // this should be available nonetheless.
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(extension_api->IsAvailableInUntrustedContext("app.isInstalled",
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                           extension.get()));
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(extension_api->IsAvailableInUntrustedContext("storage.local",
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                           extension.get()));
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(extension_api->IsAvailableInUntrustedContext(
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      "storage.local.onChanged", extension.get()));
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(extension_api->IsAvailableInUntrustedContext("storage.local.set",
127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                           extension.get()));
128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(extension_api->IsAvailableInUntrustedContext(
129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      "storage.local.MAX_ITEMS", extension.get()));
130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(extension_api->IsAvailableInUntrustedContext("storage.set",
131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                           extension.get()));
132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // APIs which override unprivileged APIs.
134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(extension_api->IsAvailableInUntrustedContext("app.runtime",
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                            extension.get()));
136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(extension_api->IsAvailableInUntrustedContext("app.window",
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                            extension.get()));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
140116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST(ExtensionAPITest, IsAvailableInUntrustedContextFeatures) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string api_full_name;
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool expect_is_available;
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } test_data[] = {{"test1", true},
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"test1.foo", false},
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"test2", false},
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"test2.foo", true},
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"test2.bar", true},
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"test2.baz", false},
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"test2.qux", false},
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"test3", true},
152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"test3.foo", false},
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"test4", true},
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   {"test5", true}};
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath api_features_path;
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PathService::Get(chrome::DIR_TEST_DATA, &api_features_path);
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  api_features_path = api_features_path.AppendASCII("extensions")
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .AppendASCII("extension_api_unittest")
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .AppendASCII("privileged_api_features.json");
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string api_features_str;
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(base::ReadFileToString(
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      api_features_path, &api_features_str)) << "privileged_api_features.json";
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> value(static_cast<base::DictionaryValue*>(
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::JSONReader::Read(api_features_str)));
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BaseFeatureProvider api_feature_provider(*value, CreateAPIFeature);
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<Extension> extension =
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      BuildExtension(ExtensionBuilder().Pass()).Build();
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionAPI api;
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    api.RegisterDependencyProvider("api", &api_feature_provider);
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EXPECT_EQ(test_data[i].expect_is_available,
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              api.IsAvailableInUntrustedContext(test_data[i].api_full_name,
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                extension.get()))
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        << i;
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST(ExtensionAPITest, APIFeatures) {
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  struct {
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string api_full_name;
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool expect_is_available;
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Feature::Context context;
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GURL url;
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } test_data[] = {
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test1", false, Feature::WEB_PAGE_CONTEXT, GURL() },
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test1", true, Feature::BLESSED_EXTENSION_CONTEXT, GURL() },
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test1", true, Feature::UNBLESSED_EXTENSION_CONTEXT, GURL() },
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test1", true, Feature::CONTENT_SCRIPT_CONTEXT, GURL() },
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test2", true, Feature::WEB_PAGE_CONTEXT, GURL("http://google.com") },
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test2", false, Feature::BLESSED_EXTENSION_CONTEXT,
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GURL("http://google.com") },
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test2.foo", false, Feature::WEB_PAGE_CONTEXT,
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GURL("http://google.com") },
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test2.foo", true, Feature::CONTENT_SCRIPT_CONTEXT, GURL() },
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test3", false, Feature::WEB_PAGE_CONTEXT, GURL("http://google.com") },
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test3.foo", true, Feature::WEB_PAGE_CONTEXT, GURL("http://google.com") },
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test3.foo", true, Feature::BLESSED_EXTENSION_CONTEXT,
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GURL("http://bad.com") },
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test4", true, Feature::BLESSED_EXTENSION_CONTEXT,
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GURL("http://bad.com") },
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test4.foo", false, Feature::BLESSED_EXTENSION_CONTEXT,
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GURL("http://bad.com") },
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test4.foo", false, Feature::UNBLESSED_EXTENSION_CONTEXT,
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GURL("http://bad.com") },
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test4.foo.foo", true, Feature::CONTENT_SCRIPT_CONTEXT, GURL() },
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test5", true, Feature::WEB_PAGE_CONTEXT, GURL("http://foo.com") },
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test5", false, Feature::WEB_PAGE_CONTEXT, GURL("http://bar.com") },
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test5.blah", true, Feature::WEB_PAGE_CONTEXT, GURL("http://foo.com") },
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test5.blah", false, Feature::WEB_PAGE_CONTEXT, GURL("http://bar.com") },
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test6", false, Feature::BLESSED_EXTENSION_CONTEXT, GURL() },
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test6.foo", true, Feature::BLESSED_EXTENSION_CONTEXT, GURL() },
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test7", true, Feature::WEB_PAGE_CONTEXT, GURL("http://foo.com") },
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test7.foo", false, Feature::WEB_PAGE_CONTEXT, GURL("http://bar.com") },
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test7.foo", true, Feature::WEB_PAGE_CONTEXT, GURL("http://foo.com") },
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { "test7.bar", false, Feature::WEB_PAGE_CONTEXT, GURL("http://bar.com") },
2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "test7.bar", false, Feature::WEB_PAGE_CONTEXT, GURL("http://foo.com") },
2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // Test parent/child.
2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent1", true, Feature::CONTENT_SCRIPT_CONTEXT, GURL() },
2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent1", false, Feature::WEB_PAGE_CONTEXT, GURL("http://foo.com") },
2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent1.child1", false, Feature::CONTENT_SCRIPT_CONTEXT, GURL() },
2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent1.child1", true, Feature::WEB_PAGE_CONTEXT,
2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL("http://foo.com") },
2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent1.child2", true, Feature::CONTENT_SCRIPT_CONTEXT, GURL() },
2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent1.child2", false, Feature::WEB_PAGE_CONTEXT,
2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL("http://foo.com") },
2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent2", true, Feature::CONTENT_SCRIPT_CONTEXT, GURL() },
2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent2", true, Feature::BLESSED_EXTENSION_CONTEXT, GURL() },
2347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent2", true, Feature::UNBLESSED_EXTENSION_CONTEXT, GURL() },
2357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent2.child3", false, Feature::CONTENT_SCRIPT_CONTEXT, GURL() },
2367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent2.child3", true, Feature::BLESSED_EXTENSION_CONTEXT, GURL() },
2377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent2.child3", false, Feature::UNBLESSED_EXTENSION_CONTEXT, GURL() },
2387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent2.child3.child.child", true, Feature::CONTENT_SCRIPT_CONTEXT,
2397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL() },
2407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent2.child3.child.child", false, Feature::BLESSED_EXTENSION_CONTEXT,
2417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL() },
2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent2.child3.child.child", true, Feature::UNBLESSED_EXTENSION_CONTEXT,
2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL() },
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent3", true, Feature::CONTENT_SCRIPT_CONTEXT, GURL() },
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent3", false, Feature::BLESSED_EXTENSION_CONTEXT, GURL() },
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent3", false, Feature::UNBLESSED_EXTENSION_CONTEXT, GURL() },
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent3.noparent", true, Feature::CONTENT_SCRIPT_CONTEXT, GURL() },
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent3.noparent", true, Feature::BLESSED_EXTENSION_CONTEXT, GURL() },
2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent3.noparent", true, Feature::UNBLESSED_EXTENSION_CONTEXT, GURL() },
2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent3.noparent.child", true, Feature::CONTENT_SCRIPT_CONTEXT, GURL() },
2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent3.noparent.child", true, Feature::BLESSED_EXTENSION_CONTEXT,
2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL() },
2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    { "parent3.noparent.child", true, Feature::UNBLESSED_EXTENSION_CONTEXT,
2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL() }
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath api_features_path;
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PathService::Get(chrome::DIR_TEST_DATA, &api_features_path);
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  api_features_path = api_features_path.AppendASCII("extensions")
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .AppendASCII("extension_api_unittest")
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .AppendASCII("api_features.json");
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string api_features_str;
26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(base::ReadFileToString(
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      api_features_path, &api_features_str)) << "api_features.json";
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> value(static_cast<base::DictionaryValue*>(
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::JSONReader::Read(api_features_str)));
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  BaseFeatureProvider api_feature_provider(*value, CreateAPIFeature);
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ExtensionAPI api;
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    api.RegisterDependencyProvider("api", &api_feature_provider);
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (base::DictionaryValue::Iterator iter(*value); !iter.IsAtEnd();
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         iter.Advance()) {
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (iter.key().find(".") == std::string::npos)
2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        api.RegisterSchemaResource(iter.key(), 0);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ExtensionAPI::OverrideSharedInstanceForTest scope(&api);
281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool expected = test_data[i].expect_is_available;
282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    Feature::Availability availability =
283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        api.IsAvailable(test_data[i].api_full_name,
284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        NULL,
285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        test_data[i].context,
286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        test_data[i].url);
287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    EXPECT_EQ(expected, availability.is_available())
288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        << base::StringPrintf("Test %d: Feature '%s' was %s: %s",
289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                              static_cast<int>(i),
290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                              test_data[i].api_full_name.c_str(),
291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                              expected ? "not available" : "available",
292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                              availability.message().c_str());
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST(ExtensionAPITest, IsAnyFeatureAvailableToContext) {
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<const Extension> app = ExtensionBuilder()
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    .SetManifest(DictionaryBuilder()
2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .Set("name", "app")
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .Set("app", DictionaryBuilder()
3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        .Set("background", DictionaryBuilder()
3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          .Set("scripts", ListBuilder().Append("background.js"))))
3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .Set("version", "1")
3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .Set("manifest_version", 2)).Build();
3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_refptr<const Extension> extension = ExtensionBuilder()
3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    .SetManifest(DictionaryBuilder()
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .Set("name", "extension")
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .Set("version", "1")
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .Set("manifest_version", 2)).Build();
3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  struct {
312b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    std::string api_full_name;
313b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bool expect_is_available;
314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    Feature::Context context;
3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const Extension* extension;
316b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    GURL url;
317b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  } test_data[] = {
3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test1", false, Feature::WEB_PAGE_CONTEXT, NULL, GURL() },
3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test1", true, Feature::UNBLESSED_EXTENSION_CONTEXT, NULL, GURL() },
3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test1", false, Feature::UNBLESSED_EXTENSION_CONTEXT, app.get(), GURL() },
3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test1", true, Feature::UNBLESSED_EXTENSION_CONTEXT, extension.get(),
3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        GURL() },
3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test2", true, Feature::CONTENT_SCRIPT_CONTEXT, NULL, GURL() },
3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test2", true, Feature::WEB_PAGE_CONTEXT, NULL,
325b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        GURL("http://google.com") },
3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test2.foo", false, Feature::WEB_PAGE_CONTEXT, NULL,
3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        GURL("http://google.com") },
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test3", true, Feature::CONTENT_SCRIPT_CONTEXT, NULL, GURL() },
3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test3", true, Feature::WEB_PAGE_CONTEXT, NULL, GURL("http://foo.com") },
3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test4.foo", true, Feature::CONTENT_SCRIPT_CONTEXT, NULL, GURL() },
3313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test7", false, Feature::WEB_PAGE_CONTEXT, NULL,
3323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        GURL("http://google.com") },
3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test7", true, Feature::WEB_PAGE_CONTEXT, NULL, GURL("http://foo.com") },
3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "test7", false, Feature::WEB_PAGE_CONTEXT, NULL, GURL("http://bar.com") }
335b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  };
336b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
337b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::FilePath api_features_path;
338b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  PathService::Get(chrome::DIR_TEST_DATA, &api_features_path);
339b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  api_features_path = api_features_path.AppendASCII("extensions")
340b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      .AppendASCII("extension_api_unittest")
341b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      .AppendASCII("api_features.json");
342b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
343b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  std::string api_features_str;
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(base::ReadFileToString(
345b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      api_features_path, &api_features_str)) << "api_features.json";
346b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> value(static_cast<base::DictionaryValue*>(
348b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::JSONReader::Read(api_features_str)));
349b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  BaseFeatureProvider api_feature_provider(*value, CreateAPIFeature);
350b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
351b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
352b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    ExtensionAPI api;
353b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    api.RegisterDependencyProvider("api", &api_feature_provider);
354b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    for (base::DictionaryValue::Iterator iter(*value); !iter.IsAtEnd();
355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)         iter.Advance()) {
356b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if (iter.key().find(".") == std::string::npos)
3577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        api.RegisterSchemaResource(iter.key(), 0);
358b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
359b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Feature* test_feature =
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        api_feature_provider.GetFeature(test_data[i].api_full_name);
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_TRUE(test_feature);
363b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    EXPECT_EQ(test_data[i].expect_is_available,
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              api.IsAnyFeatureAvailableToContext(*test_feature,
3653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                 test_data[i].extension,
366b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                                 test_data[i].context,
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                 test_data[i].url))
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << i;
369b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
370b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
371b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(ExtensionAPITest, LazyGetSchema) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ExtensionAPI> apis(ExtensionAPI::CreateWithDefaultConfiguration());
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(NULL, apis->GetSchema(std::string()));
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(NULL, apis->GetSchema(std::string()));
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(NULL, apis->GetSchema("experimental"));
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(NULL, apis->GetSchema("experimental"));
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(NULL, apis->GetSchema("foo"));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(NULL, apis->GetSchema("foo"));
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(apis->GetSchema("dns"));
38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(apis->GetSchema("dns"));
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(apis->GetSchema("extension"));
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(apis->GetSchema("extension"));
386a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_TRUE(apis->GetSchema("infobars"));
387a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_TRUE(apis->GetSchema("infobars"));
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(apis->GetSchema("omnibox"));
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(apis->GetSchema("omnibox"));
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(apis->GetSchema("storage"));
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(apis->GetSchema("storage"));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<Extension> CreateExtensionWithPermissions(
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::set<std::string>& permissions) {
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue manifest;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest.SetString("name", "extension");
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest.SetString("version", "1.0");
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest.SetInteger("manifest_version", 2);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::ListValue> permissions_list(new base::ListValue());
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::set<std::string>::const_iterator i = permissions.begin();
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i != permissions.end(); ++i) {
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      permissions_list->Append(new base::StringValue(*i));
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manifest.Set("permissions", permissions_list.release());
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string error;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(Extension::Create(
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(), Manifest::UNPACKED,
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      manifest, Extension::NO_FLAGS, &error));
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(extension.get());
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(error.empty());
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return extension;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<Extension> CreateExtensionWithPermission(
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& permission) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> permissions;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  permissions.insert(permission);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateExtensionWithPermissions(permissions);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(ExtensionAPITest, ExtensionWithUnprivilegedAPIs) {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<std::string> permissions;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    permissions.insert("storage");
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    permissions.insert("history");
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension = CreateExtensionWithPermissions(permissions);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ExtensionAPI> extension_api(
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionAPI::CreateWithDefaultConfiguration());
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const FeatureProvider& api_features = *FeatureProvider::GetAPIFeatures();
439b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "storage" is completely unprivileged.
4417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext(
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *api_features.GetFeature("storage"),
4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NULL,
4447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      Feature::BLESSED_EXTENSION_CONTEXT,
4457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GURL()));
4467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext(
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *api_features.GetFeature("storage"),
4483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NULL,
4497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      Feature::UNBLESSED_EXTENSION_CONTEXT,
4507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GURL()));
4517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext(
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *api_features.GetFeature("storage"),
4533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NULL,
4547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      Feature::CONTENT_SCRIPT_CONTEXT,
4557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GURL()));
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "extension" is partially unprivileged.
4587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext(
4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *api_features.GetFeature("extension"),
4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NULL,
4617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      Feature::BLESSED_EXTENSION_CONTEXT,
4627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GURL()));
4637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext(
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *api_features.GetFeature("extension"),
4653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NULL,
4667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      Feature::UNBLESSED_EXTENSION_CONTEXT,
4677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GURL()));
4687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext(
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *api_features.GetFeature("extension"),
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NULL,
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Feature::CONTENT_SCRIPT_CONTEXT,
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GURL()));
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext(
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *api_features.GetFeature("extension.getURL"),
4753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NULL,
4767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      Feature::CONTENT_SCRIPT_CONTEXT,
4777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GURL()));
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "history" is entirely privileged.
4807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext(
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *api_features.GetFeature("history"),
4823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NULL,
4837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      Feature::BLESSED_EXTENSION_CONTEXT,
4847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GURL()));
4857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_FALSE(extension_api->IsAnyFeatureAvailableToContext(
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *api_features.GetFeature("history"),
4873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NULL,
4887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      Feature::UNBLESSED_EXTENSION_CONTEXT,
4897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GURL()));
4907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_FALSE(extension_api->IsAnyFeatureAvailableToContext(
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *api_features.GetFeature("history"),
4923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      NULL,
4937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      Feature::CONTENT_SCRIPT_CONTEXT,
4947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GURL()));
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
497b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)scoped_refptr<Extension> CreateHostedApp() {
498b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::DictionaryValue values;
4993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  values.SetString(manifest_keys::kName, "test");
5003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  values.SetString(manifest_keys::kVersion, "0.1");
5013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  values.Set(manifest_keys::kWebURLs, new base::ListValue());
5023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  values.SetString(manifest_keys::kLaunchWebURL,
503b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   "http://www.example.com");
504b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  std::string error;
505b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_refptr<Extension> extension(Extension::Create(
506b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::FilePath(), Manifest::INTERNAL, values, Extension::NO_FLAGS,
507b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      &error));
508b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  CHECK(extension.get());
509b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return extension;
510b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
511b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
5127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)scoped_refptr<Extension> CreatePackagedAppWithPermissions(
5137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const std::set<std::string>& permissions) {
5147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::DictionaryValue values;
5153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  values.SetString(manifest_keys::kName, "test");
5163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  values.SetString(manifest_keys::kVersion, "0.1");
5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  values.SetString(manifest_keys::kPlatformAppBackground,
5187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      "http://www.example.com");
5197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::DictionaryValue* app = new base::DictionaryValue();
5217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::DictionaryValue* background = new base::DictionaryValue();
5227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::ListValue* scripts = new base::ListValue();
5237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scripts->Append(new base::StringValue("test.js"));
5247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  background->Set("scripts", scripts);
5257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  app->Set("background", background);
5263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  values.Set(manifest_keys::kApp, app);
5277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  {
5287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_ptr<base::ListValue> permissions_list(new base::ListValue());
5297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    for (std::set<std::string>::const_iterator i = permissions.begin();
5307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        i != permissions.end(); ++i) {
5317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      permissions_list->Append(new base::StringValue(*i));
5327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
5337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    values.Set("permissions", permissions_list.release());
5347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
5357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::string error;
5377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<Extension> extension(Extension::Create(
5387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::FilePath(), Manifest::INTERNAL, values, Extension::NO_FLAGS,
5397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      &error));
5407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CHECK(extension.get()) << error;
5417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return extension;
5427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
5437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
544b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)TEST(ExtensionAPITest, HostedAppPermissions) {
545b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_refptr<Extension> extension = CreateHostedApp();
546b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
547b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<ExtensionAPI> extension_api(
548b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      ExtensionAPI::CreateWithDefaultConfiguration());
549b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
550a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // "runtime" and "tabs" should not be available in hosted apps.
551b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  EXPECT_FALSE(extension_api->IsAvailable("runtime",
552b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          extension.get(),
553b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          Feature::BLESSED_EXTENSION_CONTEXT,
554b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          GURL()).is_available());
555b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  EXPECT_FALSE(extension_api->IsAvailable("runtime.id",
556b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          extension.get(),
557b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          Feature::BLESSED_EXTENSION_CONTEXT,
558b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          GURL()).is_available());
559b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  EXPECT_FALSE(extension_api->IsAvailable("runtime.sendMessage",
560b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          extension.get(),
561b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          Feature::BLESSED_EXTENSION_CONTEXT,
562b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          GURL()).is_available());
563b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  EXPECT_FALSE(extension_api->IsAvailable("runtime.sendNativeMessage",
564b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          extension.get(),
565b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          Feature::BLESSED_EXTENSION_CONTEXT,
566b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          GURL()).is_available());
567a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_FALSE(extension_api->IsAvailable("tabs.create",
568a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                          extension.get(),
569a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                          Feature::BLESSED_EXTENSION_CONTEXT,
570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                          GURL()).is_available());
571b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
572b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
5737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST(ExtensionAPITest, AppAndFriendsAvailability) {
5747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<ExtensionAPI> extension_api(
5767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      ExtensionAPI::CreateWithDefaultConfiguration());
5777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Make sure chrome.app.runtime and chrome.app.window are available to apps,
5797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // and chrome.app is not.
5807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  {
5817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    std::set<std::string> permissions;
5827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    permissions.insert("app.runtime");
5837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    permissions.insert("app.window");
5847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_refptr<Extension> extension =
5857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        CreatePackagedAppWithPermissions(permissions);
5867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_FALSE(extension_api->IsAvailable(
5877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        "app",
5887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        extension.get(),
5897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        Feature::BLESSED_EXTENSION_CONTEXT,
5907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL("http://foo.com")).is_available());
5917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_TRUE(extension_api->IsAvailable(
5927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        "app.runtime",
5937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        extension.get(),
5947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        Feature::BLESSED_EXTENSION_CONTEXT,
5957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL("http://foo.com")).is_available());
5967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_TRUE(extension_api->IsAvailable(
5977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        "app.window",
5987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        extension.get(),
5997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        Feature::BLESSED_EXTENSION_CONTEXT,
6007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL("http://foo.com")).is_available());
6017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
6027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Make sure chrome.app.runtime and chrome.app.window are not available to
6037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // extensions, and chrome.app is.
6047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  {
6057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    std::set<std::string> permissions;
6067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_refptr<Extension> extension =
6077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        CreateExtensionWithPermissions(permissions);
6087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_TRUE(extension_api->IsAvailable(
6097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        "app",
6107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        extension.get(),
6117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        Feature::BLESSED_EXTENSION_CONTEXT,
6127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL("http://foo.com")).is_available());
6137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_FALSE(extension_api->IsAvailable(
6147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        "app.runtime",
6157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        extension.get(),
6167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        Feature::BLESSED_EXTENSION_CONTEXT,
6177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL("http://foo.com")).is_available());
6187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_FALSE(extension_api->IsAvailable(
6197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        "app.window",
6207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        extension.get(),
6217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        Feature::BLESSED_EXTENSION_CONTEXT,
6227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GURL("http://foo.com")).is_available());
6237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
6247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
6257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(ExtensionAPITest, ExtensionWithDependencies) {
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extension with the "ttsEngine" permission but not the "tts" permission; it
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // should not automatically get "tts" permission.
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<Extension> extension =
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateExtensionWithPermission("ttsEngine");
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ExtensionAPI> api(
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ExtensionAPI::CreateWithDefaultConfiguration());
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(api->IsAvailable("ttsEngine",
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 extension.get(),
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 Feature::BLESSED_EXTENSION_CONTEXT,
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 GURL()).is_available());
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_FALSE(api->IsAvailable("tts",
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  extension.get(),
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  Feature::BLESSED_EXTENSION_CONTEXT,
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  GURL()).is_available());
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Conversely, extension with the "tts" permission but not the "ttsEngine"
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // permission shouldn't get the "ttsEngine" permission.
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<Extension> extension =
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateExtensionWithPermission("tts");
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ExtensionAPI> api(
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ExtensionAPI::CreateWithDefaultConfiguration());
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_FALSE(api->IsAvailable("ttsEngine",
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  extension.get(),
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  Feature::BLESSED_EXTENSION_CONTEXT,
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  GURL()).is_available());
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(api->IsAvailable("tts",
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 extension.get(),
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 Feature::BLESSED_EXTENSION_CONTEXT,
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 GURL()).is_available());
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MatchesURL(
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionAPI* api, const std::string& api_name, const std::string& url) {
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return api->IsAvailable(
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      api_name, NULL, Feature::WEB_PAGE_CONTEXT, GURL(url)).is_available();
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(ExtensionAPITest, URLMatching) {
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ExtensionAPI> api(ExtensionAPI::CreateWithDefaultConfiguration());
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "app" API is available to all URLs that content scripts can be injected.
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(MatchesURL(api.get(), "app", "http://example.com/example.html"));
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(MatchesURL(api.get(), "app", "https://blah.net"));
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(MatchesURL(api.get(), "app", "file://somefile.html"));
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Also to internal URLs.
6775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(MatchesURL(api.get(), "app", "about:flags"));
6785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(MatchesURL(api.get(), "app", "chrome://flags"));
679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // "app" should be available to chrome-extension URLs.
681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(MatchesURL(api.get(), "app",
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          "chrome-extension://fakeextension"));
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "storage" API (for example) isn't available to any URLs.
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(MatchesURL(api.get(), "storage",
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          "http://example.com/example.html"));
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(MatchesURL(api.get(), "storage", "https://blah.net"));
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(MatchesURL(api.get(), "storage", "file://somefile.html"));
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(MatchesURL(api.get(), "storage", "about:flags"));
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(MatchesURL(api.get(), "storage", "chrome://flags"));
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(MatchesURL(api.get(), "storage",
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          "chrome-extension://fakeextension"));
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(ExtensionAPITest, GetAPINameFromFullName) {
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string input;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string api_name;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string child_name;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } test_data[] = {
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "", "", "" },
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "unknown", "", "" },
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bookmarks", "bookmarks", "" },
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bookmarks.", "bookmarks", "" },
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ".bookmarks", "", "" },
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bookmarks.create", "bookmarks", "create" },
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bookmarks.create.", "bookmarks", "create." },
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bookmarks.create.monkey", "bookmarks", "create.monkey" },
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bookmarkManagerPrivate", "bookmarkManagerPrivate", "" },
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "bookmarkManagerPrivate.copy", "bookmarkManagerPrivate", "copy" }
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ExtensionAPI> api(ExtensionAPI::CreateWithDefaultConfiguration());
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string child_name;
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string api_name = api->GetAPINameFromFullName(test_data[i].input,
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       &child_name);
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(test_data[i].api_name, api_name) << test_data[i].input;
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(test_data[i].child_name, child_name) << test_data[i].input;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(ExtensionAPITest, DefaultConfigurationFeatures) {
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ExtensionAPI> api(ExtensionAPI::CreateWithDefaultConfiguration());
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SimpleFeature* bookmarks = static_cast<SimpleFeature*>(
727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      api->GetFeatureDependency("api:bookmarks"));
728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SimpleFeature* bookmarks_create = static_cast<SimpleFeature*>(
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      api->GetFeatureDependency("api:bookmarks.create"));
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SimpleFeature* feature;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(aa): More stuff to test over time.
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } test_data[] = {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { bookmarks },
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { bookmarks_create }
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SimpleFeature* feature = test_data[i].feature;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(feature) << i;
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(feature->whitelist()->empty());
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(feature->extension_types()->empty());
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    EXPECT_EQ(SimpleFeature::UNSPECIFIED_LOCATION, feature->location());
7474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_TRUE(feature->platforms()->empty());
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, feature->min_manifest_version());
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, feature->max_manifest_version());
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
753c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(ExtensionAPITest, FeaturesRequireContexts) {
754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(cduvall): Make this check API featues.
755c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> api_features1(new base::DictionaryValue());
756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> api_features2(new base::DictionaryValue());
757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::DictionaryValue* test1 = new base::DictionaryValue();
758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::DictionaryValue* test2 = new base::DictionaryValue();
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue* contexts = new base::ListValue();
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  contexts->Append(new base::StringValue("content_script"));
761c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  test1->Set("contexts", contexts);
7627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test1->SetString("channel", "stable");
7637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test2->SetString("channel", "stable");
764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  api_features1->Set("test", test1);
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  api_features2->Set("test", test2);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::DictionaryValue* api_features;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool expect_success;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } test_data[] = {
771c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { api_features1.get(), true },
772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { api_features2.get(), false }
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BaseFeatureProvider api_feature_provider(*test_data[i].api_features,
778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                             CreateAPIFeature);
779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Feature* feature = api_feature_provider.GetFeature("test");
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(test_data[i].expect_success, feature != NULL) << i;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void GetDictionaryFromList(const base::DictionaryValue* schema,
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const std::string& list_name,
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const int list_index,
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const base::DictionaryValue** out) {
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::ListValue* list;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(schema->GetList(list_name, &list));
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(list->GetDictionary(list_index, out));
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(ExtensionAPITest, TypesHaveNamespace) {
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath manifest_path;
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathService::Get(chrome::DIR_TEST_DATA, &manifest_path);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manifest_path = manifest_path.AppendASCII("extensions")
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .AppendASCII("extension_api_unittest")
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .AppendASCII("types_have_namespace.json");
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string manifest_str;
80158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_TRUE(base::ReadFileToString(manifest_path, &manifest_str))
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Failed to load: " << manifest_path.value();
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionAPI api;
8057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  api.RegisterSchemaResource("test.foo", 0);
8067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  api.LoadSchema("test.foo", manifest_str);
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* schema = api.GetSchema("test.foo");
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* dict;
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* sub_dict;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string type;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetDictionaryFromList(schema, "types", 0, &dict);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(dict->GetString("id", &type));
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("test.foo.TestType", type);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(dict->GetString("customBindings", &type));
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("test.foo.TestType", type);
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(dict->GetDictionary("properties", &sub_dict));
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* property;
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sub_dict->GetDictionary("foo", &property));
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(property->GetString("$ref", &type));
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("test.foo.OtherType", type);
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sub_dict->GetDictionary("bar", &property));
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(property->GetString("$ref", &type));
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("fully.qualified.Type", type);
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetDictionaryFromList(schema, "functions", 0, &dict);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetDictionaryFromList(dict, "parameters", 0, &sub_dict);
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sub_dict->GetString("$ref", &type));
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("test.foo.TestType", type);
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(dict->GetDictionary("returns", &sub_dict));
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sub_dict->GetString("$ref", &type));
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("fully.qualified.Type", type);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetDictionaryFromList(schema, "functions", 1, &dict);
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetDictionaryFromList(dict, "parameters", 0, &sub_dict);
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sub_dict->GetString("$ref", &type));
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("fully.qualified.Type", type);
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(dict->GetDictionary("returns", &sub_dict));
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sub_dict->GetString("$ref", &type));
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("test.foo.TestType", type);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetDictionaryFromList(schema, "events", 0, &dict);
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetDictionaryFromList(dict, "parameters", 0, &sub_dict);
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sub_dict->GetString("$ref", &type));
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("test.foo.TestType", type);
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetDictionaryFromList(dict, "parameters", 1, &sub_dict);
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sub_dict->GetString("$ref", &type));
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("fully.qualified.Type", type);
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
853a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Tests API availability with an empty manifest.
854a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST(ExtensionAPITest, NoPermissions) {
855a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const struct {
856a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const char* permission_name;
857a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    bool expect_success;
858a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  } kTests[] = {
859a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Test default module/package permission.
860a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "extension",      true },
861a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "i18n",           true },
862a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "permissions",    true },
863a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "runtime",        true },
864a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "test",           true },
865a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // These require manifest keys.
866a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "browserAction",  false },
867a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "pageAction",     false },
868a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "pageActions",    false },
869a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Some negative tests.
870a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "bookmarks",      false },
871a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "cookies",        false },
872a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "history",        false },
873a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Make sure we find the module name after stripping '.'
874a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "runtime.abcd.onStartup",  true },
8753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Test Tabs/Windows functions.
876a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "tabs.create",      true },
877a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "tabs.duplicate",   true },
878a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "tabs.onRemoved",   true },
879a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "tabs.remove",      true },
880a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "tabs.update",      true },
881a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "tabs.getSelected", true },
882a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "tabs.onUpdated",   true },
8833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "windows.get",      true },
8843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "windows.create",   true },
8853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "windows.remove",   true },
8863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    { "windows.update",   true },
887a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Test some whitelisted functions. These require no permissions.
888a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "app.getDetails",           true },
889a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "app.getDetailsForFrame",   true },
890a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "app.getIsInstalled",       true },
891a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "app.installState",         true },
892a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "app.runningState",         true },
893a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "management.getPermissionWarningsByManifest", true },
894a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "management.uninstallSelf", true },
895a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // But other functions in those modules do.
896a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    { "management.getPermissionWarningsById", false },
897a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  };
898a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
899a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<ExtensionAPI> extension_api(
900a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ExtensionAPI::CreateWithDefaultConfiguration());
901a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<Extension> extension =
902a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      BuildExtension(ExtensionBuilder().Pass()).Build();
903a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
904a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTests); ++i) {
905a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    EXPECT_EQ(kTests[i].expect_success,
906a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)              extension_api->IsAvailable(kTests[i].permission_name,
907a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         extension.get(),
908a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         Feature::BLESSED_EXTENSION_CONTEXT,
909a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         GURL()).is_available())
910a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        << "Permission being tested: " << kTests[i].permission_name;
911a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
912a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
913a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
914a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Tests that permissions that require manifest keys are available when those
915a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// keys are present.
916a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST(ExtensionAPITest, ManifestKeys) {
917a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<ExtensionAPI> extension_api(
918a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ExtensionAPI::CreateWithDefaultConfiguration());
919a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
920a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<Extension> extension =
921a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      BuildExtension(ExtensionBuilder().Pass())
922a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      .MergeManifest(DictionaryBuilder().Set("browser_action",
923a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                             DictionaryBuilder().Pass()))
924a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      .Build();
925a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
926a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_TRUE(extension_api->IsAvailable("browserAction",
927a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         extension.get(),
928a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         Feature::BLESSED_EXTENSION_CONTEXT,
929a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                         GURL()).is_available());
930a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_FALSE(extension_api->IsAvailable("pageAction",
931a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                          extension.get(),
932a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                          Feature::BLESSED_EXTENSION_CONTEXT,
933a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                          GURL()).is_available());
934a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
935a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
937