OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/common/extensions/extension_file_util.h" | 5 #include "chrome/common/extensions/extension_file_util.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 #include "net/base/escape.h" | 29 #include "net/base/escape.h" |
30 #include "net/base/file_stream.h" | 30 #include "net/base/file_stream.h" |
31 #include "ui/base/l10n/l10n_util.h" | 31 #include "ui/base/l10n/l10n_util.h" |
32 | 32 |
33 using extensions::Extension; | 33 using extensions::Extension; |
34 | 34 |
35 namespace errors = extension_manifest_errors; | 35 namespace errors = extension_manifest_errors; |
36 | 36 |
37 namespace { | 37 namespace { |
38 | 38 |
| 39 const FilePath::CharType kTempDirectoryName[] = FILE_PATH_LITERAL("Temp"); |
| 40 |
39 bool ValidateExtensionIconSet(const ExtensionIconSet& icon_set, | 41 bool ValidateExtensionIconSet(const ExtensionIconSet& icon_set, |
40 const Extension* extension, | 42 const Extension* extension, |
41 int error_message_id, | 43 int error_message_id, |
42 std::string* error) { | 44 std::string* error) { |
43 for (ExtensionIconSet::IconMap::const_iterator iter = icon_set.map().begin(); | 45 for (ExtensionIconSet::IconMap::const_iterator iter = icon_set.map().begin(); |
44 iter != icon_set.map().end(); | 46 iter != icon_set.map().end(); |
45 ++iter) { | 47 ++iter) { |
46 const FilePath path = extension->GetResource(iter->second).GetFilePath(); | 48 const FilePath path = extension->GetResource(iter->second).GetFilePath(); |
47 if (!extension_file_util::ValidateFilePath(path)) { | 49 if (!extension_file_util::ValidateFilePath(path)) { |
48 *error = l10n_util::GetStringFUTF8(error_message_id, | 50 *error = l10n_util::GetStringFUTF8(error_message_id, |
(...skipping 10 matching lines...) Expand all Loading... |
59 | 61 |
60 // Validates locale info. Doesn't check if messages.json files are valid. | 62 // Validates locale info. Doesn't check if messages.json files are valid. |
61 static bool ValidateLocaleInfo(const Extension& extension, | 63 static bool ValidateLocaleInfo(const Extension& extension, |
62 std::string* error); | 64 std::string* error); |
63 | 65 |
64 // Returns false and sets the error if script file can't be loaded, | 66 // Returns false and sets the error if script file can't be loaded, |
65 // or if it's not UTF-8 encoded. | 67 // or if it's not UTF-8 encoded. |
66 static bool IsScriptValid(const FilePath& path, const FilePath& relative_path, | 68 static bool IsScriptValid(const FilePath& path, const FilePath& relative_path, |
67 int message_id, std::string* error); | 69 int message_id, std::string* error); |
68 | 70 |
69 const char kInstallDirectoryName[] = "Extensions"; | |
70 | |
71 FilePath InstallExtension(const FilePath& unpacked_source_dir, | 71 FilePath InstallExtension(const FilePath& unpacked_source_dir, |
72 const std::string& id, | 72 const std::string& id, |
73 const std::string& version, | 73 const std::string& version, |
74 const FilePath& all_extensions_dir) { | 74 const FilePath& extensions_dir) { |
75 FilePath extension_dir = all_extensions_dir.AppendASCII(id); | 75 FilePath extension_dir = extensions_dir.AppendASCII(id); |
76 FilePath version_dir; | 76 FilePath version_dir; |
77 | 77 |
78 // Create the extension directory if it doesn't exist already. | 78 // Create the extension directory if it doesn't exist already. |
79 if (!file_util::PathExists(extension_dir)) { | 79 if (!file_util::PathExists(extension_dir)) { |
80 if (!file_util::CreateDirectory(extension_dir)) | 80 if (!file_util::CreateDirectory(extension_dir)) |
81 return FilePath(); | 81 return FilePath(); |
82 } | 82 } |
83 | 83 |
84 FilePath profile_temp_dir = GetUserDataTempDir(); | 84 // Get a temp directory on the same file system as the profile. |
| 85 FilePath install_temp_dir = GetInstallTempDir(extensions_dir); |
85 ScopedTempDir extension_temp_dir; | 86 ScopedTempDir extension_temp_dir; |
86 if (profile_temp_dir.empty() || | 87 if (install_temp_dir.empty() || |
87 !extension_temp_dir.CreateUniqueTempDirUnderPath(profile_temp_dir)) { | 88 !extension_temp_dir.CreateUniqueTempDirUnderPath(install_temp_dir)) { |
88 LOG(ERROR) << "Creating of temp dir under in the profile failed."; | 89 LOG(ERROR) << "Creating of temp dir under in the profile failed."; |
89 return FilePath(); | 90 return FilePath(); |
90 } | 91 } |
91 FilePath crx_temp_source = | 92 FilePath crx_temp_source = |
92 extension_temp_dir.path().Append(unpacked_source_dir.BaseName()); | 93 extension_temp_dir.path().Append(unpacked_source_dir.BaseName()); |
93 if (!file_util::Move(unpacked_source_dir, crx_temp_source)) { | 94 if (!file_util::Move(unpacked_source_dir, crx_temp_source)) { |
94 LOG(ERROR) << "Moving extension from : " << unpacked_source_dir.value() | 95 LOG(ERROR) << "Moving extension from : " << unpacked_source_dir.value() |
95 << " to : " << crx_temp_source.value() << " failed."; | 96 << " to : " << crx_temp_source.value() << " failed."; |
96 return FilePath(); | 97 return FilePath(); |
97 } | 98 } |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 DVLOG(1) << "Garbage collecting extensions..."; | 430 DVLOG(1) << "Garbage collecting extensions..."; |
430 file_util::FileEnumerator enumerator(install_directory, | 431 file_util::FileEnumerator enumerator(install_directory, |
431 false, // Not recursive. | 432 false, // Not recursive. |
432 file_util::FileEnumerator::DIRECTORIES); | 433 file_util::FileEnumerator::DIRECTORIES); |
433 FilePath extension_path; | 434 FilePath extension_path; |
434 for (extension_path = enumerator.Next(); !extension_path.value().empty(); | 435 for (extension_path = enumerator.Next(); !extension_path.value().empty(); |
435 extension_path = enumerator.Next()) { | 436 extension_path = enumerator.Next()) { |
436 std::string extension_id; | 437 std::string extension_id; |
437 | 438 |
438 FilePath basename = extension_path.BaseName(); | 439 FilePath basename = extension_path.BaseName(); |
| 440 // Clean up temporary files left if Chrome crashed or quit in the middle |
| 441 // of an extension install. |
| 442 if (basename.value() == kTempDirectoryName) { |
| 443 file_util::Delete(extension_path, true); // Recursive |
| 444 continue; |
| 445 } |
| 446 |
| 447 // Parse directory name as a potential extension ID. |
439 if (IsStringASCII(basename.value())) { | 448 if (IsStringASCII(basename.value())) { |
440 extension_id = UTF16ToASCII(basename.LossyDisplayName()); | 449 extension_id = UTF16ToASCII(basename.LossyDisplayName()); |
441 if (!Extension::IdIsValid(extension_id)) | 450 if (!Extension::IdIsValid(extension_id)) |
442 extension_id.clear(); | 451 extension_id.clear(); |
443 } | 452 } |
444 | 453 |
445 // Delete directories that aren't valid IDs. | 454 // Delete directories that aren't valid IDs. |
446 if (extension_id.empty()) { | 455 if (extension_id.empty()) { |
447 DLOG(WARNING) << "Invalid extension ID encountered in extensions " | 456 DLOG(WARNING) << "Invalid extension ID encountered in extensions " |
448 "directory: " << basename.value(); | 457 "directory: " << basename.value(); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 | 710 |
702 FilePath path = root.AppendASCII(host).Append(relative_path); | 711 FilePath path = root.AppendASCII(host).Append(relative_path); |
703 if (!file_util::PathExists(path) || | 712 if (!file_util::PathExists(path) || |
704 !file_util::AbsolutePath(&path) || | 713 !file_util::AbsolutePath(&path) || |
705 !root.IsParent(path)) { | 714 !root.IsParent(path)) { |
706 return FilePath(); | 715 return FilePath(); |
707 } | 716 } |
708 return path; | 717 return path; |
709 } | 718 } |
710 | 719 |
711 FilePath GetUserDataTempDir() { | 720 FilePath GetInstallTempDir(const FilePath& extensions_dir) { |
712 // We do file IO in this function, but only when the current profile's | 721 // We do file IO in this function, but only when the current profile's |
713 // Temp directory has never been used before, or in a rare error case. | 722 // Temp directory has never been used before, or in a rare error case. |
714 // Developers are not likely to see these situations often, so do an | 723 // Developers are not likely to see these situations often, so do an |
715 // explicit thread check. | 724 // explicit thread check. |
716 base::ThreadRestrictions::AssertIOAllowed(); | 725 base::ThreadRestrictions::AssertIOAllowed(); |
717 | 726 |
718 // The following enum used to be sent as a histogram to diagnose issues | 727 // Create the temp directory as a sub-directory of the Extensions directory. |
719 // accessing the temp path (crbug/70056). The histogram is gone, but | 728 // This guarantees it is on the same file system as the extension's eventual |
720 // the enum makes it clear exactly why the temp directory can not be | 729 // install target. |
721 // accessed, which may aid debugging in the future. | 730 FilePath temp_path = extensions_dir.Append(kTempDirectoryName); |
722 enum DirectoryCreationResult { | 731 if (file_util::PathExists(temp_path)) { |
723 SUCCESS = 0, | |
724 | |
725 CANT_GET_PARENT_PATH, | |
726 CANT_GET_UDT_PATH, | |
727 NOT_A_DIRECTORY, | |
728 CANT_CREATE_DIR, | |
729 CANT_WRITE_TO_PATH, | |
730 | |
731 UNSET, | |
732 NUM_DIRECTORY_CREATION_RESULTS | |
733 }; | |
734 | |
735 // All paths should set |result|. | |
736 DirectoryCreationResult result = UNSET; | |
737 | |
738 FilePath temp_path; | |
739 if (!PathService::Get(chrome::DIR_USER_DATA_TEMP, &temp_path)) { | |
740 FilePath parent_path; | |
741 if (!PathService::Get(chrome::DIR_USER_DATA, &parent_path)) | |
742 result = CANT_GET_PARENT_PATH; | |
743 else | |
744 result = CANT_GET_UDT_PATH; | |
745 | |
746 } else if (file_util::PathExists(temp_path)) { | |
747 | |
748 // Path exists. Check that it is a directory we can write to. | |
749 if (!file_util::DirectoryExists(temp_path)) { | 732 if (!file_util::DirectoryExists(temp_path)) { |
750 result = NOT_A_DIRECTORY; | 733 DLOG(WARNING) << "Not a directory: " << temp_path.value(); |
751 | 734 return FilePath(); |
752 } else if (!file_util::PathIsWritable(temp_path)) { | |
753 result = CANT_WRITE_TO_PATH; | |
754 | |
755 } else { | |
756 // Temp is a writable directory. | |
757 result = SUCCESS; | |
758 } | 735 } |
759 | 736 if (!file_util::PathIsWritable(temp_path)) { |
760 } else if (!file_util::CreateDirectory(temp_path)) { | 737 DLOG(WARNING) << "Can't write to path: " << temp_path.value(); |
761 // Path doesn't exist, and we failed to create it. | 738 return FilePath(); |
762 result = CANT_CREATE_DIR; | 739 } |
763 | 740 // This is a directory we can write to. |
764 } else { | 741 return temp_path; |
765 // Successfully created the Temp directory. | |
766 result = SUCCESS; | |
767 } | 742 } |
768 | 743 |
769 if (result == SUCCESS) | 744 // Directory doesn't exist, so create it. |
770 return temp_path; | 745 if (!file_util::CreateDirectory(temp_path)) { |
771 | 746 DLOG(WARNING) << "Couldn't create directory: " << temp_path.value(); |
772 return FilePath(); | 747 return FilePath(); |
| 748 } |
| 749 return temp_path; |
773 } | 750 } |
774 | 751 |
775 void DeleteFile(const FilePath& path, bool recursive) { | 752 void DeleteFile(const FilePath& path, bool recursive) { |
776 file_util::Delete(path, recursive); | 753 file_util::Delete(path, recursive); |
777 } | 754 } |
778 | 755 |
779 } // namespace extension_file_util | 756 } // namespace extension_file_util |
OLD | NEW |