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 |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 if (!parent_dir.empty() && file_util::IsDirectoryEmpty(parent_dir)) { | 332 if (!parent_dir.empty() && file_util::IsDirectoryEmpty(parent_dir)) { |
333 if (!file_util::Delete(parent_dir, true)) { | 333 if (!file_util::Delete(parent_dir, true)) { |
334 ret = false; | 334 ret = false; |
335 LOG(ERROR) << "Failed to delete folder: " << parent_dir.value(); | 335 LOG(ERROR) << "Failed to delete folder: " << parent_dir.value(); |
336 } | 336 } |
337 } | 337 } |
338 } | 338 } |
339 return ret; | 339 return ret; |
340 } | 340 } |
341 | 341 |
342 FilePath GetLocalStateFolder(const Product& product) { | 342 void GetLocalStateFolders(const Product& product, |
| 343 std::vector<FilePath>* paths) { |
343 // Obtain the location of the user profile data. | 344 // Obtain the location of the user profile data. |
344 FilePath local_state_folder = product.GetUserDataPath(); | 345 product.GetUserDataPaths(paths); |
345 LOG_IF(ERROR, local_state_folder.empty()) | 346 LOG_IF(ERROR, paths->empty()) |
346 << "Could not retrieve user's profile directory."; | 347 << "Could not retrieve user's profile directory."; |
347 | |
348 return local_state_folder; | |
349 } | 348 } |
350 | 349 |
351 // Creates a copy of the local state file and returns a path to the copy. | 350 // Creates a copy of the local state file and returns a path to the copy. |
352 FilePath BackupLocalStateFile(const FilePath& local_state_folder) { | 351 FilePath BackupLocalStateFile( |
| 352 const std::vector<FilePath>& local_state_folders) { |
353 FilePath backup; | 353 FilePath backup; |
354 FilePath state_file(local_state_folder.Append(chrome::kLocalStateFilename)); | 354 |
355 if (!file_util::CreateTemporaryFile(&backup)) { | 355 // Copy the first local state file that is found. |
356 LOG(ERROR) << "Failed to create temporary file for Local State."; | 356 for (size_t i = 0; i < local_state_folders.size(); ++i) { |
357 } else { | 357 const FilePath& local_state_folder = local_state_folders[i]; |
358 file_util::CopyFile(state_file, backup); | 358 FilePath state_file(local_state_folder.Append(chrome::kLocalStateFilename)); |
| 359 if (!file_util::PathExists(state_file)) |
| 360 continue; |
| 361 if (!file_util::CreateTemporaryFile(&backup)) |
| 362 LOG(ERROR) << "Failed to create temporary file for Local State."; |
| 363 else |
| 364 file_util::CopyFile(state_file, backup); |
| 365 break; |
359 } | 366 } |
360 return backup; | 367 return backup; |
361 } | 368 } |
362 | 369 |
363 enum DeleteResult { | 370 enum DeleteResult { |
364 DELETE_SUCCEEDED, | 371 DELETE_SUCCEEDED, |
365 DELETE_FAILED, | 372 DELETE_FAILED, |
366 DELETE_REQUIRES_REBOOT, | 373 DELETE_REQUIRES_REBOOT, |
367 }; | 374 }; |
368 | 375 |
369 // Copies the local state to the temp folder and then deletes it. | 376 // Deletes all user data directories for a product. |
370 // The path to the copy is returned via the local_state_copy parameter. | 377 DeleteResult DeleteLocalState(const std::vector<FilePath>& local_state_folders, |
371 DeleteResult DeleteLocalState(const Product& product) { | 378 bool schedule_on_failure) { |
372 FilePath user_local_state(GetLocalStateFolder(product)); | 379 if (local_state_folders.empty()) |
373 if (user_local_state.empty()) | |
374 return DELETE_SUCCEEDED; | 380 return DELETE_SUCCEEDED; |
375 | 381 |
376 DeleteResult result = DELETE_SUCCEEDED; | 382 DeleteResult result = DELETE_SUCCEEDED; |
377 VLOG(1) << "Deleting user profile " << user_local_state.value(); | 383 for (size_t i = 0; i < local_state_folders.size(); ++i) { |
378 if (!file_util::Delete(user_local_state, true)) { | 384 const FilePath& user_local_state = local_state_folders[i]; |
379 LOG(ERROR) << "Failed to delete user profile dir: " | 385 VLOG(1) << "Deleting user profile " << user_local_state.value(); |
380 << user_local_state.value(); | 386 if (!file_util::Delete(user_local_state, true)) { |
381 if (product.is_chrome_frame()) { | 387 LOG(ERROR) << "Failed to delete user profile dir: " |
382 ScheduleDirectoryForDeletion(user_local_state.value().c_str()); | 388 << user_local_state.value(); |
383 result = DELETE_REQUIRES_REBOOT; | 389 if (schedule_on_failure) { |
384 } else { | 390 ScheduleDirectoryForDeletion(user_local_state.value().c_str()); |
385 result = DELETE_FAILED; | 391 result = DELETE_REQUIRES_REBOOT; |
| 392 } else { |
| 393 result = DELETE_FAILED; |
| 394 } |
386 } | 395 } |
387 } | 396 } |
388 | 397 |
389 if (result == DELETE_REQUIRES_REBOOT) { | 398 if (result == DELETE_REQUIRES_REBOOT) { |
390 ScheduleParentAndGrandparentForDeletion(user_local_state); | 399 ScheduleParentAndGrandparentForDeletion(local_state_folders[0]); |
391 } else { | 400 } else { |
392 DeleteEmptyParentDir(user_local_state); | 401 DeleteEmptyParentDir(local_state_folders[0]); |
393 } | 402 } |
394 | 403 |
395 return result; | 404 return result; |
396 } | 405 } |
397 | 406 |
398 bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state, | 407 bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state, |
399 const FilePath& setup_path, | 408 const FilePath& setup_path, |
400 const Version& installed_version) { | 409 const Version& installed_version) { |
401 bool ret = false; | 410 bool ret = false; |
402 FilePath setup_exe(installer_state.GetInstallerDirectory(installed_version) | 411 FilePath setup_exe(installer_state.GetInstallerDirectory(installed_version) |
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1094 | 1103 |
1095 // Finally delete all the files from Chrome folder after moving setup.exe | 1104 // Finally delete all the files from Chrome folder after moving setup.exe |
1096 // and the user's Local State to a temp location. | 1105 // and the user's Local State to a temp location. |
1097 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, | 1106 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, |
1098 product); | 1107 product); |
1099 ret = installer::UNINSTALL_SUCCESSFUL; | 1108 ret = installer::UNINSTALL_SUCCESSFUL; |
1100 | 1109 |
1101 // When deleting files, we must make sure that we're either a "single" | 1110 // When deleting files, we must make sure that we're either a "single" |
1102 // (aka non-multi) installation or we are the Chrome Binaries. | 1111 // (aka non-multi) installation or we are the Chrome Binaries. |
1103 | 1112 |
1104 FilePath backup_state_file( | 1113 std::vector<FilePath> local_state_folders; |
1105 BackupLocalStateFile(GetLocalStateFolder(product))); | 1114 GetLocalStateFolders(product, &local_state_folders); |
| 1115 FilePath backup_state_file(BackupLocalStateFile(local_state_folders)); |
1106 | 1116 |
1107 DeleteResult delete_result = DELETE_SUCCEEDED; | 1117 DeleteResult delete_result = DELETE_SUCCEEDED; |
1108 | 1118 |
1109 if (product.is_chrome_app_host()) { | 1119 if (product.is_chrome_app_host()) { |
1110 DeleteAppHostFilesAndFolders(installer_state, product_state->version()); | 1120 DeleteAppHostFilesAndFolders(installer_state, product_state->version()); |
1111 } else if (!installer_state.is_multi_install() || | 1121 } else if (!installer_state.is_multi_install() || |
1112 product.is_chrome_binaries()) { | 1122 product.is_chrome_binaries()) { |
1113 | 1123 |
1114 // In order to be able to remove the folder in which we're running, we | 1124 // In order to be able to remove the folder in which we're running, we |
1115 // need to move setup.exe out of the install folder. | 1125 // need to move setup.exe out of the install folder. |
1116 // TODO(tommi): What if the temp folder is on a different volume? | 1126 // TODO(tommi): What if the temp folder is on a different volume? |
1117 MoveSetupOutOfInstallFolder(installer_state, setup_path, | 1127 MoveSetupOutOfInstallFolder(installer_state, setup_path, |
1118 product_state->version()); | 1128 product_state->version()); |
1119 delete_result = DeleteChromeFilesAndFolders(installer_state, | 1129 delete_result = DeleteChromeFilesAndFolders(installer_state, |
1120 product_state->version()); | 1130 product_state->version()); |
1121 } | 1131 } |
1122 | 1132 |
1123 if (delete_profile) | 1133 if (delete_profile) |
1124 DeleteLocalState(product); | 1134 DeleteLocalState(local_state_folders, product.is_chrome_frame()); |
1125 | 1135 |
1126 if (delete_result == DELETE_FAILED) { | 1136 if (delete_result == DELETE_FAILED) { |
1127 ret = installer::UNINSTALL_FAILED; | 1137 ret = installer::UNINSTALL_FAILED; |
1128 } else if (delete_result == DELETE_REQUIRES_REBOOT) { | 1138 } else if (delete_result == DELETE_REQUIRES_REBOOT) { |
1129 ret = installer::UNINSTALL_REQUIRES_REBOOT; | 1139 ret = installer::UNINSTALL_REQUIRES_REBOOT; |
1130 } | 1140 } |
1131 | 1141 |
1132 if (!force_uninstall) { | 1142 if (!force_uninstall) { |
1133 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; | 1143 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; |
1134 browser_dist->DoPostUninstallOperations(product_state->version(), | 1144 browser_dist->DoPostUninstallOperations(product_state->version(), |
1135 backup_state_file, distribution_data); | 1145 backup_state_file, distribution_data); |
1136 } | 1146 } |
1137 | 1147 |
1138 // Try and delete the preserved local state once the post-install | 1148 // Try and delete the preserved local state once the post-install |
1139 // operations are complete. | 1149 // operations are complete. |
1140 if (!backup_state_file.empty()) | 1150 if (!backup_state_file.empty()) |
1141 file_util::Delete(backup_state_file, false); | 1151 file_util::Delete(backup_state_file, false); |
1142 | 1152 |
1143 return ret; | 1153 return ret; |
1144 } | 1154 } |
1145 | 1155 |
1146 } // namespace installer | 1156 } // namespace installer |
OLD | NEW |