Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: chrome/installer/setup/uninstall.cc

Issue 10826144: Delete both regular and Metro user data dirs on uninstall. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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) {
gab 2012/08/03 17:54:20 Is it ok if the Metro directory comes out of this?
grt (UTC plus 2) 2012/08/03 20:18:37 Yes. Ideally, we'd aggregate the metrics from bot
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;
gab 2012/08/03 17:54:20 I think this should be: { NOTREACHED(); return
grt (UTC plus 2) 2012/08/03 20:18:37 I added a DCHECK to GetChromeUserDataPaths() rathe
gab 2012/08/03 20:42:41 Yes, but I still think the return statement here s
grt (UTC plus 2) 2012/08/03 20:56:34 hmm. i disagree (although it's purely academic si
gab 2012/08/03 21:58:57 Ah ok I see your point, given the returned value i
grt (UTC plus 2) 2012/08/04 19:25:20 After more thought, I like this as-is. The fact t
gab 2012/08/05 06:27:39 sgtm
375 381
376 DeleteResult result = DELETE_SUCCEEDED; 382 DeleteResult result = DELETE_SUCCEEDED;
377 VLOG(1) << "Deleting user profile " << user_local_state.value(); 383 const FilePath *user_local_state = NULL;
gab 2012/08/03 17:54:20 Move this in the for loop (see comment below as to
grt (UTC plus 2) 2012/08/03 20:18:37 Done.
378 if (!file_util::Delete(user_local_state, true)) { 384 for (size_t i = 0; i < local_state_folders.size(); ++i) {
379 LOG(ERROR) << "Failed to delete user profile dir: " 385 user_local_state = &local_state_folders[i];
380 << user_local_state.value(); 386 VLOG(1) << "Deleting user profile " << user_local_state->value();
381 if (product.is_chrome_frame()) { 387 if (!file_util::Delete(*user_local_state, true)) {
382 ScheduleDirectoryForDeletion(user_local_state.value().c_str()); 388 LOG(ERROR) << "Failed to delete user profile dir: "
383 result = DELETE_REQUIRES_REBOOT; 389 << user_local_state->value();
384 } else { 390 if (schedule_on_failure) {
385 result = DELETE_FAILED; 391 ScheduleDirectoryForDeletion(user_local_state->value().c_str());
392 result = DELETE_REQUIRES_REBOOT;
393 } else {
394 result = DELETE_FAILED;
395 }
386 } 396 }
387 } 397 }
388 398
389 if (result == DELETE_REQUIRES_REBOOT) { 399 if (user_local_state) {
gab 2012/08/03 17:54:20 This check is unnecessary given you only proceed i
grt (UTC plus 2) 2012/08/03 20:18:37 Done.
390 ScheduleParentAndGrandparentForDeletion(user_local_state); 400 if (result == DELETE_REQUIRES_REBOOT) {
391 } else { 401 ScheduleParentAndGrandparentForDeletion(*user_local_state);
gab 2012/08/03 17:54:20 You can use local_state_folders[0] here instead (g
grt (UTC plus 2) 2012/08/03 20:18:37 Done.
392 DeleteEmptyParentDir(user_local_state); 402 } else {
403 DeleteEmptyParentDir(*user_local_state);
404 }
393 } 405 }
394 406
395 return result; 407 return result;
396 } 408 }
397 409
398 bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state, 410 bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state,
399 const FilePath& setup_path, 411 const FilePath& setup_path,
400 const Version& installed_version) { 412 const Version& installed_version) {
401 bool ret = false; 413 bool ret = false;
402 FilePath setup_exe(installer_state.GetInstallerDirectory(installed_version) 414 FilePath setup_exe(installer_state.GetInstallerDirectory(installed_version)
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 1106
1095 // Finally delete all the files from Chrome folder after moving setup.exe 1107 // Finally delete all the files from Chrome folder after moving setup.exe
1096 // and the user's Local State to a temp location. 1108 // and the user's Local State to a temp location.
1097 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, 1109 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status,
1098 product); 1110 product);
1099 ret = installer::UNINSTALL_SUCCESSFUL; 1111 ret = installer::UNINSTALL_SUCCESSFUL;
1100 1112
1101 // When deleting files, we must make sure that we're either a "single" 1113 // When deleting files, we must make sure that we're either a "single"
1102 // (aka non-multi) installation or we are the Chrome Binaries. 1114 // (aka non-multi) installation or we are the Chrome Binaries.
1103 1115
1104 FilePath backup_state_file( 1116 std::vector<FilePath> local_state_folders;
1105 BackupLocalStateFile(GetLocalStateFolder(product))); 1117 GetLocalStateFolders(product, &local_state_folders);
1118 FilePath backup_state_file(BackupLocalStateFile(local_state_folders));
1106 1119
1107 DeleteResult delete_result = DELETE_SUCCEEDED; 1120 DeleteResult delete_result = DELETE_SUCCEEDED;
1108 1121
1109 if (product.is_chrome_app_host()) { 1122 if (product.is_chrome_app_host()) {
1110 DeleteAppHostFilesAndFolders(installer_state, product_state->version()); 1123 DeleteAppHostFilesAndFolders(installer_state, product_state->version());
1111 } else if (!installer_state.is_multi_install() || 1124 } else if (!installer_state.is_multi_install() ||
1112 product.is_chrome_binaries()) { 1125 product.is_chrome_binaries()) {
1113 1126
1114 // In order to be able to remove the folder in which we're running, we 1127 // 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. 1128 // need to move setup.exe out of the install folder.
1116 // TODO(tommi): What if the temp folder is on a different volume? 1129 // TODO(tommi): What if the temp folder is on a different volume?
1117 MoveSetupOutOfInstallFolder(installer_state, setup_path, 1130 MoveSetupOutOfInstallFolder(installer_state, setup_path,
1118 product_state->version()); 1131 product_state->version());
1119 delete_result = DeleteChromeFilesAndFolders(installer_state, 1132 delete_result = DeleteChromeFilesAndFolders(installer_state,
1120 product_state->version()); 1133 product_state->version());
1121 } 1134 }
1122 1135
1123 if (delete_profile) 1136 if (delete_profile)
1124 DeleteLocalState(product); 1137 DeleteLocalState(local_state_folders, product.is_chrome_frame());
1125 1138
1126 if (delete_result == DELETE_FAILED) { 1139 if (delete_result == DELETE_FAILED) {
1127 ret = installer::UNINSTALL_FAILED; 1140 ret = installer::UNINSTALL_FAILED;
1128 } else if (delete_result == DELETE_REQUIRES_REBOOT) { 1141 } else if (delete_result == DELETE_REQUIRES_REBOOT) {
1129 ret = installer::UNINSTALL_REQUIRES_REBOOT; 1142 ret = installer::UNINSTALL_REQUIRES_REBOOT;
1130 } 1143 }
1131 1144
1132 if (!force_uninstall) { 1145 if (!force_uninstall) {
1133 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; 1146 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations.";
1134 browser_dist->DoPostUninstallOperations(product_state->version(), 1147 browser_dist->DoPostUninstallOperations(product_state->version(),
1135 backup_state_file, distribution_data); 1148 backup_state_file, distribution_data);
1136 } 1149 }
1137 1150
1138 // Try and delete the preserved local state once the post-install 1151 // Try and delete the preserved local state once the post-install
1139 // operations are complete. 1152 // operations are complete.
1140 if (!backup_state_file.empty()) 1153 if (!backup_state_file.empty())
1141 file_util::Delete(backup_state_file, false); 1154 file_util::Delete(backup_state_file, false);
1142 1155
1143 return ret; 1156 return ret;
1144 } 1157 }
1145 1158
1146 } // namespace installer 1159 } // namespace installer
OLDNEW
« no previous file with comments | « no previous file | chrome/installer/util/auto_launch_util.cc » ('j') | chrome/installer/util/helper.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698