Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(671)

Side by Side Diff: chrome/common/extensions/manifest_unittest.cc

Issue 8786004: Revert "Restrict extension features based on the extension type." (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/common/extensions/manifest.cc ('k') | chrome/renderer/extensions/app_bindings.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/common/extensions/manifest.h"
6
7 #include <algorithm>
8 #include <set>
9 #include <string>
10
11 #include "base/memory/scoped_ptr.h"
12 #include "base/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/common/extensions/extension_constants.h"
15 #include "chrome/common/extensions/extension_error_utils.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace keys = extension_manifest_keys;
19 namespace errors = extension_manifest_errors;
20
21 namespace extensions {
22
23 namespace {
24
25 // Keys that define types.
26 const char* kTypeKeys[] = {
27 keys::kApp,
28 keys::kTheme,
29 keys::kPlatformApp
30 };
31
32 // Keys that are not accesible by themes.
33 const char* kNotThemeKeys[] = {
34 keys::kBrowserAction,
35 keys::kPageAction,
36 keys::kPageActions,
37 keys::kChromeURLOverrides,
38 keys::kPermissions,
39 keys::kOptionalPermissions,
40 keys::kOptionsPage,
41 keys::kBackground,
42 keys::kOfflineEnabled,
43 keys::kMinimumChromeVersion,
44 keys::kRequirements,
45 keys::kConvertedFromUserScript,
46 keys::kNaClModules,
47 keys::kPlugins,
48 keys::kContentScripts,
49 keys::kOmnibox,
50 keys::kDevToolsPage,
51 keys::kSidebar,
52 keys::kHomepageURL,
53 keys::kContentSecurityPolicy,
54 keys::kFileBrowserHandlers,
55 keys::kIncognito,
56 keys::kInputComponents,
57 keys::kTtsEngine,
58 keys::kIntents
59 };
60
61 // Keys that are not accessible by hosted apps.
62 const char* kNotHostedAppKeys[] = {
63 keys::kBrowserAction,
64 keys::kPageAction,
65 keys::kPageActions,
66 keys::kChromeURLOverrides,
67 keys::kContentScripts,
68 keys::kOmnibox,
69 keys::kDevToolsPage,
70 keys::kSidebar,
71 keys::kHomepageURL,
72 keys::kContentSecurityPolicy,
73 keys::kFileBrowserHandlers,
74 keys::kIncognito,
75 keys::kInputComponents,
76 keys::kTtsEngine,
77 keys::kIntents
78 };
79
80 // Keys not accessible by packaged aps.
81 const char* kNotPackagedAppKeys[] = {
82 keys::kBrowserAction,
83 keys::kPageAction,
84 keys::kPageActions,
85 keys::kChromeURLOverrides,
86 };
87
88 // Keys not accessible by platform apps.
89 const char* kNotPlatformAppKeys[] = {
90 keys::kBrowserAction,
91 keys::kPageAction,
92 keys::kPageActions,
93 keys::kChromeURLOverrides,
94 keys::kContentScripts,
95 keys::kOmnibox,
96 keys::kDevToolsPage,
97 keys::kSidebar,
98 keys::kHomepageURL,
99 };
100
101 // Returns all the manifest keys not including those in |filtered| or kTypeKeys.
102 std::set<std::string> GetAccessibleKeys(const char* filtered[], size_t length) {
103 std::set<std::string> all_keys = Manifest::GetAllKnownKeys();
104 std::set<std::string> filtered_keys(filtered, filtered + length);
105
106 // Starting with all possible manfiest keys, remove the keys that aren't
107 // accessible for the given type.
108 std::set<std::string> intermediate;
109 std::set_difference(all_keys.begin(), all_keys.end(),
110 filtered_keys.begin(), filtered_keys.end(),
111 std::insert_iterator<std::set<std::string> >(
112 intermediate, intermediate.begin()));
113
114 // Then remove the keys that specify types (app, platform_app, etc.).
115 std::set<std::string> result;
116 std::set<std::string> type_keys(
117 kTypeKeys, kTypeKeys + ARRAYSIZE_UNSAFE(kTypeKeys));
118 std::set_difference(intermediate.begin(), intermediate.end(),
119 type_keys.begin(), type_keys.end(),
120 std::insert_iterator<std::set<std::string> >(
121 result, result.begin()));
122
123 return result;
124 }
125
126 } // namespace
127
128 class ManifestTest : public testing::Test {
129 public:
130 ManifestTest() : default_value_("test") {}
131
132 protected:
133 void AssertType(Manifest* manifest, Manifest::Type type) {
134 EXPECT_EQ(type, manifest->GetType());
135 EXPECT_EQ(type == Manifest::kTypeTheme, manifest->IsTheme());
136 EXPECT_EQ(type == Manifest::kTypePlatformApp, manifest->IsPlatformApp());
137 EXPECT_EQ(type == Manifest::kTypePackagedApp, manifest->IsPackagedApp());
138 EXPECT_EQ(type == Manifest::kTypeHostedApp, manifest->IsHostedApp());
139 }
140
141 void TestRestrictedKeys(Manifest* manifest,
142 const char* restricted_keys[],
143 size_t restricted_keys_length) {
144 // Verify that the keys on the restricted key list for the given manifest
145 // fail validation and are filtered out.
146 DictionaryValue* value = manifest->value();
147 for (size_t i = 0; i < restricted_keys_length; ++i) {
148 std::string error, str;
149 value->Set(restricted_keys[i], Value::CreateStringValue(default_value_));
150 EXPECT_FALSE(manifest->ValidateManifest(&error));
151 EXPECT_EQ(error, ExtensionErrorUtils::FormatErrorMessage(
152 errors::kFeatureNotAllowed, restricted_keys[i]));
153 EXPECT_FALSE(manifest->GetString(restricted_keys[i], &str));
154 EXPECT_TRUE(value->Remove(restricted_keys[i], NULL));
155 }
156 }
157
158 std::string default_value_;
159 };
160
161 // Verifies that extensions can access the correct keys.
162 TEST_F(ManifestTest, Extension) {
163 // Generate the list of keys accessible by extensions.
164 std::set<std::string> extension_keys = GetAccessibleKeys(NULL, 0u);
165
166 // Construct the underlying value using every single key other than those
167 // on the restricted list.. We can use the same value for every key because we
168 // validate only by checking the presence of the keys.
169 DictionaryValue* value = new DictionaryValue();
170 for (std::set<std::string>::iterator i = extension_keys.begin();
171 i != extension_keys.end(); ++i)
172 value->Set(*i, Value::CreateStringValue(default_value_));
173
174 scoped_ptr<Manifest> manifest(new Manifest(value));
175 std::string error;
176 EXPECT_TRUE(manifest->ValidateManifest(&error));
177 EXPECT_EQ("", error);
178 AssertType(manifest.get(), Manifest::kTypeExtension);
179
180 // Verify that all the extension keys are accessible.
181 for (std::set<std::string>::iterator i = extension_keys.begin();
182 i != extension_keys.end(); ++i) {
183 std::string value;
184 manifest->GetString(*i, &value);
185 EXPECT_EQ(default_value_, value) << *i;
186 }
187
188 // Test DeepCopy and Equals.
189 scoped_ptr<Manifest> manifest2(manifest->DeepCopy());
190 EXPECT_TRUE(manifest->Equals(manifest2.get()));
191 EXPECT_TRUE(manifest2->Equals(manifest.get()));
192 value->Set("foo", Value::CreateStringValue("blah"));
193 EXPECT_FALSE(manifest->Equals(manifest2.get()));
194 }
195
196 // Verifies that themes can access the right keys.
197 TEST_F(ManifestTest, Theme) {
198 std::set<std::string> theme_keys =
199 GetAccessibleKeys(kNotThemeKeys, ARRAYSIZE_UNSAFE(kNotThemeKeys));
200
201 DictionaryValue* value = new DictionaryValue();
202 for (std::set<std::string>::iterator i = theme_keys.begin();
203 i != theme_keys.end(); ++i)
204 value->Set(*i, Value::CreateStringValue(default_value_));
205
206 std::string theme_key = keys::kTheme + std::string(".test");
207 value->Set(theme_key, Value::CreateStringValue(default_value_));
208
209 scoped_ptr<Manifest> manifest(new Manifest(value));
210 std::string error;
211 EXPECT_TRUE(manifest->ValidateManifest(&error));
212 EXPECT_EQ("", error);
213 AssertType(manifest.get(), Manifest::kTypeTheme);
214
215 // Verify that all the theme keys are accessible.
216 std::string str;
217 for (std::set<std::string>::iterator i = theme_keys.begin();
218 i != theme_keys.end(); ++i) {
219 EXPECT_TRUE(manifest->GetString(*i, &str));
220 EXPECT_EQ(default_value_, str) << *i;
221 }
222 EXPECT_TRUE(manifest->GetString(theme_key, &str));
223 EXPECT_EQ(default_value_, str) << theme_key;
224
225 // And that all the other keys fail validation and are filtered out
226 TestRestrictedKeys(manifest.get(), kNotThemeKeys,
227 ARRAYSIZE_UNSAFE(kNotThemeKeys));
228 };
229
230 // Verifies that platform apps can access the right keys.
231 TEST_F(ManifestTest, PlatformApp) {
232 std::set<std::string> platform_keys = GetAccessibleKeys(
233 kNotPlatformAppKeys,
234 ARRAYSIZE_UNSAFE(kNotPlatformAppKeys));
235
236 DictionaryValue* value = new DictionaryValue();
237 for (std::set<std::string>::iterator i = platform_keys.begin();
238 i != platform_keys.end(); ++i)
239 value->Set(*i, Value::CreateStringValue(default_value_));
240
241 value->Set(keys::kPlatformApp, Value::CreateBooleanValue(true));
242
243 scoped_ptr<Manifest> manifest(new Manifest(value));
244 std::string error;
245 EXPECT_TRUE(manifest->ValidateManifest(&error));
246 EXPECT_EQ("", error);
247 AssertType(manifest.get(), Manifest::kTypePlatformApp);
248
249 // Verify that all the platform app keys are accessible.
250 std::string str;
251 for (std::set<std::string>::iterator i = platform_keys.begin();
252 i != platform_keys.end(); ++i) {
253 EXPECT_TRUE(manifest->GetString(*i, &str));
254 EXPECT_EQ(default_value_, str) << *i;
255 }
256 bool is_platform_app = false;
257 EXPECT_TRUE(manifest->GetBoolean(keys::kPlatformApp, &is_platform_app));
258 EXPECT_TRUE(is_platform_app) << keys::kPlatformApp;
259
260 // And that all the other keys fail validation and are filtered out.
261 TestRestrictedKeys(manifest.get(), kNotPlatformAppKeys,
262 ARRAYSIZE_UNSAFE(kNotPlatformAppKeys));
263 };
264
265 // Verifies that hosted apps can access the right keys.
266 TEST_F(ManifestTest, HostedApp) {
267 std::set<std::string> keys = GetAccessibleKeys(
268 kNotHostedAppKeys,
269 ARRAYSIZE_UNSAFE(kNotHostedAppKeys));
270
271 DictionaryValue* value = new DictionaryValue();
272 for (std::set<std::string>::iterator i = keys.begin();
273 i != keys.end(); ++i)
274 value->Set(*i, Value::CreateStringValue(default_value_));
275
276 value->Set(keys::kWebURLs, Value::CreateStringValue(default_value_));
277
278 scoped_ptr<Manifest> manifest(new Manifest(value));
279 std::string error;
280 EXPECT_TRUE(manifest->ValidateManifest(&error));
281 EXPECT_EQ("", error);
282 AssertType(manifest.get(), Manifest::kTypeHostedApp);
283
284 // Verify that all the hosted app keys are accessible.
285 std::string str;
286 for (std::set<std::string>::iterator i = keys.begin();
287 i != keys.end(); ++i) {
288 EXPECT_TRUE(manifest->GetString(*i, &str));
289 EXPECT_EQ(default_value_, str) << *i;
290 }
291 EXPECT_TRUE(manifest->GetString(keys::kWebURLs, &str));
292 EXPECT_EQ(default_value_, str) << keys::kWebURLs;
293
294 // And that all the other keys fail validation and are filtered out.
295 TestRestrictedKeys(manifest.get(), kNotHostedAppKeys,
296 ARRAYSIZE_UNSAFE(kNotHostedAppKeys));
297 };
298
299 // Verifies that packaged apps can access the right keys.
300 TEST_F(ManifestTest, PackagedApp) {
301 std::set<std::string> keys = GetAccessibleKeys(
302 kNotPackagedAppKeys,
303 ARRAYSIZE_UNSAFE(kNotPackagedAppKeys));
304
305 DictionaryValue* value = new DictionaryValue();
306 for (std::set<std::string>::iterator i = keys.begin();
307 i != keys.end(); ++i)
308 value->Set(*i, Value::CreateStringValue(default_value_));
309 value->Set(keys::kApp, Value::CreateStringValue(default_value_));
310
311 scoped_ptr<Manifest> manifest(new Manifest(value));
312 std::string error;
313 EXPECT_TRUE(manifest->ValidateManifest(&error));
314 EXPECT_EQ("", error);
315 AssertType(manifest.get(), Manifest::kTypePackagedApp);
316
317 // Verify that all the packaged app keys are accessible.
318 std::string str;
319 for (std::set<std::string>::iterator i = keys.begin();
320 i != keys.end(); ++i) {
321 EXPECT_TRUE(manifest->GetString(*i, &str));
322 EXPECT_EQ(default_value_, str) << *i;
323 }
324 EXPECT_TRUE(manifest->GetString(keys::kApp, &str));
325 EXPECT_EQ(default_value_, str) << keys::kApp;
326
327 // And that all the other keys fail validation and are filtered out.
328 TestRestrictedKeys(manifest.get(), kNotPackagedAppKeys,
329 ARRAYSIZE_UNSAFE(kNotPackagedAppKeys));
330 };
331
332 // Verifies that the various getters filter unknown and restricted keys.
333 TEST_F(ManifestTest, Getters) {
334 DictionaryValue* value = new DictionaryValue();
335 scoped_ptr<Manifest> manifest(new Manifest(value));
336 std::string unknown_key = "asdfaskldjf";
337
338 // Verify that the key filtering works for each of the getters.
339 // Get and GetBoolean
340 bool expected_bool = true, actual_bool = false;
341 value->Set(unknown_key, Value::CreateBooleanValue(expected_bool));
342 EXPECT_FALSE(manifest->HasKey(unknown_key));
343 EXPECT_FALSE(manifest->GetBoolean(unknown_key, &actual_bool));
344 EXPECT_FALSE(actual_bool);
345 Value* actual_value = NULL;
346 EXPECT_FALSE(manifest->Get(unknown_key, &actual_value));
347 EXPECT_TRUE(value->Remove(unknown_key, NULL));
348
349 // GetInteger
350 int expected_int = 5, actual_int = 0;
351 value->Set(unknown_key, Value::CreateIntegerValue(expected_int));
352 EXPECT_FALSE(manifest->GetInteger(unknown_key, &actual_int));
353 EXPECT_NE(expected_int, actual_int);
354 EXPECT_TRUE(value->Remove(unknown_key, NULL));
355
356 // GetString
357 std::string expected_str = "hello", actual_str;
358 value->Set(unknown_key, Value::CreateStringValue(expected_str));
359 EXPECT_FALSE(manifest->GetString(unknown_key, &actual_str));
360 EXPECT_NE(expected_str, actual_str);
361 EXPECT_TRUE(value->Remove(unknown_key, NULL));
362
363 // GetString (string16)
364 string16 expected_str16(UTF8ToUTF16("hello")), actual_str16;
365 value->Set(unknown_key, Value::CreateStringValue(expected_str16));
366 EXPECT_FALSE(manifest->GetString(unknown_key, &actual_str16));
367 EXPECT_NE(expected_str16, actual_str16);
368 EXPECT_TRUE(value->Remove(unknown_key, NULL));
369
370 // GetDictionary
371 DictionaryValue* expected_dict = new DictionaryValue();
372 DictionaryValue* actual_dict = NULL;
373 expected_dict->Set("foo", Value::CreateStringValue("bar"));
374 value->Set(unknown_key, expected_dict);
375 EXPECT_FALSE(manifest->GetDictionary(unknown_key, &actual_dict));
376 EXPECT_EQ(NULL, actual_dict);
377 std::string path = unknown_key + ".foo";
378 EXPECT_FALSE(manifest->GetString(path, &actual_str));
379 EXPECT_NE("bar", actual_str);
380 EXPECT_TRUE(value->Remove(unknown_key, NULL));
381
382 // GetList
383 ListValue* expected_list = new ListValue();
384 ListValue* actual_list = NULL;
385 expected_list->Append(Value::CreateStringValue("blah"));
386 value->Set(unknown_key, expected_list);
387 EXPECT_FALSE(manifest->GetList(unknown_key, &actual_list));
388 EXPECT_EQ(NULL, actual_list);
389 EXPECT_TRUE(value->Remove(unknown_key, NULL));
390 }
391
392 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/common/extensions/manifest.cc ('k') | chrome/renderer/extensions/app_bindings.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698