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. 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 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 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 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 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 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. 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 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 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