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