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 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
311 FilePath grandparent_dir(parent_dir.DirName()); | 311 FilePath grandparent_dir(parent_dir.DirName()); |
312 ret = ScheduleFileSystemEntityForDeletion(grandparent_dir.value().c_str()); | 312 ret = ScheduleFileSystemEntityForDeletion(grandparent_dir.value().c_str()); |
313 if (!ret) { | 313 if (!ret) { |
314 LOG(ERROR) << "Failed to schedule grandparent dir for deletion: " | 314 LOG(ERROR) << "Failed to schedule grandparent dir for deletion: " |
315 << grandparent_dir.value(); | 315 << grandparent_dir.value(); |
316 } | 316 } |
317 } | 317 } |
318 return ret; | 318 return ret; |
319 } | 319 } |
320 | 320 |
321 // Deletes empty parent & empty grandparent dir of given path. | 321 // Deletes the given directory if it is empty. Returns true if the directory is |
322 bool DeleteEmptyParentDir(const FilePath& path) { | 322 // deleted. *error is set to true iff the attempt to delete the file fails. |
323 bool ret = true; | 323 bool DeleteEmptyDir(const FilePath& path, bool* error) { |
gab
2012/08/09 16:07:22
I'm not a fan of the bool return and bool* error p
erikwright (departed)
2012/08/13 14:53:22
Done.
| |
324 FilePath parent_dir = path.DirName(); | 324 *error = false; |
325 if (!parent_dir.empty() && file_util::IsDirectoryEmpty(parent_dir)) { | |
326 if (!file_util::Delete(parent_dir, true)) { | |
327 ret = false; | |
328 LOG(ERROR) << "Failed to delete folder: " << parent_dir.value(); | |
329 } | |
330 | 325 |
331 parent_dir = parent_dir.DirName(); | 326 if (path.empty()) |
332 if (!parent_dir.empty() && file_util::IsDirectoryEmpty(parent_dir)) { | 327 return false; |
333 if (!file_util::Delete(parent_dir, true)) { | 328 |
334 ret = false; | 329 if (!file_util::IsDirectoryEmpty(path)) |
gab
2012/08/09 16:07:22
Group this condition with path.empty() above since
erikwright (departed)
2012/08/13 14:53:22
N/A.
| |
335 LOG(ERROR) << "Failed to delete folder: " << parent_dir.value(); | 330 return false; |
336 } | 331 |
337 } | 332 if (file_util::Delete(path, true)) |
338 } | 333 return true; |
339 return ret; | 334 |
335 *error = true; | |
336 LOG(ERROR) << "Failed to delete folder: " << path.value(); | |
337 return false; | |
340 } | 338 } |
341 | 339 |
342 void GetLocalStateFolders(const Product& product, | 340 void GetLocalStateFolders(const Product& product, |
343 std::vector<FilePath>* paths) { | 341 std::vector<FilePath>* paths) { |
344 // Obtain the location of the user profile data. | 342 // Obtain the location of the user profile data. |
345 product.GetUserDataPaths(paths); | 343 product.GetUserDataPaths(paths); |
346 LOG_IF(ERROR, paths->empty()) | 344 LOG_IF(ERROR, paths->empty()) |
347 << "Could not retrieve user's profile directory."; | 345 << "Could not retrieve user's profile directory."; |
348 } | 346 } |
349 | 347 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
391 result = DELETE_REQUIRES_REBOOT; | 389 result = DELETE_REQUIRES_REBOOT; |
392 } else { | 390 } else { |
393 result = DELETE_FAILED; | 391 result = DELETE_FAILED; |
394 } | 392 } |
395 } | 393 } |
396 } | 394 } |
397 | 395 |
398 if (result == DELETE_REQUIRES_REBOOT) { | 396 if (result == DELETE_REQUIRES_REBOOT) { |
399 ScheduleParentAndGrandparentForDeletion(local_state_folders[0]); | 397 ScheduleParentAndGrandparentForDeletion(local_state_folders[0]); |
400 } else { | 398 } else { |
401 DeleteEmptyParentDir(local_state_folders[0]); | 399 bool error = false; |
400 if (DeleteEmptyDir(local_state_folders[0].DirName(), &error)) | |
401 DeleteEmptyDir(local_state_folders[0].DirName().DirName(), &error); | |
402 } | 402 } |
403 | 403 |
404 return result; | 404 return result; |
405 } | 405 } |
406 | 406 |
407 bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state, | 407 bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state, |
408 const FilePath& setup_path, | 408 const FilePath& setup_path, |
409 const Version& installed_version) { | 409 const Version& installed_version) { |
410 bool ret = false; | 410 bool ret = false; |
411 FilePath setup_exe(installer_state.GetInstallerDirectory(installed_version) | 411 FilePath setup_exe(installer_state.GetInstallerDirectory(installed_version) |
(...skipping 27 matching lines...) Expand all Loading... | |
439 | 439 |
440 DeleteInstallTempDir(target_path); | 440 DeleteInstallTempDir(target_path); |
441 | 441 |
442 DeleteResult result = DELETE_SUCCEEDED; | 442 DeleteResult result = DELETE_SUCCEEDED; |
443 | 443 |
444 FilePath app_host_exe(target_path.Append(installer::kChromeAppHostExe)); | 444 FilePath app_host_exe(target_path.Append(installer::kChromeAppHostExe)); |
445 if (!file_util::Delete(app_host_exe, false)) { | 445 if (!file_util::Delete(app_host_exe, false)) { |
446 result = DELETE_FAILED; | 446 result = DELETE_FAILED; |
447 LOG(ERROR) << "Failed to delete path: " << app_host_exe.value(); | 447 LOG(ERROR) << "Failed to delete path: " << app_host_exe.value(); |
448 } else { | 448 } else { |
449 DeleteEmptyParentDir(target_path); | 449 bool error = false; |
450 if (DeleteEmptyDir(target_path, &error)) { | |
451 // Now check and delete if the parent directories are empty | |
452 // For example Google\Chrome or Chromium | |
453 if (DeleteEmptyDir(target_path.DirName(), &error)) | |
454 DeleteEmptyDir(target_path.DirName().DirName(), &error); | |
455 } | |
456 if (error) | |
457 result = DELETE_FAILED; | |
450 } | 458 } |
451 | 459 |
452 return result; | 460 return result; |
453 } | 461 } |
454 | 462 |
455 DeleteResult DeleteChromeFilesAndFolders(const InstallerState& installer_state, | 463 DeleteResult DeleteChromeFilesAndFolders(const InstallerState& installer_state, |
456 const Version& installed_version) { | 464 const Version& installed_version) { |
457 const FilePath& target_path = installer_state.target_path(); | 465 const FilePath& target_path = installer_state.target_path(); |
458 if (target_path.empty()) { | 466 if (target_path.empty()) { |
459 LOG(ERROR) << "DeleteChromeFilesAndFolders: no installation destination " | 467 LOG(ERROR) << "DeleteChromeFilesAndFolders: no installation destination " |
(...skipping 11 matching lines...) Expand all Loading... | |
471 false, | 479 false, |
472 static_cast<FileEnumerator::FileType>(FileEnumerator::FILES | | 480 static_cast<FileEnumerator::FileType>(FileEnumerator::FILES | |
473 FileEnumerator::DIRECTORIES)); | 481 FileEnumerator::DIRECTORIES)); |
474 while (true) { | 482 while (true) { |
475 FilePath to_delete(file_enumerator.Next()); | 483 FilePath to_delete(file_enumerator.Next()); |
476 if (to_delete.empty()) | 484 if (to_delete.empty()) |
477 break; | 485 break; |
478 if (to_delete.BaseName().value() == installer::kChromeAppHostExe) | 486 if (to_delete.BaseName().value() == installer::kChromeAppHostExe) |
479 continue; | 487 continue; |
480 | 488 |
481 VLOG(1) << "Deleting install path " << target_path.value(); | 489 VLOG(1) << "Deleting install path " << to_delete.value(); |
482 if (!file_util::Delete(to_delete, true)) { | 490 if (!file_util::Delete(to_delete, true)) { |
483 LOG(ERROR) << "Failed to delete path (1st try): " << to_delete.value(); | 491 LOG(ERROR) << "Failed to delete path (1st try): " << to_delete.value(); |
484 if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) { | 492 if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) { |
485 // We don't try killing Chrome processes for Chrome Frame builds since | 493 // We don't try killing Chrome processes for Chrome Frame builds since |
486 // that is unlikely to help. Instead, schedule files for deletion and | 494 // that is unlikely to help. Instead, schedule files for deletion and |
487 // return a value that will trigger a reboot prompt. | 495 // return a value that will trigger a reboot prompt. |
488 FileEnumerator::FindInfo find_info; | 496 FileEnumerator::FindInfo find_info; |
489 file_enumerator.GetFindInfo(&find_info); | 497 file_enumerator.GetFindInfo(&find_info); |
490 if (FileEnumerator::IsDirectory(find_info)) | 498 if (FileEnumerator::IsDirectory(find_info)) |
491 ScheduleDirectoryForDeletion(to_delete.value().c_str()); | 499 ScheduleDirectoryForDeletion(to_delete.value().c_str()); |
492 else | 500 else |
493 ScheduleFileSystemEntityForDeletion(to_delete.value().c_str()); | 501 ScheduleFileSystemEntityForDeletion(to_delete.value().c_str()); |
494 result = DELETE_REQUIRES_REBOOT; | 502 result = DELETE_REQUIRES_REBOOT; |
495 } else { | 503 } else { |
496 // Try closing any running Chrome processes and deleting files once | 504 // Try closing any running Chrome processes and deleting files once |
497 // again. | 505 // again. |
498 CloseAllChromeProcesses(); | 506 CloseAllChromeProcesses(); |
499 if (!file_util::Delete(to_delete, true)) { | 507 if (!file_util::Delete(to_delete, true)) { |
500 LOG(ERROR) << "Failed to delete path (2nd try): " | 508 LOG(ERROR) << "Failed to delete path (2nd try): " |
501 << to_delete.value(); | 509 << to_delete.value(); |
502 result = DELETE_FAILED; | 510 result = DELETE_FAILED; |
503 break; | 511 break; |
504 } | 512 } |
505 } | 513 } |
506 } | 514 } |
507 } | 515 } |
508 | 516 |
509 if (result == DELETE_REQUIRES_REBOOT) { | 517 if (result == DELETE_REQUIRES_REBOOT) { |
518 // Delete the Application directory at reboot if empty. | |
519 ScheduleFileSystemEntityForDeletion(target_path.value().c_str()); | |
520 | |
510 // If we need a reboot to continue, schedule the parent directories for | 521 // If we need a reboot to continue, schedule the parent directories for |
511 // deletion unconditionally. If they are not empty, the session manager | 522 // deletion unconditionally. If they are not empty, the session manager |
512 // will not delete them on reboot. | 523 // will not delete them on reboot. |
513 ScheduleParentAndGrandparentForDeletion(target_path); | 524 ScheduleParentAndGrandparentForDeletion(target_path); |
514 } else { | 525 } else { |
515 // Now check and delete if the parent directories are empty | 526 bool error = false; |
516 // For example Google\Chrome or Chromium | 527 if (DeleteEmptyDir(target_path, &error)) { |
517 DeleteEmptyParentDir(target_path); | 528 // Now check and delete if the parent directories are empty |
529 // For example Google\Chrome or Chromium | |
530 if (DeleteEmptyDir(target_path.DirName(), &error)) | |
531 DeleteEmptyDir(target_path.DirName().DirName(), &error); | |
532 } | |
533 if (error) | |
534 result = DELETE_FAILED; | |
518 } | 535 } |
519 return result; | 536 return result; |
520 } | 537 } |
521 | 538 |
522 // This method checks if Chrome is currently running or if the user has | 539 // This method checks if Chrome is currently running or if the user has |
523 // cancelled the uninstall operation by clicking Cancel on the confirmation | 540 // cancelled the uninstall operation by clicking Cancel on the confirmation |
524 // box that Chrome pops up. | 541 // box that Chrome pops up. |
525 InstallStatus IsChromeActiveOrUserCancelled( | 542 InstallStatus IsChromeActiveOrUserCancelled( |
526 const InstallerState& installer_state, | 543 const InstallerState& installer_state, |
527 const Product& product) { | 544 const Product& product) { |
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1161 | 1178 |
1162 // Try and delete the preserved local state once the post-install | 1179 // Try and delete the preserved local state once the post-install |
1163 // operations are complete. | 1180 // operations are complete. |
1164 if (!backup_state_file.empty()) | 1181 if (!backup_state_file.empty()) |
1165 file_util::Delete(backup_state_file, false); | 1182 file_util::Delete(backup_state_file, false); |
1166 | 1183 |
1167 return ret; | 1184 return ret; |
1168 } | 1185 } |
1169 | 1186 |
1170 } // namespace installer | 1187 } // namespace installer |
OLD | NEW |