1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/common/extensions/extension_file_util.h"
7 #include "base/file_util.h"
8 #include "base/json/json_string_value_serializer.h"
9 #include "base/path_service.h"
10 #include "base/scoped_temp_dir.h"
11 #include "base/stringprintf.h"
12 #include "base/utf_string_conversions.h"
13 #include "chrome/common/chrome_paths.h"
14 #include "chrome/common/extensions/extension.h"
15 #include "chrome/common/extensions/extension_manifest_constants.h"
16 #include "grit/generated_resources.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "ui/base/l10n/l10n_util.h"
21 using extensions::Extension
;
23 namespace keys
= extension_manifest_keys
;
26 // http://crbug.com/106381
27 #define InstallUninstallGarbageCollect DISABLED_InstallUninstallGarbageCollect
29 TEST(ExtensionFileUtil
, InstallUninstallGarbageCollect
) {
31 ASSERT_TRUE(temp
.CreateUniqueTempDir());
33 // Create a source extension.
34 std::string
extension_id("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
35 std::string
version("1.0");
36 FilePath src
= temp
.path().AppendASCII(extension_id
);
37 ASSERT_TRUE(file_util::CreateDirectory(src
));
39 // Create a extensions tree.
40 FilePath all_extensions
= temp
.path().AppendASCII("extensions");
41 ASSERT_TRUE(file_util::CreateDirectory(all_extensions
));
43 // Install in empty directory. Should create parent directories as needed.
44 FilePath version_1
= extension_file_util::InstallExtension(src
,
48 ASSERT_EQ(version_1
.value(),
49 all_extensions
.AppendASCII(extension_id
).AppendASCII("1.0_0")
51 ASSERT_TRUE(file_util::DirectoryExists(version_1
));
53 // Should have moved the source.
54 ASSERT_FALSE(file_util::DirectoryExists(src
));
56 // Install again. Should create a new one with different name.
57 ASSERT_TRUE(file_util::CreateDirectory(src
));
58 FilePath version_2
= extension_file_util::InstallExtension(src
,
62 ASSERT_EQ(version_2
.value(),
63 all_extensions
.AppendASCII(extension_id
).AppendASCII("1.0_1")
65 ASSERT_TRUE(file_util::DirectoryExists(version_2
));
67 // Should have moved the source.
68 ASSERT_FALSE(file_util::DirectoryExists(src
));
70 // Install yet again. Should create a new one with a different name.
71 ASSERT_TRUE(file_util::CreateDirectory(src
));
72 FilePath version_3
= extension_file_util::InstallExtension(src
,
76 ASSERT_EQ(version_3
.value(),
77 all_extensions
.AppendASCII(extension_id
).AppendASCII("1.0_2")
79 ASSERT_TRUE(file_util::DirectoryExists(version_3
));
81 // Collect garbage. Should remove first one.
82 std::multimap
<std::string
, FilePath
> extension_paths
;
83 extension_paths
.insert(std::make_pair(extension_id
,
84 FilePath().AppendASCII(extension_id
).Append(version_2
.BaseName())));
85 extension_paths
.insert(std::make_pair(extension_id
,
86 FilePath().AppendASCII(extension_id
).Append(version_3
.BaseName())));
87 extension_file_util::GarbageCollectExtensions(all_extensions
,
89 ASSERT_FALSE(file_util::DirectoryExists(version_1
));
90 ASSERT_TRUE(file_util::DirectoryExists(version_2
));
91 ASSERT_TRUE(file_util::DirectoryExists(version_3
));
93 // Uninstall. Should remove entire extension subtree.
94 extension_file_util::UninstallExtension(all_extensions
, extension_id
);
95 ASSERT_FALSE(file_util::DirectoryExists(version_2
.DirName()));
96 ASSERT_FALSE(file_util::DirectoryExists(version_3
.DirName()));
97 ASSERT_TRUE(file_util::DirectoryExists(all_extensions
));
100 TEST(ExtensionFileUtil
, LoadExtensionWithValidLocales
) {
101 FilePath install_dir
;
102 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &install_dir
));
103 install_dir
= install_dir
.AppendASCII("extensions")
105 .AppendASCII("Extensions")
106 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
107 .AppendASCII("1.0.0.0");
110 scoped_refptr
<Extension
> extension(extension_file_util::LoadExtension(
111 install_dir
, Extension::LOAD
, Extension::NO_FLAGS
, &error
));
112 ASSERT_TRUE(extension
!= NULL
);
113 EXPECT_EQ("The first extension that I made.", extension
->description());
116 TEST(ExtensionFileUtil
, LoadExtensionWithoutLocalesFolder
) {
117 FilePath install_dir
;
118 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &install_dir
));
119 install_dir
= install_dir
.AppendASCII("extensions")
121 .AppendASCII("Extensions")
122 .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa")
126 scoped_refptr
<Extension
> extension(extension_file_util::LoadExtension(
127 install_dir
, Extension::LOAD
, Extension::NO_FLAGS
, &error
));
128 ASSERT_FALSE(extension
== NULL
);
129 EXPECT_TRUE(error
.empty());
133 // http://crbug.com/106381
134 #define CheckIllegalFilenamesNoUnderscores \
135 DISABLED_CheckIllegalFilenamesNoUnderscores
137 TEST(ExtensionFileUtil
, CheckIllegalFilenamesNoUnderscores
) {
139 ASSERT_TRUE(temp
.CreateUniqueTempDir());
141 FilePath src_path
= temp
.path().AppendASCII("some_dir");
142 ASSERT_TRUE(file_util::CreateDirectory(src_path
));
144 std::string data
= "{ \"name\": { \"message\": \"foobar\" } }";
145 ASSERT_TRUE(file_util::WriteFile(src_path
.AppendASCII("some_file.txt"),
146 data
.c_str(), data
.length()));
148 EXPECT_TRUE(extension_file_util::CheckForIllegalFilenames(temp
.path(),
153 // http://crbug.com/106381
154 #define CheckIllegalFilenamesOnlyReserved \
155 DISABLED_CheckIllegalFilenamesOnlyReserved
157 TEST(ExtensionFileUtil
, CheckIllegalFilenamesOnlyReserved
) {
159 ASSERT_TRUE(temp
.CreateUniqueTempDir());
161 FilePath src_path
= temp
.path().Append(Extension::kLocaleFolder
);
162 ASSERT_TRUE(file_util::CreateDirectory(src_path
));
165 EXPECT_TRUE(extension_file_util::CheckForIllegalFilenames(temp
.path(),
170 // http://crbug.com/106381
171 #define CheckIllegalFilenamesReservedAndIllegal \
172 DISABLED_CheckIllegalFilenamesReservedAndIllegal
174 TEST(ExtensionFileUtil
, CheckIllegalFilenamesReservedAndIllegal
) {
176 ASSERT_TRUE(temp
.CreateUniqueTempDir());
178 FilePath src_path
= temp
.path().Append(Extension::kLocaleFolder
);
179 ASSERT_TRUE(file_util::CreateDirectory(src_path
));
181 src_path
= temp
.path().AppendASCII("_some_dir");
182 ASSERT_TRUE(file_util::CreateDirectory(src_path
));
185 EXPECT_FALSE(extension_file_util::CheckForIllegalFilenames(temp
.path(),
189 TEST(ExtensionFileUtil
, LoadExtensionGivesHelpfullErrorOnMissingManifest
) {
190 FilePath install_dir
;
191 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &install_dir
));
192 install_dir
= install_dir
.AppendASCII("extensions")
194 .AppendASCII("Extensions")
195 .AppendASCII("dddddddddddddddddddddddddddddddd")
199 scoped_refptr
<Extension
> extension(extension_file_util::LoadExtension(
200 install_dir
, Extension::LOAD
, Extension::NO_FLAGS
, &error
));
201 ASSERT_TRUE(extension
== NULL
);
202 ASSERT_FALSE(error
.empty());
203 ASSERT_STREQ("Manifest file is missing or unreadable.", error
.c_str());
206 TEST(ExtensionFileUtil
, LoadExtensionGivesHelpfullErrorOnBadManifest
) {
207 FilePath install_dir
;
208 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &install_dir
));
209 install_dir
= install_dir
.AppendASCII("extensions")
211 .AppendASCII("Extensions")
212 .AppendASCII("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
216 scoped_refptr
<Extension
> extension(extension_file_util::LoadExtension(
217 install_dir
, Extension::LOAD
, Extension::NO_FLAGS
, &error
));
218 ASSERT_TRUE(extension
== NULL
);
219 ASSERT_FALSE(error
.empty());
220 ASSERT_STREQ("Manifest is not valid JSON. "
221 "Line: 2, column: 16, Syntax error.", error
.c_str());
224 TEST(ExtensionFileUtil
, FailLoadingNonUTF8Scripts
) {
225 FilePath install_dir
;
226 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &install_dir
));
227 install_dir
= install_dir
.AppendASCII("extensions")
229 .AppendASCII("bad_encoding");
232 scoped_refptr
<Extension
> extension(extension_file_util::LoadExtension(
233 install_dir
, Extension::LOAD
, Extension::NO_FLAGS
, &error
));
234 ASSERT_TRUE(extension
== NULL
);
235 ASSERT_STREQ("Could not load file 'bad_encoding.js' for content script. "
236 "It isn't UTF-8 encoded.", error
.c_str());
239 TEST(ExtensionFileUtil
, ExtensionURLToRelativeFilePath
) {
240 #define URL_PREFIX "chrome-extension://extension-id/"
243 const char* expected_relative_path
;
245 { URL_PREFIX
"simple.html",
247 { URL_PREFIX
"directory/to/file.html",
248 "directory/to/file.html" },
249 { URL_PREFIX
"escape%20spaces.html",
250 "escape spaces.html" },
251 { URL_PREFIX
"%C3%9Cber.html",
252 "\xC3\x9C" "ber.html" },
254 { URL_PREFIX
"C%3A/simple.html",
257 { URL_PREFIX
"////simple.html",
259 { URL_PREFIX
"/simple.html",
261 { URL_PREFIX
"\\simple.html",
263 { URL_PREFIX
"\\\\foo\\simple.html",
268 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
269 GURL
url(test_cases
[i
].url
);
270 #if defined(OS_POSIX)
271 FilePath
expected_path(test_cases
[i
].expected_relative_path
);
272 #elif defined(OS_WIN)
273 FilePath
expected_path(UTF8ToWide(test_cases
[i
].expected_relative_path
));
276 FilePath actual_path
=
277 extension_file_util::ExtensionURLToRelativeFilePath(url
);
278 EXPECT_FALSE(actual_path
.IsAbsolute()) <<
279 " For the path " << actual_path
.value();
280 EXPECT_EQ(expected_path
.value(), actual_path
.value()) <<
281 " For the path " << url
;
285 TEST(ExtensionFileUtil
, ExtensionResourceURLToFilePath
) {
286 // Setup filesystem for testing.
288 ASSERT_TRUE(file_util::CreateNewTempDirectory(
289 FILE_PATH_LITERAL(""), &root_path
));
290 ASSERT_TRUE(file_util::AbsolutePath(&root_path
));
292 FilePath api_path
= root_path
.Append(FILE_PATH_LITERAL("apiname"));
293 ASSERT_TRUE(file_util::CreateDirectory(api_path
));
295 const char data
[] = "Test Data";
296 FilePath resource_path
= api_path
.Append(FILE_PATH_LITERAL("test.js"));
297 ASSERT_TRUE(file_util::WriteFile(resource_path
, data
, sizeof(data
)));
298 resource_path
= api_path
.Append(FILE_PATH_LITERAL("escape spaces.js"));
299 ASSERT_TRUE(file_util::WriteFile(resource_path
, data
, sizeof(data
)));
301 #ifdef FILE_PATH_USES_WIN_SEPARATORS
306 #define URL_PREFIX "chrome-extension-resource://"
309 const FilePath::CharType
* expected_path
;
311 { URL_PREFIX
"apiname/test.js",
312 FILE_PATH_LITERAL("test.js") },
313 { URL_PREFIX
"/apiname/test.js",
314 FILE_PATH_LITERAL("test.js") },
316 { URL_PREFIX
"apiname/%74%65st.js",
317 FILE_PATH_LITERAL("test.js") },
318 { URL_PREFIX
"apiname/escape%20spaces.js",
319 FILE_PATH_LITERAL("escape spaces.js") },
320 // Test file does not exist.
321 { URL_PREFIX
"apiname/directory/to/file.js",
323 // Test apiname/../../test.js
324 { URL_PREFIX
"apiname/../../test.js",
325 FILE_PATH_LITERAL("test.js") },
326 { URL_PREFIX
"apiname/..%2F../test.js",
328 { URL_PREFIX
"apiname/f/../../../test.js",
329 FILE_PATH_LITERAL("test.js") },
330 { URL_PREFIX
"apiname/f%2F..%2F..%2F../test.js",
336 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
337 GURL
url(test_cases
[i
].url
);
338 FilePath expected_path
;
339 if (test_cases
[i
].expected_path
)
340 expected_path
= root_path
.Append(FILE_PATH_LITERAL("apiname")).Append(
341 test_cases
[i
].expected_path
);
342 FilePath actual_path
=
343 extension_file_util::ExtensionResourceURLToFilePath(url
, root_path
);
344 EXPECT_EQ(expected_path
.value(), actual_path
.value()) <<
345 " For the path " << url
;
347 // Remove temp files.
348 ASSERT_TRUE(file_util::Delete(root_path
, true));
351 static scoped_refptr
<Extension
> LoadExtensionManifest(
352 DictionaryValue
* manifest
,
353 const FilePath
& manifest_dir
,
354 Extension::Location location
,
356 std::string
* error
) {
357 scoped_refptr
<Extension
> extension
= Extension::Create(
358 manifest_dir
, location
, *manifest
, extra_flags
, error
);
362 static scoped_refptr
<Extension
> LoadExtensionManifest(
363 const std::string
& manifest_value
,
364 const FilePath
& manifest_dir
,
365 Extension::Location location
,
367 std::string
* error
) {
368 JSONStringValueSerializer
serializer(manifest_value
);
369 scoped_ptr
<Value
> result(serializer
.Deserialize(NULL
, error
));
372 CHECK_EQ(Value::TYPE_DICTIONARY
, result
->GetType());
373 return LoadExtensionManifest(static_cast<DictionaryValue
*>(result
.get()),
381 // http://crbug.com/108279
382 #define ValidateThemeUTF8 DISABLED_ValidateThemeUTF8
384 TEST(ExtensionFileUtil
, ValidateThemeUTF8
) {
386 ASSERT_TRUE(temp
.CreateUniqueTempDir());
388 // "aeo" with accents. Use http://0xcc.net/jsescape/ to decode them.
389 std::string non_ascii_file
= "\xC3\xA0\xC3\xA8\xC3\xB2.png";
390 FilePath non_ascii_path
= temp
.path().Append(FilePath::FromUTF8Unsafe(
392 file_util::WriteFile(non_ascii_path
, "", 0);
394 std::string kManifest
=
396 "{ \"name\": \"Test\", \"version\": \"1.0\", "
397 " \"theme\": { \"images\": { \"theme_frame\": \"%s\" } }"
398 "}", non_ascii_file
.c_str());
400 scoped_refptr
<Extension
> extension
= LoadExtensionManifest(
401 kManifest
, temp
.path(), Extension::LOAD
, 0, &error
);
402 ASSERT_TRUE(extension
.get()) << error
;
404 Extension::InstallWarningVector warnings
;
405 EXPECT_TRUE(extension_file_util::ValidateExtension(extension
,
406 &error
, &warnings
)) <<
408 EXPECT_EQ(0U, warnings
.size());
412 // This test hangs on Windows sometimes. http://crbug.com/110279
413 #define MAYBE_BackgroundScriptsMustExist DISABLED_BackgroundScriptsMustExist
415 #define MAYBE_BackgroundScriptsMustExist BackgroundScriptsMustExist
417 TEST(ExtensionFileUtil
, MAYBE_BackgroundScriptsMustExist
) {
419 ASSERT_TRUE(temp
.CreateUniqueTempDir());
421 scoped_ptr
<DictionaryValue
> value(new DictionaryValue());
422 value
->SetString("name", "test");
423 value
->SetString("version", "1");
424 value
->SetInteger("manifest_version", 1);
426 ListValue
* scripts
= new ListValue();
427 scripts
->Append(Value::CreateStringValue("foo.js"));
428 value
->Set("background.scripts", scripts
);
431 Extension::InstallWarningVector warnings
;
432 scoped_refptr
<Extension
> extension
= LoadExtensionManifest(
433 value
.get(), temp
.path(), Extension::LOAD
, 0, &error
);
434 ASSERT_TRUE(extension
.get()) << error
;
436 EXPECT_FALSE(extension_file_util::ValidateExtension(extension
,
438 EXPECT_EQ(l10n_util::GetStringFUTF8(
439 IDS_EXTENSION_LOAD_BACKGROUND_SCRIPT_FAILED
, ASCIIToUTF16("foo.js")),
441 EXPECT_EQ(0U, warnings
.size());
444 scripts
->Append(Value::CreateStringValue("http://google.com/foo.js"));
446 extension
= LoadExtensionManifest(value
.get(), temp
.path(), Extension::LOAD
,
448 ASSERT_TRUE(extension
.get()) << error
;
451 EXPECT_FALSE(extension_file_util::ValidateExtension(extension
,
453 EXPECT_EQ(l10n_util::GetStringFUTF8(
454 IDS_EXTENSION_LOAD_BACKGROUND_SCRIPT_FAILED
,
455 ASCIIToUTF16("http://google.com/foo.js")),
457 EXPECT_EQ(0U, warnings
.size());
460 // Private key, generated by Chrome specifically for this test, and
461 // never used elsewhere.
462 const char private_key
[] =
463 "-----BEGIN PRIVATE KEY-----\n"
464 "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKt02SR0FYaYy6fpW\n"
465 "MAA+kU1BgK3d+OmmWfdr+JATIjhRkyeSF4lTd/71JQsyKqPzYkQPi3EeROWM+goTv\n"
466 "EhJqq07q63BolpsFmlV+S4ny+sBA2B4aWwRYXlBWikdrQSA0mJMzvEHc6nKzBgXik\n"
467 "QSVbyyBNAsxlDB9WaCxRVOpK3AgMBAAECgYBGvSPlrVtAOAQ2V8j9FqorKZA8SLPX\n"
468 "IeJC/yzU3RB2nPMjI17aMOvrUHxJUhzMeh4jwabVvSzzDtKFozPGupW3xaI8sQdi2\n"
469 "WWMTQIk/Q9HHDWoQ9qA6SwX2qWCc5SyjCKqVp78ye+000kqTJYjBsDgXeAlzKcx2B\n"
470 "4GAAeWonDdkQJBANNb8wrqNWFn7DqyQTfELzcRTRnqQ/r1pdeJo6obzbnwGnlqe3t\n"
471 "KhLjtJNIGrQg5iC0OVLWFuvPJs0t3z62A1ckCQQDPq2JZuwTwu5Pl4DJ0r9O1FdqN\n"
472 "JgqPZyMptokCDQ3khLLGakIu+TqB9YtrzI69rJMSG2Egb+6McaDX+dh3XmR/AkB9t\n"
473 "xJf6qDnmA2td/tMtTc0NOk8Qdg/fD8xbZ/YfYMnVoYYs9pQoilBaWRePDRNURMLYZ\n"
474 "vHAI0Llmw7tj7jv17pAkEAz44uXRpjRKtllUIvi5pUENAHwDz+HvdpGH68jpU3hmb\n"
475 "uOwrmnQYxaMReFV68Z2w9DcLZn07f7/R9Wn72z89CxwJAFsDoNaDes4h48bX7plct\n"
476 "s9ACjmTwcCigZjN2K7AGv7ntCLF3DnV5dK0dTHNaAdD3SbY3jl29Rk2CwiURSX6Ee\n"
478 "-----END PRIVATE KEY-----\n";
480 TEST(ExtensionFileUtil
, FindPrivateKeyFiles
) {
482 ASSERT_TRUE(temp
.CreateUniqueTempDir());
484 FilePath src_path
= temp
.path().AppendASCII("some_dir");
485 ASSERT_TRUE(file_util::CreateDirectory(src_path
));
487 ASSERT_TRUE(file_util::WriteFile(src_path
.AppendASCII("a_key.pem"),
488 private_key
, arraysize(private_key
)));
489 ASSERT_TRUE(file_util::WriteFile(src_path
.AppendASCII("second_key.pem"),
490 private_key
, arraysize(private_key
)));
491 // Shouldn't find a key with a different extension.
492 ASSERT_TRUE(file_util::WriteFile(src_path
.AppendASCII("key.diff_ext"),
493 private_key
, arraysize(private_key
)));
494 // Shouldn't find a key that isn't parsable.
495 ASSERT_TRUE(file_util::WriteFile(src_path
.AppendASCII("unparsable_key.pem"),
496 private_key
, arraysize(private_key
) - 30));
497 std::vector
<FilePath
> private_keys
=
498 extension_file_util::FindPrivateKeyFiles(temp
.path());
499 EXPECT_EQ(2U, private_keys
.size());
500 EXPECT_THAT(private_keys
,
501 testing::Contains(src_path
.AppendASCII("a_key.pem")));
502 EXPECT_THAT(private_keys
,
503 testing::Contains(src_path
.AppendASCII("second_key.pem")));
506 TEST(ExtensionFileUtil
, WarnOnPrivateKey
) {
508 ASSERT_TRUE(temp
.CreateUniqueTempDir());
510 FilePath ext_path
= temp
.path().AppendASCII("ext_root");
511 ASSERT_TRUE(file_util::CreateDirectory(ext_path
));
513 const char manifest
[] =
515 " \"name\": \"Test Extension\",\n"
516 " \"version\": \"1.0\",\n"
517 " \"manifest_version\": 2,\n"
518 " \"description\": \"The first extension that I made.\"\n"
520 ASSERT_TRUE(file_util::WriteFile(ext_path
.AppendASCII("manifest.json"),
521 manifest
, strlen(manifest
)));
522 ASSERT_TRUE(file_util::WriteFile(ext_path
.AppendASCII("a_key.pem"),
523 private_key
, strlen(private_key
)));
526 scoped_refptr
<Extension
> extension(extension_file_util::LoadExtension(
527 ext_path
, "the_id", Extension::EXTERNAL_PREF
,
528 Extension::NO_FLAGS
, &error
));
529 ASSERT_TRUE(extension
.get()) << error
;
530 ASSERT_EQ(1u, extension
->install_warnings().size());
532 extension
->install_warnings(),
533 testing::ElementsAre(
535 &Extension::InstallWarning::message
,
536 testing::ContainsRegex(
537 "extension includes the key file.*ext_root.a_key.pem"))));
539 // Turn the warning into an error with ERROR_ON_PRIVATE_KEY.
540 extension
= extension_file_util::LoadExtension(
541 ext_path
, "the_id", Extension::EXTERNAL_PREF
,
542 Extension::ERROR_ON_PRIVATE_KEY
, &error
);
543 EXPECT_FALSE(extension
.get());
545 testing::ContainsRegex(
546 "extension includes the key file.*ext_root.a_key.pem"));
549 TEST(ExtensionFileUtil
, CheckZeroLengthImageFile
) {
550 FilePath install_dir
;
551 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &install_dir
));
553 // Try to install an extension with a zero-length icon file.
554 FilePath ext_dir
= install_dir
.AppendASCII("extensions")
556 .AppendASCII("Extensions")
557 .AppendASCII("ffffffffffffffffffffffffffffffff");
560 scoped_refptr
<Extension
> extension(extension_file_util::LoadExtension(
561 ext_dir
, Extension::LOAD
, Extension::NO_FLAGS
, &error
));
562 ASSERT_TRUE(extension
== NULL
);
563 ASSERT_STREQ("Could not load extension icon 'icon.png'.",
566 // Try to install an extension with a zero-length browser action icon file.
567 ext_dir
= install_dir
.AppendASCII("extensions")
569 .AppendASCII("Extensions")
570 .AppendASCII("gggggggggggggggggggggggggggggggg");
572 scoped_refptr
<Extension
> extension2(extension_file_util::LoadExtension(
573 ext_dir
, Extension::LOAD
, Extension::NO_FLAGS
, &error
));
574 ASSERT_TRUE(extension2
== NULL
);
575 ASSERT_STREQ("Could not load icon 'icon.png' for browser action.",
578 // Try to install an extension with a zero-length page action icon file.
579 ext_dir
= install_dir
.AppendASCII("extensions")
581 .AppendASCII("Extensions")
582 .AppendASCII("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
584 scoped_refptr
<Extension
> extension3(extension_file_util::LoadExtension(
585 ext_dir
, Extension::LOAD
, Extension::NO_FLAGS
, &error
));
586 ASSERT_TRUE(extension3
== NULL
);
587 ASSERT_STREQ("Could not load icon 'icon.png' for page action.",
591 // TODO(aa): More tests as motivation allows. Maybe steal some from
592 // ExtensionService? Many of them could probably be tested here without the
593 // MessageLoop shenanigans.