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 |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 388 if (!base::IsDirectoryEmpty(path)) | 388 if (!base::IsDirectoryEmpty(path)) |
| 389 return DELETE_NOT_EMPTY; | 389 return DELETE_NOT_EMPTY; |
| 390 | 390 |
| 391 if (base::DeleteFile(path, true)) | 391 if (base::DeleteFile(path, true)) |
| 392 return DELETE_SUCCEEDED; | 392 return DELETE_SUCCEEDED; |
| 393 | 393 |
| 394 LOG(ERROR) << "Failed to delete folder: " << path.value(); | 394 LOG(ERROR) << "Failed to delete folder: " << path.value(); |
| 395 return DELETE_FAILED; | 395 return DELETE_FAILED; |
| 396 } | 396 } |
| 397 | 397 |
| 398 void GetLocalStateFolders(const Product& product, | 398 base::FilePath GetLocalStateFolder(const Product& product) { |
| 399 std::vector<base::FilePath>* paths) { | |
| 400 // Obtain the location of the user profile data. | 399 // Obtain the location of the user profile data. |
| 401 product.GetUserDataPaths(paths); | 400 base::FilePath local_state_folder = product.GetUserDataPath(); |
| 402 LOG_IF(ERROR, paths->empty()) | 401 LOG_IF(ERROR, local_state_folder.empty()) |
| 403 << "Could not retrieve user's profile directory."; | 402 << "Could not retrieve user's profile directory."; |
| 403 | |
| 404 return local_state_folder; | |
| 404 } | 405 } |
| 405 | 406 |
| 406 // Creates a copy of the local state file and returns a path to the copy. | 407 // Creates a copy of the local state file and returns a path to the copy. |
| 407 base::FilePath BackupLocalStateFile( | 408 base::FilePath BackupLocalStateFile(const base::FilePath& local_state_folder) { |
| 408 const std::vector<base::FilePath>& local_state_folders) { | |
| 409 base::FilePath backup; | 409 base::FilePath backup; |
| 410 | 410 base::FilePath state_file( |
| 411 // Copy the first local state file that is found. | 411 local_state_folder.Append(chrome::kLocalStateFilename)); |
| 412 for (size_t i = 0; i < local_state_folders.size(); ++i) { | 412 if (!base::CreateTemporaryFile(&backup)) |
| 413 const base::FilePath& local_state_folder = local_state_folders[i]; | 413 LOG(ERROR) << "Failed to create temporary file for Local State."; |
| 414 base::FilePath state_file( | 414 else |
| 415 local_state_folder.Append(chrome::kLocalStateFilename)); | 415 base::CopyFile(state_file, backup); |
| 416 if (!base::PathExists(state_file)) | |
| 417 continue; | |
| 418 if (!base::CreateTemporaryFile(&backup)) | |
| 419 LOG(ERROR) << "Failed to create temporary file for Local State."; | |
| 420 else | |
| 421 base::CopyFile(state_file, backup); | |
| 422 break; | |
| 423 } | |
| 424 return backup; | 416 return backup; |
| 425 } | 417 } |
| 426 | 418 |
| 427 // Deletes all user data directories for a product. | 419 // Deletes a product's user data directory. |
| 428 DeleteResult DeleteLocalState( | 420 DeleteResult DeleteLocalState(const base::FilePath& local_state_folder, |
|
gab
2014/04/02 15:16:57
Why is this called DeleteLocalState if it deletes
grt (UTC plus 2)
2014/04/02 16:53:09
It deletes all locally-stored state (which happens
gab
2014/04/02 17:20:14
Yes that's what I meant, sorry for being unclear :
| |
| 429 const std::vector<base::FilePath>& local_state_folders, | 421 bool schedule_on_failure) { |
| 430 bool schedule_on_failure) { | 422 if (local_state_folder.empty()) |
| 431 if (local_state_folders.empty()) | |
| 432 return DELETE_SUCCEEDED; | 423 return DELETE_SUCCEEDED; |
| 433 | 424 |
| 434 DeleteResult result = DELETE_SUCCEEDED; | 425 DeleteResult result = DELETE_SUCCEEDED; |
| 435 for (size_t i = 0; i < local_state_folders.size(); ++i) { | 426 VLOG(1) << "Deleting user profile " << local_state_folder.value(); |
| 436 const base::FilePath& user_local_state = local_state_folders[i]; | 427 if (!base::DeleteFile(local_state_folder, true)) { |
| 437 VLOG(1) << "Deleting user profile " << user_local_state.value(); | 428 LOG(ERROR) << "Failed to delete user profile dir: " |
| 438 if (!base::DeleteFile(user_local_state, true)) { | 429 << local_state_folder.value(); |
| 439 LOG(ERROR) << "Failed to delete user profile dir: " | 430 if (schedule_on_failure) { |
| 440 << user_local_state.value(); | 431 ScheduleDirectoryForDeletion(local_state_folder); |
| 441 if (schedule_on_failure) { | 432 result = DELETE_REQUIRES_REBOOT; |
| 442 ScheduleDirectoryForDeletion(user_local_state); | 433 } else { |
| 443 result = DELETE_REQUIRES_REBOOT; | 434 result = DELETE_FAILED; |
| 444 } else { | |
| 445 result = DELETE_FAILED; | |
| 446 } | |
| 447 } | 435 } |
| 448 } | 436 } |
| 449 | 437 |
| 450 if (result == DELETE_REQUIRES_REBOOT) { | 438 if (result == DELETE_REQUIRES_REBOOT) { |
| 451 ScheduleParentAndGrandparentForDeletion(local_state_folders[0]); | 439 ScheduleParentAndGrandparentForDeletion(local_state_folder); |
| 452 } else { | 440 } else { |
| 453 const base::FilePath user_data_dir(local_state_folders[0].DirName()); | 441 const base::FilePath user_data_dir(local_state_folder.DirName()); |
| 454 if (!user_data_dir.empty() && | 442 if (!user_data_dir.empty() && |
| 455 DeleteEmptyDir(user_data_dir) == DELETE_SUCCEEDED) { | 443 DeleteEmptyDir(user_data_dir) == DELETE_SUCCEEDED) { |
| 456 const base::FilePath product_dir(user_data_dir.DirName()); | 444 const base::FilePath product_dir(user_data_dir.DirName()); |
| 457 if (!product_dir.empty()) | 445 if (!product_dir.empty()) |
| 458 DeleteEmptyDir(product_dir); | 446 DeleteEmptyDir(product_dir); |
| 459 } | 447 } |
| 460 } | 448 } |
| 461 | 449 |
| 462 return result; | 450 return result; |
| 463 } | 451 } |
| (...skipping 861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1325 | 1313 |
| 1326 // Finally delete all the files from Chrome folder after moving setup.exe | 1314 // Finally delete all the files from Chrome folder after moving setup.exe |
| 1327 // and the user's Local State to a temp location. | 1315 // and the user's Local State to a temp location. |
| 1328 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, | 1316 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, |
| 1329 product); | 1317 product); |
| 1330 ret = installer::UNINSTALL_SUCCESSFUL; | 1318 ret = installer::UNINSTALL_SUCCESSFUL; |
| 1331 | 1319 |
| 1332 // When deleting files, we must make sure that we're either a "single" | 1320 // When deleting files, we must make sure that we're either a "single" |
| 1333 // (aka non-multi) installation or we are the Chrome Binaries. | 1321 // (aka non-multi) installation or we are the Chrome Binaries. |
| 1334 | 1322 |
| 1335 std::vector<base::FilePath> local_state_folders; | 1323 base::FilePath local_state_folder(GetLocalStateFolder(product)); |
| 1336 GetLocalStateFolders(product, &local_state_folders); | 1324 base::FilePath backup_state_file(BackupLocalStateFile(local_state_folder)); |
| 1337 base::FilePath backup_state_file(BackupLocalStateFile(local_state_folders)); | |
| 1338 | 1325 |
| 1339 if (product.is_chrome_app_host()) { | 1326 if (product.is_chrome_app_host()) { |
| 1340 DeleteAppHostFilesAndFolders(installer_state, product_state->version()); | 1327 DeleteAppHostFilesAndFolders(installer_state, product_state->version()); |
| 1341 } else if (!installer_state.is_multi_install() || | 1328 } else if (!installer_state.is_multi_install() || |
| 1342 product.is_chrome_binaries()) { | 1329 product.is_chrome_binaries()) { |
| 1343 DeleteResult delete_result = DeleteChromeFilesAndFolders( | 1330 DeleteResult delete_result = DeleteChromeFilesAndFolders( |
| 1344 installer_state, base::MakeAbsoluteFilePath(setup_exe)); | 1331 installer_state, base::MakeAbsoluteFilePath(setup_exe)); |
| 1345 if (delete_result == DELETE_FAILED) { | 1332 if (delete_result == DELETE_FAILED) { |
| 1346 ret = installer::UNINSTALL_FAILED; | 1333 ret = installer::UNINSTALL_FAILED; |
| 1347 } else if (delete_result == DELETE_REQUIRES_REBOOT) { | 1334 } else if (delete_result == DELETE_REQUIRES_REBOOT) { |
| 1348 ret = installer::UNINSTALL_REQUIRES_REBOOT; | 1335 ret = installer::UNINSTALL_REQUIRES_REBOOT; |
| 1349 } | 1336 } |
| 1350 } | 1337 } |
| 1351 | 1338 |
| 1352 if (delete_profile) | 1339 if (delete_profile) |
| 1353 DeleteLocalState(local_state_folders, product.is_chrome_frame()); | 1340 DeleteLocalState(local_state_folder, product.is_chrome_frame()); |
| 1354 | 1341 |
| 1355 if (!force_uninstall) { | 1342 if (!force_uninstall) { |
| 1356 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; | 1343 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; |
| 1357 browser_dist->DoPostUninstallOperations(product_state->version(), | 1344 browser_dist->DoPostUninstallOperations(product_state->version(), |
| 1358 backup_state_file, distribution_data); | 1345 backup_state_file, distribution_data); |
| 1359 } | 1346 } |
| 1360 | 1347 |
| 1361 // Try and delete the preserved local state once the post-install | 1348 // Try and delete the preserved local state once the post-install |
| 1362 // operations are complete. | 1349 // operations are complete. |
| 1363 if (!backup_state_file.empty()) | 1350 if (!backup_state_file.empty()) |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1434 // If we need a reboot to continue, schedule the parent directories for | 1421 // If we need a reboot to continue, schedule the parent directories for |
| 1435 // deletion unconditionally. If they are not empty, the session manager | 1422 // deletion unconditionally. If they are not empty, the session manager |
| 1436 // will not delete them on reboot. | 1423 // will not delete them on reboot. |
| 1437 ScheduleParentAndGrandparentForDeletion(target_path); | 1424 ScheduleParentAndGrandparentForDeletion(target_path); |
| 1438 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { | 1425 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { |
| 1439 *uninstall_status = UNINSTALL_FAILED; | 1426 *uninstall_status = UNINSTALL_FAILED; |
| 1440 } | 1427 } |
| 1441 } | 1428 } |
| 1442 | 1429 |
| 1443 } // namespace installer | 1430 } // namespace installer |
| OLD | NEW |