Chromium Code Reviews| 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 // This file defines the methods useful for uninstalling Chrome. | 5 // This file defines the methods useful for uninstalling Chrome. |
| 6 | 6 |
| 7 #include "chrome/installer/setup/uninstall.h" | 7 #include "chrome/installer/setup/uninstall.h" |
| 8 | 8 |
| 9 #include <windows.h> | 9 #include <windows.h> |
| 10 | 10 |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/base_paths.h" | 13 #include "base/base_paths.h" |
| 14 #include "base/files/file_enumerator.h" | 14 #include "base/files/file_enumerator.h" |
| 15 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
| 16 #include "base/path_service.h" | 16 #include "base/path_service.h" |
| 17 #include "base/process/kill.h" | 17 #include "base/process/kill.h" |
| 18 #include "base/strings/string16.h" | 18 #include "base/strings/string16.h" |
| 19 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
| 20 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
| 21 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
| 22 #include "base/win/registry.h" | 22 #include "base/win/registry.h" |
| 23 #include "base/win/scoped_handle.h" | 23 #include "base/win/scoped_handle.h" |
| 24 #include "base/win/shortcut.h" | 24 #include "base/win/shortcut.h" |
| 25 #include "base/win/windows_version.h" | 25 #include "base/win/windows_version.h" |
| 26 #include "chrome/common/chrome_constants.h" | 26 #include "chrome/common/chrome_constants.h" |
| 27 #include "chrome/common/chrome_paths.h" | 27 #include "chrome/common/chrome_paths.h" |
| 28 #include "chrome/common/chrome_result_codes.h" | 28 #include "chrome/common/chrome_result_codes.h" |
| 29 #include "chrome/installer/setup/app_launcher_installer.h" | |
| 29 #include "chrome/installer/setup/install.h" | 30 #include "chrome/installer/setup/install.h" |
| 30 #include "chrome/installer/setup/install_worker.h" | 31 #include "chrome/installer/setup/install_worker.h" |
| 31 #include "chrome/installer/setup/setup_constants.h" | 32 #include "chrome/installer/setup/setup_constants.h" |
| 32 #include "chrome/installer/setup/setup_util.h" | 33 #include "chrome/installer/setup/setup_util.h" |
| 33 #include "chrome/installer/util/auto_launch_util.h" | 34 #include "chrome/installer/util/auto_launch_util.h" |
| 34 #include "chrome/installer/util/browser_distribution.h" | 35 #include "chrome/installer/util/browser_distribution.h" |
| 35 #include "chrome/installer/util/channel_info.h" | 36 #include "chrome/installer/util/channel_info.h" |
| 36 #include "chrome/installer/util/delete_after_reboot_helper.h" | 37 #include "chrome/installer/util/delete_after_reboot_helper.h" |
| 37 #include "chrome/installer/util/firewall_manager_win.h" | 38 #include "chrome/installer/util/firewall_manager_win.h" |
| 38 #include "chrome/installer/util/google_update_constants.h" | 39 #include "chrome/installer/util/google_update_constants.h" |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 | 179 |
| 179 // If chrome has been reactivated, clear all events for this brand as well. | 180 // If chrome has been reactivated, clear all events for this brand as well. |
| 180 base::string16 reactivation_brand_wide; | 181 base::string16 reactivation_brand_wide; |
| 181 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand_wide)) { | 182 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand_wide)) { |
| 182 std::string reactivation_brand(base::UTF16ToASCII(reactivation_brand_wide)); | 183 std::string reactivation_brand(base::UTF16ToASCII(reactivation_brand_wide)); |
| 183 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str()); | 184 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str()); |
| 184 rlz_lib::ClearProductState(rlz_lib::CHROME, points); | 185 rlz_lib::ClearProductState(rlz_lib::CHROME, points); |
| 185 } | 186 } |
| 186 } | 187 } |
| 187 | 188 |
| 188 // Decides whether setup.exe and the installer archive should be removed based | 189 // Returns whether setup.exe should be removed based on the original and |
| 189 // on the original and installer states: | 190 // installer states: |
| 190 // * non-multi product being uninstalled: remove both | 191 // * non-multi product being uninstalled: remove setup.exe |
| 191 // * any multi product left besides App Host: keep both | 192 // * any multi product left: keep setup.exe |
| 192 // * only App Host left: keep setup.exe | 193 bool CheckShouldRemoveSetup(const InstallationState& original_state, |
| 193 void CheckShouldRemoveSetupAndArchive(const InstallationState& original_state, | 194 const InstallerState& installer_state) { |
| 194 const InstallerState& installer_state, | 195 // If any multi-install product is left we must leave the installer and |
| 195 bool* remove_setup, | 196 // archive. |
| 196 bool* remove_archive) { | |
| 197 *remove_setup = true; | |
| 198 *remove_archive = true; | |
| 199 | |
| 200 // If any multi-install product is left (other than App Host) we must leave | |
| 201 // the installer and archive. For the App Host, we only leave the installer. | |
| 202 if (!installer_state.is_multi_install()) { | 197 if (!installer_state.is_multi_install()) { |
| 203 VLOG(1) << "Removing all installer files for a non-multi installation."; | 198 VLOG(1) << "Removing all installer files for a non-multi installation."; |
| 204 } else { | 199 } else { |
| 205 // Loop through all known products... | 200 // Loop through all known products... |
| 206 for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { | 201 for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { |
| 207 BrowserDistribution::Type dist_type = | 202 BrowserDistribution::Type dist_type = |
| 208 static_cast<BrowserDistribution::Type>(i); | 203 static_cast<BrowserDistribution::Type>(i); |
| 209 const ProductState* product_state = original_state.GetProductState( | 204 const ProductState* product_state = original_state.GetProductState( |
| 210 installer_state.system_install(), dist_type); | 205 installer_state.system_install(), dist_type); |
| 211 // If the product is installed, in multi mode, and is not part of the | 206 // If the product is installed, in multi mode, and is not part of the |
| 212 // active uninstallation... | 207 // active uninstallation... |
| 213 if (product_state && product_state->is_multi_install() && | 208 if (product_state && product_state->is_multi_install() && |
| 214 !installer_state.FindProduct(dist_type)) { | 209 !installer_state.FindProduct(dist_type)) { |
| 215 // setup.exe will not be removed as there is a remaining multi-install | 210 // setup.exe will not be removed as there is a remaining multi-install |
| 216 // product. | 211 // product. |
| 217 *remove_setup = false; | 212 VLOG(1) << "Keeping all installer files due to a remaining " |
| 218 // As a special case, we can still remove the actual archive if the | 213 << "multi-install product."; |
| 219 // only remaining product is the App Host. | 214 return false; |
| 220 if (dist_type != BrowserDistribution::CHROME_APP_HOST) { | |
| 221 VLOG(1) << "Keeping all installer files due to a remaining " | |
| 222 << "multi-install product."; | |
| 223 *remove_archive = false; | |
| 224 return; | |
| 225 } | |
| 226 VLOG(1) << "Keeping setup.exe due to a remaining " | |
| 227 << "app-host installation."; | |
| 228 } | 215 } |
| 229 } | 216 } |
| 230 VLOG(1) << "Removing the installer archive."; | 217 VLOG(1) << "Removing all installer files."; |
| 231 if (remove_setup) | |
| 232 VLOG(1) << "Removing setup.exe."; | |
| 233 } | 218 } |
| 219 return true; | |
| 234 } | 220 } |
| 235 | 221 |
| 236 // Removes all files from the installer directory, leaving setup.exe iff | 222 // Removes all files from the installer directory, leaving setup.exe iff |
| 237 // |remove_setup| is false. | 223 // |remove_setup| is false. |
| 238 // Returns false in case of an error. | 224 // Returns false in case of an error. |
| 239 bool RemoveInstallerFiles(const base::FilePath& installer_directory, | 225 bool RemoveInstallerFiles(const base::FilePath& installer_directory, |
| 240 bool remove_setup) { | 226 bool remove_setup) { |
| 241 base::FileEnumerator file_enumerator( | 227 base::FileEnumerator file_enumerator( |
| 242 installer_directory, | 228 installer_directory, |
| 243 false, | 229 false, |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 506 // We cannot delete the file right away, but try to delete it some other | 492 // We cannot delete the file right away, but try to delete it some other |
| 507 // way. Either with the help of a different process or the system. | 493 // way. Either with the help of a different process or the system. |
| 508 if (!base::DeleteFileAfterReboot(temp_file)) { | 494 if (!base::DeleteFileAfterReboot(temp_file)) { |
| 509 const uint32 kDeleteAfterMs = 10 * 1000; | 495 const uint32 kDeleteAfterMs = 10 * 1000; |
| 510 installer::DeleteFileFromTempProcess(temp_file, kDeleteAfterMs); | 496 installer::DeleteFileFromTempProcess(temp_file, kDeleteAfterMs); |
| 511 } | 497 } |
| 512 } | 498 } |
| 513 return true; | 499 return true; |
| 514 } | 500 } |
| 515 | 501 |
| 516 DeleteResult DeleteAppHostFilesAndFolders(const InstallerState& installer_state, | |
| 517 const Version& installed_version) { | |
| 518 const base::FilePath& target_path = installer_state.target_path(); | |
| 519 if (target_path.empty()) { | |
| 520 LOG(ERROR) << "DeleteAppHostFilesAndFolders: no installation destination " | |
| 521 << "path."; | |
| 522 return DELETE_FAILED; // Nothing else we can do to uninstall, so we return. | |
| 523 } | |
| 524 | |
| 525 DeleteInstallTempDir(target_path); | |
| 526 | |
| 527 DeleteResult result = DELETE_SUCCEEDED; | |
| 528 | |
| 529 base::FilePath app_host_exe(target_path.Append(installer::kChromeAppHostExe)); | |
| 530 if (!base::DeleteFile(app_host_exe, false)) { | |
| 531 result = DELETE_FAILED; | |
| 532 LOG(ERROR) << "Failed to delete path: " << app_host_exe.value(); | |
| 533 } | |
| 534 | |
| 535 return result; | |
| 536 } | |
| 537 | |
| 538 DeleteResult DeleteChromeFilesAndFolders(const InstallerState& installer_state, | 502 DeleteResult DeleteChromeFilesAndFolders(const InstallerState& installer_state, |
| 539 const base::FilePath& setup_exe) { | 503 const base::FilePath& setup_exe) { |
| 540 const base::FilePath& target_path = installer_state.target_path(); | 504 const base::FilePath& target_path = installer_state.target_path(); |
| 541 if (target_path.empty()) { | 505 if (target_path.empty()) { |
| 542 LOG(ERROR) << "DeleteChromeFilesAndFolders: no installation destination " | 506 LOG(ERROR) << "DeleteChromeFilesAndFolders: no installation destination " |
| 543 << "path."; | 507 << "path."; |
| 544 return DELETE_FAILED; // Nothing else we can do to uninstall, so we return. | 508 return DELETE_FAILED; // Nothing else we can do to uninstall, so we return. |
| 545 } | 509 } |
| 546 | 510 |
| 547 DeleteInstallTempDir(target_path); | 511 DeleteInstallTempDir(target_path); |
| 548 | 512 |
| 549 DeleteResult result = DELETE_SUCCEEDED; | 513 DeleteResult result = DELETE_SUCCEEDED; |
| 550 | 514 |
| 551 base::FilePath installer_directory; | 515 base::FilePath installer_directory; |
| 552 if (target_path.IsParent(setup_exe)) | 516 if (target_path.IsParent(setup_exe)) |
| 553 installer_directory = setup_exe.DirName(); | 517 installer_directory = setup_exe.DirName(); |
| 554 | 518 |
| 555 // Enumerate all the files in target_path recursively (breadth-first). | 519 // Enumerate all the files in target_path recursively (breadth-first). |
| 556 // We delete a file or folder unless it is a parent/child of the installer | 520 // We delete a file or folder unless it is a parent/child of the installer |
| 557 // directory. For parents of the installer directory, we will later recurse | 521 // directory. For parents of the installer directory, we will later recurse |
| 558 // and delete all the children (that are not also parents/children of the | 522 // and delete all the children (that are not also parents/children of the |
| 559 // installer directory). | 523 // installer directory). |
| 560 base::FileEnumerator file_enumerator(target_path, true, | 524 base::FileEnumerator file_enumerator(target_path, true, |
| 561 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); | 525 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); |
| 562 for (base::FilePath to_delete = file_enumerator.Next(); !to_delete.empty(); | 526 for (base::FilePath to_delete = file_enumerator.Next(); !to_delete.empty(); |
| 563 to_delete = file_enumerator.Next()) { | 527 to_delete = file_enumerator.Next()) { |
| 564 if (to_delete.BaseName().value() == installer::kChromeAppHostExe) | |
| 565 continue; | |
| 566 if (!installer_directory.empty() && | 528 if (!installer_directory.empty() && |
| 567 (to_delete == installer_directory || | 529 (to_delete == installer_directory || |
| 568 installer_directory.IsParent(to_delete) || | 530 installer_directory.IsParent(to_delete) || |
| 569 to_delete.IsParent(installer_directory))) { | 531 to_delete.IsParent(installer_directory))) { |
| 570 continue; | 532 continue; |
| 571 } | 533 } |
| 572 | 534 |
| 573 VLOG(1) << "Deleting install path " << to_delete.value(); | 535 VLOG(1) << "Deleting install path " << to_delete.value(); |
| 574 if (!base::DeleteFile(to_delete, true)) { | 536 if (!base::DeleteFile(to_delete, true)) { |
| 575 LOG(ERROR) << "Failed to delete path (1st try): " << to_delete.value(); | 537 LOG(ERROR) << "Failed to delete path (1st try): " << to_delete.value(); |
| (...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1141 new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration); | 1103 new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration); |
| 1142 if (!suffix.empty()) { | 1104 if (!suffix.empty()) { |
| 1143 new_cmd.AppendSwitchNative( | 1105 new_cmd.AppendSwitchNative( |
| 1144 installer::switches::kRegisterChromeBrowserSuffix, suffix); | 1106 installer::switches::kRegisterChromeBrowserSuffix, suffix); |
| 1145 } | 1107 } |
| 1146 DWORD exit_code = installer::UNKNOWN_STATUS; | 1108 DWORD exit_code = installer::UNKNOWN_STATUS; |
| 1147 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); | 1109 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); |
| 1148 } | 1110 } |
| 1149 } | 1111 } |
| 1150 | 1112 |
| 1113 HKEY reg_root = installer_state.root_key(); | |
| 1114 | |
| 1151 if (is_chrome) { | 1115 if (is_chrome) { |
| 1152 // Chrome is not in use so lets uninstall Chrome by deleting various files | 1116 // Chrome is not in use so lets uninstall Chrome by deleting various files |
| 1153 // and registry entries. Here we will just make best effort and keep going | 1117 // and registry entries. Here we will just make best effort and keep going |
| 1154 // in case of errors. | 1118 // in case of errors. |
| 1155 ClearRlzProductState(); | 1119 ClearRlzProductState(); |
| 1156 // Delete the key that delegate_execute might make. | 1120 // Delete the key that delegate_execute might make. |
| 1157 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { | 1121 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
| 1158 InstallUtil::DeleteRegistryKey(HKEY_CURRENT_USER, | 1122 InstallUtil::DeleteRegistryKey(HKEY_CURRENT_USER, |
| 1159 chrome::kMetroRegistryPath, | 1123 chrome::kMetroRegistryPath, |
| 1160 WorkItem::kWow64Default); | 1124 WorkItem::kWow64Default); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1173 Append(installer::kChromeExe)); | 1137 Append(installer::kChromeExe)); |
| 1174 VLOG(1) << "Retargeting user-generated Chrome shortcuts."; | 1138 VLOG(1) << "Retargeting user-generated Chrome shortcuts."; |
| 1175 if (base::PathExists(system_chrome_path)) { | 1139 if (base::PathExists(system_chrome_path)) { |
| 1176 RetargetUserShortcutsWithArgs(installer_state, product, chrome_exe, | 1140 RetargetUserShortcutsWithArgs(installer_state, product, chrome_exe, |
| 1177 system_chrome_path); | 1141 system_chrome_path); |
| 1178 } else { | 1142 } else { |
| 1179 LOG(ERROR) << "Retarget failed: system-level Chrome not found."; | 1143 LOG(ERROR) << "Retarget failed: system-level Chrome not found."; |
| 1180 } | 1144 } |
| 1181 } | 1145 } |
| 1182 | 1146 |
| 1147 #if defined(GOOGLE_CHROME_BUILD) | |
| 1148 if (!InstallUtil::IsChromeSxSProcess()) { | |
|
grt (UTC plus 2)
2015/01/09 18:57:04
nit: no braces
huangs
2015/01/18 01:18:24
Done.
| |
| 1149 app_launcher_installer::RemoveShadowKey(reg_root); | |
|
grt (UTC plus 2)
2015/01/09 18:57:04
i think this belongs in the is_chrome block below
huangs
2015/01/18 01:18:24
Moved, but I don't understand the reason you state
grt (UTC plus 2)
2015/01/20 21:30:22
Doh! So it is! In any case, I think the block belo
huangs
2015/01/20 23:26:00
Okay. No additional change here.
| |
| 1150 } | |
| 1151 #endif | |
| 1152 | |
| 1183 DeleteShortcuts(installer_state, product, chrome_exe); | 1153 DeleteShortcuts(installer_state, product, chrome_exe); |
| 1184 } | 1154 } |
| 1185 | 1155 |
| 1186 // Delete the registry keys (Uninstall key and Version key). | 1156 // Delete the registry keys (Uninstall key and Version key). |
| 1187 HKEY reg_root = installer_state.root_key(); | |
| 1188 | |
| 1189 // Note that we must retrieve the distribution-specific data before deleting | 1157 // Note that we must retrieve the distribution-specific data before deleting |
| 1190 // product.GetVersionKey(). | 1158 // product.GetVersionKey(). |
| 1191 base::string16 distribution_data(browser_dist->GetDistributionData(reg_root)); | 1159 base::string16 distribution_data(browser_dist->GetDistributionData(reg_root)); |
| 1192 | 1160 |
| 1193 // Remove Control Panel uninstall link. | 1161 // Remove Control Panel uninstall link. |
| 1194 if (product.ShouldCreateUninstallEntry()) { | 1162 if (product.ShouldCreateUninstallEntry()) { |
| 1195 InstallUtil::DeleteRegistryKey( | 1163 InstallUtil::DeleteRegistryKey( |
| 1196 reg_root, browser_dist->GetUninstallRegPath(), KEY_WOW64_32KEY); | 1164 reg_root, browser_dist->GetUninstallRegPath(), KEY_WOW64_32KEY); |
| 1197 } | 1165 } |
| 1198 | 1166 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1269 | 1237 |
| 1270 UninstallActiveSetupEntries(installer_state, product); | 1238 UninstallActiveSetupEntries(installer_state, product); |
| 1271 | 1239 |
| 1272 UninstallFirewallRules(browser_dist, chrome_exe); | 1240 UninstallFirewallRules(browser_dist, chrome_exe); |
| 1273 | 1241 |
| 1274 RemoveBlacklistState(); | 1242 RemoveBlacklistState(); |
| 1275 | 1243 |
| 1276 // Notify the shell that associations have changed since Chrome was likely | 1244 // Notify the shell that associations have changed since Chrome was likely |
| 1277 // unregistered. | 1245 // unregistered. |
| 1278 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); | 1246 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); |
| 1279 | |
| 1280 // TODO(huangs): Implement actual migration code and remove the hack below. | |
| 1281 // Remove the "shadow" App Launcher registry keys. | |
| 1282 // TODO(hunags): Management of this key should not be conditional on | |
| 1283 // multi-install since the app list feature is available regardless of how | |
| 1284 // chrome is installed. | |
| 1285 if (installer_state.is_multi_install()) { | |
| 1286 // Delete the "shadow" keys. | |
| 1287 BrowserDistribution* shadow_app_launcher_dist = | |
| 1288 BrowserDistribution::GetSpecificDistribution( | |
| 1289 BrowserDistribution::CHROME_APP_HOST); | |
| 1290 InstallUtil::DeleteRegistryKey( | |
| 1291 reg_root, | |
| 1292 shadow_app_launcher_dist->GetVersionKey(), | |
| 1293 KEY_WOW64_32KEY); | |
| 1294 } | |
| 1295 } | 1247 } |
| 1296 | 1248 |
| 1297 if (installer_state.is_multi_install()) | 1249 if (installer_state.is_multi_install()) |
| 1298 ProcessGoogleUpdateItems(original_state, installer_state, product); | 1250 ProcessGoogleUpdateItems(original_state, installer_state, product); |
| 1299 | 1251 |
| 1300 // Get the state of the installed product (if any) | 1252 // Get the state of the installed product (if any) |
| 1301 const ProductState* product_state = | 1253 const ProductState* product_state = |
| 1302 original_state.GetProductState(installer_state.system_install(), | 1254 original_state.GetProductState(installer_state.system_install(), |
| 1303 browser_dist->GetType()); | 1255 browser_dist->GetType()); |
| 1304 | 1256 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1361 base::FilePath user_data_dir(GetUserDataDir(product)); | 1313 base::FilePath user_data_dir(GetUserDataDir(product)); |
| 1362 base::FilePath backup_state_file; | 1314 base::FilePath backup_state_file; |
| 1363 if (!user_data_dir.empty()) { | 1315 if (!user_data_dir.empty()) { |
| 1364 backup_state_file = BackupLocalStateFile(user_data_dir); | 1316 backup_state_file = BackupLocalStateFile(user_data_dir); |
| 1365 } else { | 1317 } else { |
| 1366 LOG(ERROR) << "Could not retrieve the user's profile directory."; | 1318 LOG(ERROR) << "Could not retrieve the user's profile directory."; |
| 1367 ret = installer::UNINSTALL_FAILED; | 1319 ret = installer::UNINSTALL_FAILED; |
| 1368 delete_profile = false; | 1320 delete_profile = false; |
| 1369 } | 1321 } |
| 1370 | 1322 |
| 1371 if (product.is_chrome_app_host()) { | 1323 if (!installer_state.is_multi_install() || product.is_chrome_binaries()) { |
| 1372 DeleteAppHostFilesAndFolders(installer_state, product_state->version()); | |
| 1373 } else if (!installer_state.is_multi_install() || | |
| 1374 product.is_chrome_binaries()) { | |
| 1375 DeleteResult delete_result = DeleteChromeFilesAndFolders( | 1324 DeleteResult delete_result = DeleteChromeFilesAndFolders( |
| 1376 installer_state, base::MakeAbsoluteFilePath(setup_exe)); | 1325 installer_state, base::MakeAbsoluteFilePath(setup_exe)); |
| 1377 if (delete_result == DELETE_FAILED) { | 1326 if (delete_result == DELETE_FAILED) { |
| 1378 ret = installer::UNINSTALL_FAILED; | 1327 ret = installer::UNINSTALL_FAILED; |
| 1379 } else if (delete_result == DELETE_REQUIRES_REBOOT) { | 1328 } else if (delete_result == DELETE_REQUIRES_REBOOT) { |
| 1380 ret = installer::UNINSTALL_REQUIRES_REBOOT; | 1329 ret = installer::UNINSTALL_REQUIRES_REBOOT; |
| 1381 } | 1330 } |
| 1382 } | 1331 } |
| 1383 | 1332 |
| 1384 if (delete_profile) | 1333 if (delete_profile) |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1412 LOG(ERROR) << "No installation destination path."; | 1361 LOG(ERROR) << "No installation destination path."; |
| 1413 *uninstall_status = UNINSTALL_FAILED; | 1362 *uninstall_status = UNINSTALL_FAILED; |
| 1414 return; | 1363 return; |
| 1415 } | 1364 } |
| 1416 if (!target_path.IsParent(base::MakeAbsoluteFilePath(setup_exe))) { | 1365 if (!target_path.IsParent(base::MakeAbsoluteFilePath(setup_exe))) { |
| 1417 VLOG(1) << "setup.exe is not in target path. Skipping installer cleanup."; | 1366 VLOG(1) << "setup.exe is not in target path. Skipping installer cleanup."; |
| 1418 return; | 1367 return; |
| 1419 } | 1368 } |
| 1420 base::FilePath install_directory(setup_exe.DirName()); | 1369 base::FilePath install_directory(setup_exe.DirName()); |
| 1421 | 1370 |
| 1422 bool remove_setup = true; | 1371 bool remove_setup = CheckShouldRemoveSetup(original_state, installer_state); |
| 1423 bool remove_archive = true; | |
| 1424 CheckShouldRemoveSetupAndArchive(original_state, installer_state, | |
| 1425 &remove_setup, &remove_archive); | |
| 1426 if (!remove_archive) | |
| 1427 return; | |
| 1428 | 1372 |
| 1429 if (remove_setup) { | 1373 if (remove_setup) { |
| 1430 // In order to be able to remove the folder in which we're running, we | 1374 // In order to be able to remove the folder in which we're running, we |
| 1431 // need to move setup.exe out of the install folder. | 1375 // need to move setup.exe out of the install folder. |
| 1432 // TODO(tommi): What if the temp folder is on a different volume? | 1376 // TODO(tommi): What if the temp folder is on a different volume? |
| 1433 MoveSetupOutOfInstallFolder(installer_state, setup_exe); | 1377 MoveSetupOutOfInstallFolder(installer_state, setup_exe); |
| 1434 } | 1378 } |
| 1435 | 1379 |
| 1436 // Remove files from "...\<product>\Application\<version>\Installer" | 1380 // Remove files from "...\<product>\Application\<version>\Installer" |
| 1437 if (!RemoveInstallerFiles(install_directory, remove_setup)) { | 1381 if (!RemoveInstallerFiles(install_directory, remove_setup)) { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 1466 // If we need a reboot to continue, schedule the parent directories for | 1410 // If we need a reboot to continue, schedule the parent directories for |
| 1467 // deletion unconditionally. If they are not empty, the session manager | 1411 // deletion unconditionally. If they are not empty, the session manager |
| 1468 // will not delete them on reboot. | 1412 // will not delete them on reboot. |
| 1469 ScheduleParentAndGrandparentForDeletion(target_path); | 1413 ScheduleParentAndGrandparentForDeletion(target_path); |
| 1470 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { | 1414 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { |
| 1471 *uninstall_status = UNINSTALL_FAILED; | 1415 *uninstall_status = UNINSTALL_FAILED; |
| 1472 } | 1416 } |
| 1473 } | 1417 } |
| 1474 | 1418 |
| 1475 } // namespace installer | 1419 } // namespace installer |
| OLD | NEW |