| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extensions_service_unittest.h" | 5 #include "chrome/browser/extensions/extensions_service_unittest.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
| 13 #include "base/json/json_reader.h" | 13 #include "base/json/json_reader.h" |
| 14 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
| 15 #include "base/path_service.h" | 15 #include "base/path_service.h" |
| 16 #include "base/scoped_ptr.h" | 16 #include "base/scoped_ptr.h" |
| 17 #include "base/string16.h" | 17 #include "base/string16.h" |
| 18 #include "base/string_number_conversions.h" | 18 #include "base/string_number_conversions.h" |
| 19 #include "base/string_util.h" | 19 #include "base/string_util.h" |
| 20 #include "base/task.h" | 20 #include "base/task.h" |
| 21 #include "base/utf_string_conversions.h" | 21 #include "base/utf_string_conversions.h" |
| 22 #include "base/version.h" | 22 #include "base/version.h" |
| 23 #include "chrome/browser/chrome_thread.h" | 23 #include "chrome/browser/chrome_thread.h" |
| 24 #include "chrome/browser/extensions/crx_installer.h" | 24 #include "chrome/browser/extensions/crx_installer.h" |
| 25 #include "chrome/browser/extensions/extension_creator.h" | 25 #include "chrome/browser/extensions/extension_creator.h" |
| 26 #include "chrome/browser/extensions/extension_error_reporter.h" | 26 #include "chrome/browser/extensions/extension_error_reporter.h" |
| 27 #include "chrome/browser/extensions/extensions_service.h" | 27 #include "chrome/browser/extensions/extensions_service.h" |
| 28 #include "chrome/browser/extensions/external_extension_provider.h" | 28 #include "chrome/browser/extensions/external_extension_provider.h" |
| 29 #include "chrome/browser/extensions/external_pref_extension_provider.h" | 29 #include "chrome/browser/extensions/external_pref_extension_provider.h" |
| 30 #include "chrome/browser/extensions/pack_extension_job.cc" |
| 30 #include "chrome/browser/pref_value_store.h" | 31 #include "chrome/browser/pref_value_store.h" |
| 31 #include "chrome/common/extensions/extension.h" | 32 #include "chrome/common/extensions/extension.h" |
| 32 #include "chrome/common/extensions/extension_constants.h" | 33 #include "chrome/common/extensions/extension_constants.h" |
| 33 #include "chrome/common/extensions/extension_resource.h" | 34 #include "chrome/common/extensions/extension_resource.h" |
| 34 #include "chrome/common/extensions/url_pattern.h" | 35 #include "chrome/common/extensions/url_pattern.h" |
| 35 #include "chrome/common/chrome_paths.h" | 36 #include "chrome/common/chrome_paths.h" |
| 36 #include "chrome/common/chrome_switches.h" | 37 #include "chrome/common/chrome_switches.h" |
| 37 #include "chrome/common/json_value_serializer.h" | 38 #include "chrome/common/json_value_serializer.h" |
| 38 #include "chrome/common/notification_registrar.h" | 39 #include "chrome/common/notification_registrar.h" |
| 39 #include "chrome/common/notification_service.h" | 40 #include "chrome/common/notification_service.h" |
| (...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 | 594 |
| 594 protected: | 595 protected: |
| 595 ExtensionList loaded_; | 596 ExtensionList loaded_; |
| 596 std::string unloaded_id_; | 597 std::string unloaded_id_; |
| 597 Extension* installed_; | 598 Extension* installed_; |
| 598 | 599 |
| 599 private: | 600 private: |
| 600 NotificationRegistrar registrar_; | 601 NotificationRegistrar registrar_; |
| 601 }; | 602 }; |
| 602 | 603 |
| 603 FilePath::StringType NormalizeSeperators(FilePath::StringType path) { | 604 FilePath NormalizeSeparators(const FilePath& path) { |
| 604 #if defined(FILE_PATH_USES_WIN_SEPARATORS) | 605 #if defined(FILE_PATH_USES_WIN_SEPARATORS) |
| 605 FilePath::StringType ret_val; | 606 return path.NormalizeWindowsPathSeparators(); |
| 606 for (size_t i = 0; i < path.length(); i++) { | 607 #else |
| 607 if (FilePath::IsSeparator(path[i])) | 608 return path; |
| 608 path[i] = FilePath::kSeparators[0]; | |
| 609 } | |
| 610 #endif // FILE_PATH_USES_WIN_SEPARATORS | 609 #endif // FILE_PATH_USES_WIN_SEPARATORS |
| 611 return path; | |
| 612 } | 610 } |
| 611 |
| 612 // Receives notifications from a PackExtensionJob, indicating either that |
| 613 // packing succeeded or that there was some error. |
| 614 class PackExtensionTestClient : public PackExtensionJob::Client { |
| 615 public: |
| 616 PackExtensionTestClient(const FilePath& expected_crx_path, |
| 617 const FilePath& expected_private_key_path); |
| 618 virtual void OnPackSuccess(const FilePath& crx_path, |
| 619 const FilePath& private_key_path); |
| 620 virtual void OnPackFailure(const std::string& error_message); |
| 621 |
| 622 private: |
| 623 const FilePath expected_crx_path_; |
| 624 const FilePath expected_private_key_path_; |
| 625 DISALLOW_COPY_AND_ASSIGN(PackExtensionTestClient); |
| 626 }; |
| 627 |
| 628 PackExtensionTestClient::PackExtensionTestClient( |
| 629 const FilePath& expected_crx_path, |
| 630 const FilePath& expected_private_key_path) |
| 631 : expected_crx_path_(expected_crx_path), |
| 632 expected_private_key_path_(expected_private_key_path) {} |
| 633 |
| 634 // If packing succeeded, we make sure that the package names match our |
| 635 // expectations. |
| 636 void PackExtensionTestClient::OnPackSuccess(const FilePath& crx_path, |
| 637 const FilePath& private_key_path) { |
| 638 // We got the notification and processed it; we don't expect any further tasks |
| 639 // to be posted to the current thread, so we should stop blocking and continue |
| 640 // on with the rest of the test. |
| 641 // This call to |Quit()| matches the call to |Run()| in the |
| 642 // |PackPunctuatedExtension| test. |
| 643 MessageLoop::current()->Quit(); |
| 644 EXPECT_EQ(expected_crx_path_.value(), crx_path.value()); |
| 645 EXPECT_EQ(expected_private_key_path_.value(), private_key_path.value()); |
| 646 ASSERT_TRUE(file_util::PathExists(private_key_path)); |
| 647 } |
| 648 |
| 649 // The tests are designed so that we never expect to see a packing error. |
| 650 void PackExtensionTestClient::OnPackFailure(const std::string& error_message) { |
| 651 FAIL() << "Packing should not fail."; |
| 652 } |
| 653 |
| 613 // Test loading good extensions from the profile directory. | 654 // Test loading good extensions from the profile directory. |
| 614 TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) { | 655 TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) { |
| 615 // Initialize the test dir with a good Preferences/extensions. | 656 // Initialize the test dir with a good Preferences/extensions. |
| 616 FilePath source_install_dir; | 657 FilePath source_install_dir; |
| 617 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir)); | 658 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_install_dir)); |
| 618 source_install_dir = source_install_dir | 659 source_install_dir = source_install_dir |
| 619 .AppendASCII("extensions") | 660 .AppendASCII("extensions") |
| 620 .AppendASCII("good") | 661 .AppendASCII("good") |
| 621 .AppendASCII("Extensions"); | 662 .AppendASCII("Extensions"); |
| 622 FilePath pref_path = source_install_dir | 663 FilePath pref_path = source_install_dir |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 929 // Try packing with an invalid manifest. | 970 // Try packing with an invalid manifest. |
| 930 std::string invalid_manifest_content = "I am not a manifest."; | 971 std::string invalid_manifest_content = "I am not a manifest."; |
| 931 ASSERT_TRUE(file_util::WriteFile( | 972 ASSERT_TRUE(file_util::WriteFile( |
| 932 temp_dir2.path().Append(Extension::kManifestFilename), | 973 temp_dir2.path().Append(Extension::kManifestFilename), |
| 933 invalid_manifest_content.c_str(), invalid_manifest_content.size())); | 974 invalid_manifest_content.c_str(), invalid_manifest_content.size())); |
| 934 creator.reset(new ExtensionCreator()); | 975 creator.reset(new ExtensionCreator()); |
| 935 ASSERT_FALSE(creator->Run(temp_dir2.path(), crx_path, privkey_path, | 976 ASSERT_FALSE(creator->Run(temp_dir2.path(), crx_path, privkey_path, |
| 936 FilePath())); | 977 FilePath())); |
| 937 } | 978 } |
| 938 | 979 |
| 980 // Test Packaging and installing an extension whose name contains punctuation. |
| 981 TEST_F(ExtensionsServiceTest, PackPunctuatedExtension) { |
| 982 InitializeEmptyExtensionsService(); |
| 983 FilePath extensions_path; |
| 984 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); |
| 985 extensions_path = extensions_path.AppendASCII("extensions"); |
| 986 FilePath input_directory = extensions_path |
| 987 .AppendASCII("good") |
| 988 .AppendASCII("Extensions") |
| 989 .AppendASCII(good0) |
| 990 .AppendASCII("1.0.0.0"); |
| 991 |
| 992 ScopedTempDir temp_dir; |
| 993 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 994 |
| 995 // Extension names containing punctuation, and the expected names for the |
| 996 // packed extensions. |
| 997 const FilePath punctuated_names[] = { |
| 998 FilePath(FilePath::StringType( |
| 999 FILE_PATH_LITERAL("this.extensions.name.has.periods"))), |
| 1000 FilePath(FilePath::StringType( |
| 1001 FILE_PATH_LITERAL(".thisextensionsnamestartswithaperiod"))), |
| 1002 NormalizeSeparators(FilePath(FilePath::StringType( |
| 1003 FILE_PATH_LITERAL("thisextensionhasaslashinitsname/")))), |
| 1004 }; |
| 1005 const FilePath expected_crx_names[] = { |
| 1006 FilePath(FilePath::StringType( |
| 1007 FILE_PATH_LITERAL("this.extensions.name.has.periods.crx"))), |
| 1008 FilePath(FilePath::StringType( |
| 1009 FILE_PATH_LITERAL(".thisextensionsnamestartswithaperiod.crx"))), |
| 1010 FilePath(FilePath::StringType( |
| 1011 FILE_PATH_LITERAL("thisextensionhasaslashinitsname.crx"))), |
| 1012 }; |
| 1013 const FilePath expected_private_key_names[] = { |
| 1014 FilePath(FilePath::StringType( |
| 1015 FILE_PATH_LITERAL("this.extensions.name.has.periods.pem"))), |
| 1016 FilePath(FilePath::StringType( |
| 1017 FILE_PATH_LITERAL(".thisextensionsnamestartswithaperiod.pem"))), |
| 1018 FilePath(FilePath::StringType( |
| 1019 FILE_PATH_LITERAL("thisextensionhasaslashinitsname.pem"))), |
| 1020 }; |
| 1021 |
| 1022 for (size_t i = 0; i < arraysize(punctuated_names); ++i) { |
| 1023 SCOPED_TRACE(punctuated_names[i].value().c_str()); |
| 1024 FilePath output_dir = temp_dir.path().Append(punctuated_names[i]); |
| 1025 |
| 1026 // Copy the extension into the output directory, as PackExtensionJob doesn't |
| 1027 // let us choose where to output the packed extension. |
| 1028 ASSERT_TRUE(file_util::CopyDirectory(input_directory, output_dir, true)); |
| 1029 |
| 1030 FilePath expected_crx_path = temp_dir.path().Append(expected_crx_names[i]); |
| 1031 FilePath expected_private_key_path = |
| 1032 temp_dir.path().Append(expected_private_key_names[i]); |
| 1033 PackExtensionTestClient pack_client(expected_crx_path, |
| 1034 expected_private_key_path); |
| 1035 scoped_refptr<PackExtensionJob> packer(new PackExtensionJob(&pack_client, |
| 1036 output_dir, |
| 1037 FilePath())); |
| 1038 packer->Start(); |
| 1039 |
| 1040 // The packer will post a notification task to the current thread's message |
| 1041 // loop when it is finished. We manually run the loop here so that we |
| 1042 // block and catch the notification; otherwise, the process would exit. |
| 1043 // This call to |Run()| is matched by a call to |Quit()| in the |
| 1044 // |PackExtensionTestClient|'s notification handling code. |
| 1045 MessageLoop::current()->Run(); |
| 1046 |
| 1047 if (HasFatalFailure()) |
| 1048 return; |
| 1049 |
| 1050 InstallExtension(expected_crx_path, true); |
| 1051 } |
| 1052 } |
| 1053 |
| 939 // Test Packaging and installing an extension using an openssl generated key. | 1054 // Test Packaging and installing an extension using an openssl generated key. |
| 940 // The openssl is generated with the following: | 1055 // The openssl is generated with the following: |
| 941 // > openssl genrsa -out privkey.pem 1024 | 1056 // > openssl genrsa -out privkey.pem 1024 |
| 942 // > openssl pkcs8 -topk8 -nocrypt -in privkey.pem -out privkey_asn1.pem | 1057 // > openssl pkcs8 -topk8 -nocrypt -in privkey.pem -out privkey_asn1.pem |
| 943 // The privkey.pem is a PrivateKey, and the pcks8 -topk8 creates a | 1058 // The privkey.pem is a PrivateKey, and the pcks8 -topk8 creates a |
| 944 // PrivateKeyInfo ASN.1 structure, we our RSAPrivateKey expects. | 1059 // PrivateKeyInfo ASN.1 structure, we our RSAPrivateKey expects. |
| 945 TEST_F(ExtensionsServiceTest, PackExtensionOpenSSLKey) { | 1060 TEST_F(ExtensionsServiceTest, PackExtensionOpenSSLKey) { |
| 946 InitializeEmptyExtensionsService(); | 1061 InitializeEmptyExtensionsService(); |
| 947 FilePath extensions_path; | 1062 FilePath extensions_path; |
| 948 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); | 1063 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); |
| (...skipping 1172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2121 // Component extensions shouldn't get recourded in the prefs. | 2236 // Component extensions shouldn't get recourded in the prefs. |
| 2122 ValidatePrefKeyCount(0); | 2237 ValidatePrefKeyCount(0); |
| 2123 | 2238 |
| 2124 // Reload all extensions, and make sure it comes back. | 2239 // Reload all extensions, and make sure it comes back. |
| 2125 std::string extension_id = service_->extensions()->at(0)->id(); | 2240 std::string extension_id = service_->extensions()->at(0)->id(); |
| 2126 loaded_.clear(); | 2241 loaded_.clear(); |
| 2127 service_->ReloadExtensions(); | 2242 service_->ReloadExtensions(); |
| 2128 ASSERT_EQ(1u, service_->extensions()->size()); | 2243 ASSERT_EQ(1u, service_->extensions()->size()); |
| 2129 EXPECT_EQ(extension_id, service_->extensions()->at(0)->id()); | 2244 EXPECT_EQ(extension_id, service_->extensions()->at(0)->id()); |
| 2130 } | 2245 } |
| OLD | NEW |