1 // Copyright (c) 2013 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 "base/file_util.h"
6 #include "base/format_macros.h"
7 #include "base/path_service.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/stringprintf.h"
10 #include "chrome/common/chrome_paths.h"
11 #include "chrome/common/extensions/command.h"
12 #include "chrome/common/extensions/extension_file_util.h"
13 #include "chrome/common/extensions/extension_test_util.h"
14 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
15 #include "chrome/common/url_constants.h"
16 #include "extensions/common/extension.h"
17 #include "extensions/common/extension_resource.h"
18 #include "extensions/common/manifest.h"
19 #include "extensions/common/permissions/permissions_data.h"
20 #include "net/base/mime_sniffer.h"
21 #include "net/dns/mock_host_resolver.h"
22 #include "skia/ext/image_operations.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "third_party/skia/include/core/SkBitmap.h"
25 #include "ui/gfx/codec/png_codec.h"
26 #include "url/gurl.h"
27
28 using extension_test_util::LoadManifest;
29 using extension_test_util::LoadManifestStrict;
30 using base::FilePath;
31
32 namespace extensions {
33
34 // We persist location values in the preferences, so this is a sanity test that
35 // someone doesn't accidentally change them.
TEST(ExtensionTest,LocationValuesTest)36 TEST(ExtensionTest, LocationValuesTest) {
37 ASSERT_EQ(0, Manifest::INVALID_LOCATION);
38 ASSERT_EQ(1, Manifest::INTERNAL);
39 ASSERT_EQ(2, Manifest::EXTERNAL_PREF);
40 ASSERT_EQ(3, Manifest::EXTERNAL_REGISTRY);
41 ASSERT_EQ(4, Manifest::UNPACKED);
42 ASSERT_EQ(5, Manifest::COMPONENT);
43 ASSERT_EQ(6, Manifest::EXTERNAL_PREF_DOWNLOAD);
44 ASSERT_EQ(7, Manifest::EXTERNAL_POLICY_DOWNLOAD);
45 ASSERT_EQ(8, Manifest::COMMAND_LINE);
46 ASSERT_EQ(9, Manifest::EXTERNAL_POLICY);
47 }
48
TEST(ExtensionTest,LocationPriorityTest)49 TEST(ExtensionTest, LocationPriorityTest) {
50 for (int i = 0; i < Manifest::NUM_LOCATIONS; i++) {
51 Manifest::Location loc = static_cast<Manifest::Location>(i);
52
53 // INVALID is not a valid location.
54 if (loc == Manifest::INVALID_LOCATION)
55 continue;
56
57 // Comparing a location that has no rank will hit a CHECK. Do a
58 // compare with every valid location, to be sure each one is covered.
59
60 // Check that no install source can override a componenet extension.
61 ASSERT_EQ(Manifest::COMPONENT,
62 Manifest::GetHigherPriorityLocation(Manifest::COMPONENT, loc));
63 ASSERT_EQ(Manifest::COMPONENT,
64 Manifest::GetHigherPriorityLocation(loc, Manifest::COMPONENT));
65
66 // Check that any source can override a user install. This might change
67 // in the future, in which case this test should be updated.
68 ASSERT_EQ(loc,
69 Manifest::GetHigherPriorityLocation(Manifest::INTERNAL, loc));
70 ASSERT_EQ(loc,
71 Manifest::GetHigherPriorityLocation(loc, Manifest::INTERNAL));
72 }
73
74 // Check a few interesting cases that we know can happen:
75 ASSERT_EQ(Manifest::EXTERNAL_POLICY_DOWNLOAD,
76 Manifest::GetHigherPriorityLocation(
77 Manifest::EXTERNAL_POLICY_DOWNLOAD,
78 Manifest::EXTERNAL_PREF));
79
80 ASSERT_EQ(Manifest::EXTERNAL_PREF,
81 Manifest::GetHigherPriorityLocation(
82 Manifest::INTERNAL,
83 Manifest::EXTERNAL_PREF));
84 }
85
TEST(ExtensionTest,GetResourceURLAndPath)86 TEST(ExtensionTest, GetResourceURLAndPath) {
87 scoped_refptr<Extension> extension = LoadManifestStrict("empty_manifest",
88 "empty.json");
89 EXPECT_TRUE(extension.get());
90
91 EXPECT_EQ(extension->url().spec() + "bar/baz.js",
92 Extension::GetResourceURL(extension->url(), "bar/baz.js").spec());
93 EXPECT_EQ(extension->url().spec() + "baz.js",
94 Extension::GetResourceURL(extension->url(),
95 "bar/../baz.js").spec());
96 EXPECT_EQ(extension->url().spec() + "baz.js",
97 Extension::GetResourceURL(extension->url(), "../baz.js").spec());
98
99 // Test that absolute-looking paths ("/"-prefixed) are pasted correctly.
100 EXPECT_EQ(extension->url().spec() + "test.html",
101 extension->GetResourceURL("/test.html").spec());
102 }
103
TEST(ExtensionTest,GetResource)104 TEST(ExtensionTest, GetResource) {
105 const FilePath valid_path_test_cases[] = {
106 FilePath(FILE_PATH_LITERAL("manifest.json")),
107 FilePath(FILE_PATH_LITERAL("a/b/c/manifest.json")),
108 FilePath(FILE_PATH_LITERAL("com/manifest.json")),
109 FilePath(FILE_PATH_LITERAL("lpt/manifest.json")),
110 };
111 const FilePath invalid_path_test_cases[] = {
112 // Directory name
113 FilePath(FILE_PATH_LITERAL("src/")),
114 // Contains a drive letter specification.
115 FilePath(FILE_PATH_LITERAL("C:\\manifest.json")),
116 // Use backslash '\\' as separator.
117 FilePath(FILE_PATH_LITERAL("a\\b\\c\\manifest.json")),
118 // Reserved Characters with extension
119 FilePath(FILE_PATH_LITERAL("mani>fest.json")),
120 FilePath(FILE_PATH_LITERAL("mani<fest.json")),
121 FilePath(FILE_PATH_LITERAL("mani*fest.json")),
122 FilePath(FILE_PATH_LITERAL("mani:fest.json")),
123 FilePath(FILE_PATH_LITERAL("mani?fest.json")),
124 FilePath(FILE_PATH_LITERAL("mani|fest.json")),
125 // Reserved Characters without extension
126 FilePath(FILE_PATH_LITERAL("mani>fest")),
127 FilePath(FILE_PATH_LITERAL("mani<fest")),
128 FilePath(FILE_PATH_LITERAL("mani*fest")),
129 FilePath(FILE_PATH_LITERAL("mani:fest")),
130 FilePath(FILE_PATH_LITERAL("mani?fest")),
131 FilePath(FILE_PATH_LITERAL("mani|fest")),
132 // Reserved Names with extension.
133 FilePath(FILE_PATH_LITERAL("com1.json")),
134 FilePath(FILE_PATH_LITERAL("com9.json")),
135 FilePath(FILE_PATH_LITERAL("LPT1.json")),
136 FilePath(FILE_PATH_LITERAL("LPT9.json")),
137 FilePath(FILE_PATH_LITERAL("CON.json")),
138 FilePath(FILE_PATH_LITERAL("PRN.json")),
139 FilePath(FILE_PATH_LITERAL("AUX.json")),
140 FilePath(FILE_PATH_LITERAL("NUL.json")),
141 // Reserved Names without extension.
142 FilePath(FILE_PATH_LITERAL("com1")),
143 FilePath(FILE_PATH_LITERAL("com9")),
144 FilePath(FILE_PATH_LITERAL("LPT1")),
145 FilePath(FILE_PATH_LITERAL("LPT9")),
146 FilePath(FILE_PATH_LITERAL("CON")),
147 FilePath(FILE_PATH_LITERAL("PRN")),
148 FilePath(FILE_PATH_LITERAL("AUX")),
149 FilePath(FILE_PATH_LITERAL("NUL")),
150 // Reserved Names as directory.
151 FilePath(FILE_PATH_LITERAL("com1/manifest.json")),
152 FilePath(FILE_PATH_LITERAL("com9/manifest.json")),
153 FilePath(FILE_PATH_LITERAL("LPT1/manifest.json")),
154 FilePath(FILE_PATH_LITERAL("LPT9/manifest.json")),
155 FilePath(FILE_PATH_LITERAL("CON/manifest.json")),
156 FilePath(FILE_PATH_LITERAL("PRN/manifest.json")),
157 FilePath(FILE_PATH_LITERAL("AUX/manifest.json")),
158 FilePath(FILE_PATH_LITERAL("NUL/manifest.json")),
159 };
160
161 scoped_refptr<Extension> extension = LoadManifestStrict("empty_manifest",
162 "empty.json");
163 EXPECT_TRUE(extension.get());
164 for (size_t i = 0; i < arraysize(valid_path_test_cases); ++i)
165 EXPECT_TRUE(!extension->GetResource(valid_path_test_cases[i]).empty());
166 for (size_t i = 0; i < arraysize(invalid_path_test_cases); ++i)
167 EXPECT_TRUE(extension->GetResource(invalid_path_test_cases[i]).empty());
168 }
169
TEST(ExtensionTest,GetAbsolutePathNoError)170 TEST(ExtensionTest, GetAbsolutePathNoError) {
171 scoped_refptr<Extension> extension = LoadManifestStrict("absolute_path",
172 "absolute.json");
173 EXPECT_TRUE(extension.get());
174 std::string err;
175 std::vector<InstallWarning> warnings;
176 EXPECT_TRUE(extension_file_util::ValidateExtension(extension.get(),
177 &err, &warnings));
178 EXPECT_EQ(0U, warnings.size());
179
180 EXPECT_EQ(extension->path().AppendASCII("test.html").value(),
181 extension->GetResource("test.html").GetFilePath().value());
182 EXPECT_EQ(extension->path().AppendASCII("test.js").value(),
183 extension->GetResource("test.js").GetFilePath().value());
184 }
185
186
TEST(ExtensionTest,IdIsValid)187 TEST(ExtensionTest, IdIsValid) {
188 EXPECT_TRUE(Extension::IdIsValid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
189 EXPECT_TRUE(Extension::IdIsValid("pppppppppppppppppppppppppppppppp"));
190 EXPECT_TRUE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmnop"));
191 EXPECT_TRUE(Extension::IdIsValid("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"));
192 EXPECT_FALSE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmno"));
193 EXPECT_FALSE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmnopa"));
194 EXPECT_FALSE(Extension::IdIsValid("0123456789abcdef0123456789abcdef"));
195 EXPECT_FALSE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmnoq"));
196 EXPECT_FALSE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmno0"));
197 }
198
199
200 // This test ensures that the mimetype sniffing code stays in sync with the
201 // actual crx files that we test other parts of the system with.
TEST(ExtensionTest,MimeTypeSniffing)202 TEST(ExtensionTest, MimeTypeSniffing) {
203 base::FilePath path;
204 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
205 path = path.AppendASCII("extensions").AppendASCII("good.crx");
206
207 std::string data;
208 ASSERT_TRUE(base::ReadFileToString(path, &data));
209
210 std::string result;
211 EXPECT_TRUE(net::SniffMimeType(data.c_str(),
212 data.size(),
213 GURL("http://www.example.com/foo.crx"),
214 std::string(),
215 &result));
216 EXPECT_EQ(std::string(Extension::kMimeType), result);
217
218 data.clear();
219 result.clear();
220 path = path.DirName().AppendASCII("bad_magic.crx");
221 ASSERT_TRUE(base::ReadFileToString(path, &data));
222 EXPECT_TRUE(net::SniffMimeType(data.c_str(),
223 data.size(),
224 GURL("http://www.example.com/foo.crx"),
225 std::string(),
226 &result));
227 EXPECT_EQ("application/octet-stream", result);
228 }
229
TEST(ExtensionTest,WantsFileAccess)230 TEST(ExtensionTest, WantsFileAccess) {
231 scoped_refptr<Extension> extension;
232 GURL file_url("file:///etc/passwd");
233
234 // Ignore the policy delegate for this test.
235 PermissionsData::SetPolicyDelegate(NULL);
236
237 // <all_urls> permission
238 extension = LoadManifest("permissions", "permissions_all_urls.json");
239 EXPECT_TRUE(extension->wants_file_access());
240 EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
241 extension.get(), file_url, file_url, -1, NULL, -1, NULL));
242 extension = LoadManifest(
243 "permissions", "permissions_all_urls.json", Extension::ALLOW_FILE_ACCESS);
244 EXPECT_TRUE(extension->wants_file_access());
245 EXPECT_TRUE(PermissionsData::CanExecuteScriptOnPage(
246 extension.get(), file_url, file_url, -1, NULL, -1, NULL));
247
248 // file:///* permission
249 extension = LoadManifest("permissions", "permissions_file_scheme.json");
250 EXPECT_TRUE(extension->wants_file_access());
251 EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
252 extension.get(), file_url, file_url, -1, NULL, -1, NULL));
253 extension = LoadManifest("permissions",
254 "permissions_file_scheme.json",
255 Extension::ALLOW_FILE_ACCESS);
256 EXPECT_TRUE(extension->wants_file_access());
257 EXPECT_TRUE(PermissionsData::CanExecuteScriptOnPage(
258 extension.get(), file_url, file_url, -1, NULL, -1, NULL));
259
260 // http://* permission
261 extension = LoadManifest("permissions", "permissions_http_scheme.json");
262 EXPECT_FALSE(extension->wants_file_access());
263 EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
264 extension.get(), file_url, file_url, -1, NULL, -1, NULL));
265 extension = LoadManifest("permissions",
266 "permissions_http_scheme.json",
267 Extension::ALLOW_FILE_ACCESS);
268 EXPECT_FALSE(extension->wants_file_access());
269 EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
270 extension.get(), file_url, file_url, -1, NULL, -1, NULL));
271
272 // <all_urls> content script match
273 extension = LoadManifest("permissions", "content_script_all_urls.json");
274 EXPECT_TRUE(extension->wants_file_access());
275 EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
276 extension.get(),
277 file_url,
278 file_url,
279 -1,
280 &ContentScriptsInfo::GetContentScripts(extension.get())[0],
281 -1,
282 NULL));
283 extension = LoadManifest("permissions", "content_script_all_urls.json",
284 Extension::ALLOW_FILE_ACCESS);
285 EXPECT_TRUE(extension->wants_file_access());
286 EXPECT_TRUE(PermissionsData::CanExecuteScriptOnPage(
287 extension.get(),
288 file_url,
289 file_url,
290 -1,
291 &ContentScriptsInfo::GetContentScripts(extension.get())[0],
292 -1,
293 NULL));
294
295 // file:///* content script match
296 extension = LoadManifest("permissions", "content_script_file_scheme.json");
297 EXPECT_TRUE(extension->wants_file_access());
298 EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
299 extension.get(),
300 file_url,
301 file_url,
302 -1,
303 &ContentScriptsInfo::GetContentScripts(extension.get())[0],
304 -1,
305 NULL));
306 extension = LoadManifest("permissions", "content_script_file_scheme.json",
307 Extension::ALLOW_FILE_ACCESS);
308 EXPECT_TRUE(extension->wants_file_access());
309 EXPECT_TRUE(PermissionsData::CanExecuteScriptOnPage(
310 extension.get(),
311 file_url,
312 file_url,
313 -1,
314 &ContentScriptsInfo::GetContentScripts(extension.get())[0],
315 -1,
316 NULL));
317
318 // http://* content script match
319 extension = LoadManifest("permissions", "content_script_http_scheme.json");
320 EXPECT_FALSE(extension->wants_file_access());
321 EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
322 extension.get(),
323 file_url,
324 file_url,
325 -1,
326 &ContentScriptsInfo::GetContentScripts(extension.get())[0],
327 -1,
328 NULL));
329 extension = LoadManifest("permissions", "content_script_http_scheme.json",
330 Extension::ALLOW_FILE_ACCESS);
331 EXPECT_FALSE(extension->wants_file_access());
332 EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
333 extension.get(),
334 file_url,
335 file_url,
336 -1,
337 &ContentScriptsInfo::GetContentScripts(extension.get())[0],
338 -1,
339 NULL));
340 }
341
TEST(ExtensionTest,ExtraFlags)342 TEST(ExtensionTest, ExtraFlags) {
343 scoped_refptr<Extension> extension;
344 extension = LoadManifest("app", "manifest.json", Extension::FROM_WEBSTORE);
345 EXPECT_TRUE(extension->from_webstore());
346
347 extension = LoadManifest("app", "manifest.json", Extension::FROM_BOOKMARK);
348 EXPECT_TRUE(extension->from_bookmark());
349
350 extension = LoadManifest("app", "manifest.json", Extension::NO_FLAGS);
351 EXPECT_FALSE(extension->from_bookmark());
352 EXPECT_FALSE(extension->from_webstore());
353 }
354
355 } // namespace extensions
356