diff options
Diffstat (limited to 'chrome/browser/extensions/extension_file_util.cc')
-rw-r--r-- | chrome/browser/extensions/extension_file_util.cc | 174 |
1 files changed, 57 insertions, 117 deletions
diff --git a/chrome/browser/extensions/extension_file_util.cc b/chrome/browser/extensions/extension_file_util.cc index bf6cd9c..9c15da3 100644 --- a/chrome/browser/extensions/extension_file_util.cc +++ b/chrome/browser/extensions/extension_file_util.cc @@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/scoped_temp_dir.h" #include "base/string_util.h" +#include "chrome/browser/extensions/extension_prefs.h" #include "chrome/browser/extensions/extension_l10n_util.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_constants.h" @@ -17,6 +18,8 @@ namespace extension_file_util { const char kInstallDirectoryName[] = "Extensions"; +// TODO(mpcomplete): obsolete. remove after migration period. +// http://code.google.com/p/chromium/issues/detail?id=19733 const char kCurrentVersionFileName[] = "Current Version"; bool MoveDirSafely(const FilePath& source_dir, const FilePath& dest_dir) { @@ -37,76 +40,34 @@ bool MoveDirSafely(const FilePath& source_dir, const FilePath& dest_dir) { return true; } -bool SetCurrentVersion(const FilePath& dest_dir, const std::string& version, - std::string* error) { - // Write out the new CurrentVersion file. - // <profile>/Extension/<name>/CurrentVersion - FilePath current_version = dest_dir.AppendASCII(kCurrentVersionFileName); - FilePath current_version_old = - current_version.InsertBeforeExtension(FILE_PATH_LITERAL("_old")); - if (file_util::PathExists(current_version_old)) { - if (!file_util::Delete(current_version_old, false)) { - *error = "Couldn't remove CurrentVersion_old file."; - return false; - } - } - - if (file_util::PathExists(current_version)) { - if (!file_util::Move(current_version, current_version_old)) { - *error = "Couldn't move CurrentVersion file."; - return false; - } - } - net::FileStream stream; - int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE; - if (stream.Open(current_version, flags) != 0) - return false; - if (stream.Write(version.c_str(), version.size(), NULL) < 0) { - // Restore the old CurrentVersion. - if (file_util::PathExists(current_version_old)) { - if (!file_util::Move(current_version_old, current_version)) { - LOG(WARNING) << "couldn't restore " << current_version_old.value() << - " to " << current_version.value(); - - // TODO(erikkay): This is an ugly state to be in. Try harder? - } - } - *error = "Couldn't create CurrentVersion file."; - return false; - } - return true; -} - -bool ReadCurrentVersion(const FilePath& dir, std::string* version_string) { - FilePath current_version = dir.AppendASCII(kCurrentVersionFileName); - if (file_util::PathExists(current_version)) { - if (file_util::ReadFileToString(current_version, version_string)) { - TrimWhitespaceASCII(*version_string, TRIM_ALL, version_string); - return true; - } - } - return false; -} - Extension::InstallType CompareToInstalledVersion( - const FilePath& install_directory, const std::string& id, - const std::string& new_version_str, std::string *current_version_str) { - CHECK(current_version_str); - FilePath dir(install_directory.AppendASCII(id.c_str())); - if (!ReadCurrentVersion(dir, current_version_str)) + const FilePath& extensions_dir, + const std::string& extension_id, + const std::string& current_version_str, + const std::string& new_version_str, + FilePath* version_dir) { + FilePath dest_dir = extensions_dir.AppendASCII(extension_id); + FilePath current_version_dir = dest_dir.AppendASCII(current_version_str); + *version_dir = dest_dir.AppendASCII(new_version_str); + + if (current_version_str.empty()) return Extension::NEW_INSTALL; scoped_ptr<Version> current_version( - Version::GetVersionFromString(*current_version_str)); + Version::GetVersionFromString(current_version_str)); scoped_ptr<Version> new_version( Version::GetVersionFromString(new_version_str)); int comp = new_version->CompareTo(*current_version); if (comp > 0) return Extension::UPGRADE; - else if (comp == 0) - return Extension::REINSTALL; - else + if (comp < 0) return Extension::DOWNGRADE; + + // Same version. Treat corrupted existing installation as new install case. + if (!SanityCheckExtension(current_version_dir)) + return Extension::NEW_INSTALL; + + return Extension::REINSTALL; } bool SanityCheckExtension(const FilePath& dir) { @@ -118,44 +79,17 @@ bool SanityCheckExtension(const FilePath& dir) { } bool InstallExtension(const FilePath& src_dir, - const FilePath& extensions_dir, - const std::string& extension_id, - const std::string& extension_version, - FilePath* version_dir, - Extension::InstallType* install_type, + const FilePath& version_dir, std::string* error) { - FilePath dest_dir = extensions_dir.AppendASCII(extension_id); - *version_dir = dest_dir.AppendASCII(extension_version); - - std::string current_version; - *install_type = CompareToInstalledVersion( - extensions_dir, extension_id, extension_version, ¤t_version); - - // Do not allow downgrade. - if (*install_type == Extension::DOWNGRADE) - return true; - - if (*install_type == Extension::REINSTALL) { - if (!SanityCheckExtension(*version_dir)) { - // Treat corrupted existing installation as new install case. - *install_type = Extension::NEW_INSTALL; - } else { - return true; - } - } - // If anything fails after this, we want to delete the extension dir. ScopedTempDir scoped_version_dir; - scoped_version_dir.Set(*version_dir); + scoped_version_dir.Set(version_dir); - if (!MoveDirSafely(src_dir, *version_dir)) { + if (!MoveDirSafely(src_dir, version_dir)) { *error = "Could not move extension directory into profile."; return false; } - if (!SetCurrentVersion(dest_dir, extension_version, error)) - return false; - scoped_version_dir.Take(); return true; } @@ -184,13 +118,20 @@ Extension* LoadExtension(const FilePath& extension_path, bool require_key, require_key, error)) return NULL; + if (!ValidateExtension(extension.get(), error)) + return NULL; + + return extension.release(); +} + +bool ValidateExtension(Extension* extension, std::string* error) { // Validate icons exist. for (std::map<int, std::string>::const_iterator iter = extension->icons().begin(); iter != extension->icons().end(); ++iter) { if (!file_util::PathExists(extension->GetResourcePath(iter->second))) { *error = StringPrintf("Could not load extension icon '%s'.", iter->second.c_str()); - return NULL; + return false; } } @@ -207,14 +148,14 @@ Extension* LoadExtension(const FilePath& extension_path, bool require_key, *error = StringPrintf( "Could not load '%s' for theme.", WideToUTF8(image_path.ToWStringHack()).c_str()); - return NULL; + return false; } } } } // Themes cannot contain other extension types. - return extension.release(); + return true; } // Validate that claimed script resources actually exist. @@ -226,7 +167,7 @@ Extension* LoadExtension(const FilePath& extension_path, bool require_key, if (!file_util::PathExists(path)) { *error = StringPrintf("Could not load '%s' for content script.", WideToUTF8(path.ToWStringHack()).c_str()); - return NULL; + return false; } } @@ -235,7 +176,7 @@ Extension* LoadExtension(const FilePath& extension_path, bool require_key, if (!file_util::PathExists(path)) { *error = StringPrintf("Could not load '%s' for content script.", WideToUTF8(path.ToWStringHack()).c_str()); - return NULL; + return false; } } } @@ -246,7 +187,7 @@ Extension* LoadExtension(const FilePath& extension_path, bool require_key, if (!file_util::PathExists(plugin.path)) { *error = StringPrintf("Could not load '%s' for plugin.", WideToUTF8(plugin.path.ToWStringHack()).c_str()); - return NULL; + return false; } } @@ -257,7 +198,7 @@ Extension* LoadExtension(const FilePath& extension_path, bool require_key, if (!file_util::PathExists(blacklist.path)) { *error = StringPrintf("Could not load '%s' for privacy blacklist.", WideToUTF8(blacklist.path.ToWStringHack()).c_str()); - return NULL; + return false; } } @@ -272,33 +213,34 @@ Extension* LoadExtension(const FilePath& extension_path, bool require_key, if (!file_util::PathExists(extension->GetResourcePath(*iter))) { *error = StringPrintf("Could not load icon '%s' for page action.", iter->c_str()); - return NULL; + return false; } } } // Load locale information if available. - FilePath locale_path = extension_path.AppendASCII(Extension::kLocaleFolder); + FilePath locale_path = + extension->path().AppendASCII(Extension::kLocaleFolder); if (file_util::PathExists(locale_path)) { if (!extension_l10n_util::AddValidLocales(locale_path, - extension.get(), + extension, error)) { - return NULL; + return false; } - if (!extension_l10n_util::ValidateDefaultLocale(extension.get())) { + if (!extension_l10n_util::ValidateDefaultLocale(extension)) { *error = extension_manifest_errors::kLocalesNoDefaultLocaleSpecified; - return NULL; + return false; } } // Check children of extension root to see if any of them start with _ and is // not on the reserved list. - if (!CheckForIllegalFilenames(extension_path, error)) { - return NULL; + if (!CheckForIllegalFilenames(extension->path(), error)) { + return false; } - return extension.release(); + return true; } void UninstallExtension(const std::string& id, const FilePath& extensions_dir) { @@ -314,8 +256,7 @@ void UninstallExtension(const std::string& id, const FilePath& extensions_dir) { FilePath current_version_file = extension_root.AppendASCII( kCurrentVersionFileName); if (!file_util::PathExists(current_version_file)) { - LOG(WARNING) << "Extension " << id - << " does not have a Current Version file."; + // This is OK, since we're phasing out the current version file. } else { if (!file_util::Delete(current_version_file, false)) { LOG(WARNING) << "Could not delete Current Version file for extension " @@ -332,7 +273,8 @@ void UninstallExtension(const std::string& id, const FilePath& extensions_dir) { LOG(WARNING) << "Could not delete directory for extension " << id; } -void GarbageCollectExtensions(const FilePath& install_directory) { +void GarbageCollectExtensions(const FilePath& install_directory, + const std::set<std::string>& installed_ids) { // Nothing to clean up if it doesn't exist. if (!file_util::DirectoryExists(install_directory)) return; @@ -347,13 +289,11 @@ void GarbageCollectExtensions(const FilePath& install_directory) { std::string extension_id = WideToASCII( extension_path.BaseName().ToWStringHack()); - // If there is no Current Version file, just delete the directory and move - // on. This can legitimately happen when an uninstall does not complete, for - // example, when a plugin is in use at uninstall time. - FilePath current_version_path = extension_path.AppendASCII( - kCurrentVersionFileName); - if (!file_util::PathExists(current_version_path)) { - LOG(INFO) << "Deleting incomplete install for directory " + // If there is no entry in the prefs file, just delete the directory and + // move on. This can legitimately happen when an uninstall does not + // complete, for example, when a plugin is in use at uninstall time. + if (installed_ids.count(extension_id) == 0) { + LOG(INFO) << "Deleting unreferenced install for directory " << WideToASCII(extension_path.ToWStringHack()) << "."; file_util::Delete(extension_path, true); // Recursive. continue; @@ -409,4 +349,4 @@ bool CheckForIllegalFilenames(const FilePath& extension_path, return true; } -} // extensionfile_util +} // extension_file_util |