From f96ba6c9186cab5fb4842c4e427d54ec665c5d2f Mon Sep 17 00:00:00 2001 From: "kuchhal@chromium.org" Date: Wed, 8 Oct 2008 17:15:52 +0000 Subject: [PATCH] Fix some problems with machine level install. BUG=2380 Review URL: http://codereview.chromium.org/6402 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3015 0039d316-1c4b-4281-b951-d872f2087c98 --- base/file_util.h | 4 ++ base/file_util_win.cc | 7 ++ chrome/installer/setup/install.cc | 4 ++ chrome/installer/setup/main.cc | 2 +- chrome/installer/setup/setup.cc | 5 ++ chrome/installer/setup/uninstall.cc | 66 +++++++++++++------ chrome/installer/util/browser_distribution.cc | 3 - chrome/installer/util/browser_distribution.h | 2 - .../util/google_chrome_distribution.cc | 19 ------ .../util/google_chrome_distribution.h | 2 - 10 files changed, 66 insertions(+), 48 deletions(-) diff --git a/base/file_util.h b/base/file_util.h index b0605791c9..9624e605a6 100644 --- a/base/file_util.h +++ b/base/file_util.h @@ -208,6 +208,10 @@ bool UpdateShortcutLink(const wchar_t *source, const wchar_t *destination, const wchar_t *working_dir, const wchar_t *arguments, const wchar_t *description, const wchar_t *icon, int icon_index); + +// Return true if the given directory is empty +bool IsDirectoryEmpty(const std::wstring& dir_path); + #endif diff --git a/base/file_util_win.cc b/base/file_util_win.cc index fc53dc95d4..8253e53a8c 100644 --- a/base/file_util_win.cc +++ b/base/file_util_win.cc @@ -365,6 +365,13 @@ bool UpdateShortcutLink(const wchar_t *source, const wchar_t *destination, return SUCCEEDED(result); } +bool IsDirectoryEmpty(const std::wstring& dir_path) { + FileEnumerator files(dir_path, false, FileEnumerator::FILES_AND_DIRECTORIES); + if (files.Next().empty()) + return true; + return false; +} + bool GetTempDir(std::wstring* path) { wchar_t temp_path[MAX_PATH + 1]; DWORD path_len = ::GetTempPath(MAX_PATH, temp_path); diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc index 4f41e04358..5d65dbf65f 100644 --- a/chrome/installer/setup/install.cc +++ b/chrome/installer/setup/install.cc @@ -50,6 +50,10 @@ void AddUninstallShortcutWorkItems(HKEY reg_root, file_util::GetFilenameFromPath(exe_path)); uninstall_cmd.append(L"\" --"); uninstall_cmd.append(installer_util::switches::kUninstall); + if (reg_root == HKEY_LOCAL_MACHINE) { + uninstall_cmd.append(L" --"); + uninstall_cmd.append(installer_util::switches::kSystemInstall); + } // Create DisplayName, UninstallString and InstallLocation keys BrowserDistribution* dist = BrowserDistribution::GetDistribution(); diff --git a/chrome/installer/setup/main.cc b/chrome/installer/setup/main.cc index 54e66b8142..9714f68fff 100644 --- a/chrome/installer/setup/main.cc +++ b/chrome/installer/setup/main.cc @@ -272,7 +272,7 @@ installer_util::InstallStatus InstallChrome(const CommandLine& cmd_line, BrowserDistribution* dist = BrowserDistribution::GetDistribution(); dist->UpdateDiffInstallStatus(system_install, incremental_install, - install_status); + install_status); return install_status; } diff --git a/chrome/installer/setup/setup.cc b/chrome/installer/setup/setup.cc index 2ac4dfac30..e3edf19814 100644 --- a/chrome/installer/setup/setup.cc +++ b/chrome/installer/setup/setup.cc @@ -130,6 +130,11 @@ bool CreateOrUpdateChromeShortcuts(const std::wstring& exe_path, file_util::GetFilenameFromPath(exe_path)); std::wstring arguments(L" --"); arguments.append(installer_util::switches::kUninstall); + if (system_install) { + arguments.append(L" --"); + arguments.append(installer_util::switches::kSystemInstall); + } + LOG(INFO) << "Creating/updating uninstall link at " << uninstall_link; std::wstring target_folder = file_util::GetDirectoryFromPath(install_path); ret2 = file_util::CreateShortcutLink(setup_exe.c_str(), diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc index f4cb6971f8..4988e5471a 100644 --- a/chrome/installer/setup/uninstall.cc +++ b/chrome/installer/setup/uninstall.cc @@ -57,6 +57,49 @@ void DeleteChromeShortcut(bool system_uninstall) { } } +// Deletes all installed files of Chromium and Folders. Before deleting it +// needs to move setup.exe in a temp folder because the current process +// is using that file. It returns false when it can not get the path to +// installation folder, in all other cases it returns true even in case +// of error (only logs the error). +bool DeleteFilesAndFolders(const std::wstring& exe_path, bool system_uninstall, + const installer::Version& installed_version) { + std::wstring install_path(installer::GetChromeInstallPath(system_uninstall)); + if (install_path.empty()) { + LOG(ERROR) << "Could not get installation destination path."; + return false; // Nothing else we can do for uninstall, so we return. + } else { + LOG(INFO) << "install destination path: " << install_path; + } + + std::wstring setup_exe(installer::GetInstallerPathUnderChrome( + install_path, installed_version.GetString())); + file_util::AppendToPath(&setup_exe, file_util::GetFilenameFromPath(exe_path)); + + std::wstring temp_file; + file_util::CreateTemporaryFileName(&temp_file); + file_util::Move(setup_exe, temp_file); + + LOG(INFO) << "Deleting install path " << install_path; + if (!file_util::Delete(install_path, true)) + LOG(ERROR) << "Failed to delete folder: " << install_path; + + // Now check and delete if the parent directories are empty + // For example Google\Chrome or Chromium + std::wstring parent_dir = file_util::GetDirectoryFromPath(install_path); + if (!parent_dir.empty() && file_util::IsDirectoryEmpty(parent_dir)) { + if (!file_util::Delete(parent_dir, true)) + LOG(ERROR) << "Failed to delete folder: " << parent_dir; + parent_dir = file_util::GetDirectoryFromPath(parent_dir); + if (!parent_dir.empty() && + file_util::IsDirectoryEmpty(parent_dir)) { + if (!file_util::Delete(parent_dir, true)) + LOG(ERROR) << "Failed to delete folder: " << parent_dir; + } + } + return true; +} + // This method tries to delete a registry key and logs an error message // in case of failure. It returns true if deletion is successful, // otherwise false. @@ -126,8 +169,6 @@ installer_util::InstallStatus installer_setup::UninstallChrome( if (status != installer_util::UNINSTALL_CONFIRMED) return status; - BrowserDistribution* dist = BrowserDistribution::GetDistribution(); - dist->DoPreUninstallOperations(); #if defined(GOOGLE_CHROME_BUILD) // TODO(rahulk): This should be done by DoPreUninstallOperations call above wchar_t product[39]; // GUID + '\0' @@ -151,6 +192,7 @@ installer_util::InstallStatus installer_setup::UninstallChrome( // Delete the registry keys (Uninstall key and Version key). HKEY reg_root = system_uninstall ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; RegKey key(reg_root, L"", KEY_ALL_ACCESS); + BrowserDistribution* dist = BrowserDistribution::GetDistribution(); DeleteRegistryKey(key, dist->GetUninstallRegPath()); DeleteRegistryKey(key, dist->GetVersionKey()); @@ -188,26 +230,8 @@ installer_util::InstallStatus installer_setup::UninstallChrome( // Finally delete all the files from Chrome folder after moving setup.exe // to a temp location. - std::wstring install_path(installer::GetChromeInstallPath(system_uninstall)); - if (install_path.empty()) { - LOG(ERROR) << "Could not get installation destination path."; - // Nothing else we could do for uninstall, so we return. + if (!DeleteFilesAndFolders(exe_path, system_uninstall, installed_version)) return installer_util::UNINSTALL_FAILED; - } else { - LOG(INFO) << "install destination path: " << install_path; - } - - std::wstring setup_exe(installer::GetInstallerPathUnderChrome( - install_path, installed_version.GetString())); - file_util::AppendToPath(&setup_exe, file_util::GetFilenameFromPath(exe_path)); - - std::wstring temp_file; - file_util::CreateTemporaryFileName(&temp_file); - file_util::Move(setup_exe, temp_file); - - LOG(INFO) << "Deleting install path " << install_path; - if (!file_util::Delete(install_path, true)) - LOG(ERROR) << "Failed to delete folder: " << install_path; LOG(INFO) << "Uninstallation complete. Launching Uninstall survey."; dist->DoPostUninstallOperations(installed_version); diff --git a/chrome/installer/util/browser_distribution.cc b/chrome/installer/util/browser_distribution.cc index c34dca8520..914179c602 100644 --- a/chrome/installer/util/browser_distribution.cc +++ b/chrome/installer/util/browser_distribution.cc @@ -26,9 +26,6 @@ void BrowserDistribution::DoPostUninstallOperations( const installer::Version& version) { } -void BrowserDistribution::DoPreUninstallOperations() { -} - std::wstring BrowserDistribution::GetApplicationName() { return L"Chromium"; } diff --git a/chrome/installer/util/browser_distribution.h b/chrome/installer/util/browser_distribution.h index e678417f43..627ae75923 100644 --- a/chrome/installer/util/browser_distribution.h +++ b/chrome/installer/util/browser_distribution.h @@ -19,8 +19,6 @@ class BrowserDistribution { virtual void DoPostUninstallOperations(const installer::Version& version); - virtual void DoPreUninstallOperations(); - virtual std::wstring GetApplicationName(); virtual std::wstring GetInstallSubDir(); diff --git a/chrome/installer/util/google_chrome_distribution.cc b/chrome/installer/util/google_chrome_distribution.cc index e9c7b01a9e..f5ea4335c9 100644 --- a/chrome/installer/util/google_chrome_distribution.cc +++ b/chrome/installer/util/google_chrome_distribution.cc @@ -73,25 +73,6 @@ void GoogleChromeDistribution::DoPostUninstallOperations( WMIProcessUtil::Launch(command, &pid); } -// Uninstall Chrome specific Gears. First we find Gears MSI ProductId (that -// changes with every new version of Gears) using Gears MSI UpgradeCode (that -// does not change) and then uninstall Gears using API. -void GoogleChromeDistribution::DoPreUninstallOperations() { - /* TODO(rahulk) this comment is commented for now because it is causing extra - dependencies for the renderer. Need to remove ifdef from uninstall.cc and - uncomment this function. - wchar_t product[39]; // GUID + '\0' - MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); // Don't show any UI to user. - for (int i = 0; MsiEnumRelatedProducts(google_update::kGearsUpgradeCode, 0, i, - product) != ERROR_NO_MORE_ITEMS; ++i) { - LOG(INFO) << "Uninstalling Gears - " << product; - unsigned int ret = MsiConfigureProduct(product, INSTALLLEVEL_MAXIMUM, - INSTALLSTATE_ABSENT); - if (ret != ERROR_SUCCESS) - LOG(ERROR) << "Failed to uninstall Gears " << product << ": " << ret; - }*/ -} - std::wstring GoogleChromeDistribution::GetApplicationName() { const std::wstring& product_name = installer_util::GetLocalizedString(IDS_PRODUCT_NAME_BASE); diff --git a/chrome/installer/util/google_chrome_distribution.h b/chrome/installer/util/google_chrome_distribution.h index 9b15180907..9e803e0f52 100644 --- a/chrome/installer/util/google_chrome_distribution.h +++ b/chrome/installer/util/google_chrome_distribution.h @@ -15,8 +15,6 @@ class GoogleChromeDistribution : public BrowserDistribution { public: virtual void DoPostUninstallOperations(const installer::Version& version); - virtual void DoPreUninstallOperations(); - virtual std::wstring GetApplicationName(); virtual std::wstring GetInstallSubDir();