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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 43 #include "chrome/installer/util/installer_state.h" | 43 #include "chrome/installer/util/installer_state.h" |
| 44 #include "chrome/installer/util/logging_installer.h" | 44 #include "chrome/installer/util/logging_installer.h" |
| 45 #include "chrome/installer/util/self_cleaning_temp_dir.h" | 45 #include "chrome/installer/util/self_cleaning_temp_dir.h" |
| 46 #include "chrome/installer/util/shell_util.h" | 46 #include "chrome/installer/util/shell_util.h" |
| 47 #include "chrome/installer/util/util_constants.h" | 47 #include "chrome/installer/util/util_constants.h" |
| 48 #include "content/public/common/result_codes.h" | 48 #include "content/public/common/result_codes.h" |
| 49 #include "extensions/common/constants.h" | 49 #include "extensions/common/constants.h" |
| 50 #include "rlz/lib/rlz_lib.h" | 50 #include "rlz/lib/rlz_lib.h" |
| 51 | 51 |
| 52 using base::win::RegKey; | 52 using base::win::RegKey; |
| 53 using installer::InstallStatus; | 53 |
| 54 using installer::MasterPreferences; | 54 namespace installer { |
|
grt (UTC plus 2)
2014/04/02 16:53:10
In patch set 2, I've moved all private functions i
gab
2014/04/02 17:20:14
Sounds good, I assume the code didn't change (didn
| |
| 55 | 55 |
| 56 namespace { | 56 namespace { |
| 57 | 57 |
| 58 // Avoid leaving behind a Temp dir. If one exists, ask SelfCleaningTempDir to | 58 // Avoid leaving behind a Temp dir. If one exists, ask SelfCleaningTempDir to |
| 59 // clean it up for us. This may involve scheduling it for deletion after | 59 // clean it up for us. This may involve scheduling it for deletion after |
| 60 // reboot. Don't report that a reboot is required in this case, however. | 60 // reboot. Don't report that a reboot is required in this case, however. |
| 61 // TODO(erikwright): Shouldn't this still lead to | 61 // TODO(erikwright): Shouldn't this still lead to |
| 62 // ScheduleParentAndGrandparentForDeletion? | 62 // ScheduleParentAndGrandparentForDeletion? |
| 63 void DeleteInstallTempDir(const base::FilePath& target_path) { | 63 void DeleteInstallTempDir(const base::FilePath& target_path) { |
| 64 base::FilePath temp_path(target_path.DirName().Append( | 64 base::FilePath temp_path(target_path.DirName().Append( |
| 65 installer::kInstallTempDir)); | 65 installer::kInstallTempDir)); |
| 66 if (base::DirectoryExists(temp_path)) { | 66 if (base::DirectoryExists(temp_path)) { |
| 67 installer::SelfCleaningTempDir temp_dir; | 67 SelfCleaningTempDir temp_dir; |
| 68 if (!temp_dir.Initialize(target_path.DirName(), | 68 if (!temp_dir.Initialize(target_path.DirName(), |
| 69 installer::kInstallTempDir) || | 69 installer::kInstallTempDir) || |
| 70 !temp_dir.Delete()) { | 70 !temp_dir.Delete()) { |
| 71 LOG(ERROR) << "Failed to delete temp dir " << temp_path.value(); | 71 LOG(ERROR) << "Failed to delete temp dir " << temp_path.value(); |
| 72 } | 72 } |
| 73 } | 73 } |
| 74 } | 74 } |
| 75 | 75 |
| 76 // Iterates over the list of distribution types in |dist_types|, and | 76 // Iterates over the list of distribution types in |dist_types|, and |
| 77 // adds to |update_list| the work item to update the corresponding "ap" | 77 // adds to |update_list| the work item to update the corresponding "ap" |
| 78 // registry value specified in |channel_info|. | 78 // registry value specified in |channel_info|. |
| 79 void AddChannelValueUpdateWorkItems( | 79 void AddChannelValueUpdateWorkItems( |
| 80 const installer::InstallationState& original_state, | 80 const InstallationState& original_state, |
| 81 const installer::InstallerState& installer_state, | 81 const InstallerState& installer_state, |
| 82 const installer::ChannelInfo& channel_info, | 82 const ChannelInfo& channel_info, |
| 83 const std::vector<BrowserDistribution::Type>& dist_types, | 83 const std::vector<BrowserDistribution::Type>& dist_types, |
| 84 WorkItemList* update_list) { | 84 WorkItemList* update_list) { |
| 85 const bool system_level = installer_state.system_install(); | 85 const bool system_level = installer_state.system_install(); |
| 86 const HKEY reg_root = installer_state.root_key(); | 86 const HKEY reg_root = installer_state.root_key(); |
| 87 for (size_t i = 0; i < dist_types.size(); ++i) { | 87 for (size_t i = 0; i < dist_types.size(); ++i) { |
| 88 BrowserDistribution::Type dist_type = dist_types[i]; | 88 BrowserDistribution::Type dist_type = dist_types[i]; |
| 89 const installer::ProductState* product_state = | 89 const ProductState* product_state = |
| 90 original_state.GetProductState(system_level, dist_type); | 90 original_state.GetProductState(system_level, dist_type); |
| 91 // Only modify other products if they're installed and multi. | 91 // Only modify other products if they're installed and multi. |
| 92 if (product_state != NULL && | 92 if (product_state != NULL && |
| 93 product_state->is_multi_install() && | 93 product_state->is_multi_install() && |
| 94 !product_state->channel().Equals(channel_info)) { | 94 !product_state->channel().Equals(channel_info)) { |
| 95 BrowserDistribution* other_dist = | 95 BrowserDistribution* other_dist = |
| 96 BrowserDistribution::GetSpecificDistribution(dist_type); | 96 BrowserDistribution::GetSpecificDistribution(dist_type); |
| 97 update_list->AddSetRegValueWorkItem(reg_root, other_dist->GetStateKey(), | 97 update_list->AddSetRegValueWorkItem(reg_root, other_dist->GetStateKey(), |
| 98 google_update::kRegApField, channel_info.value(), true); | 98 google_update::kRegApField, channel_info.value(), true); |
| 99 } else { | 99 } else { |
| 100 LOG_IF(ERROR, | 100 LOG_IF(ERROR, |
| 101 product_state != NULL && product_state->is_multi_install()) | 101 product_state != NULL && product_state->is_multi_install()) |
| 102 << "Channel value for " | 102 << "Channel value for " |
| 103 << BrowserDistribution::GetSpecificDistribution( | 103 << BrowserDistribution::GetSpecificDistribution( |
| 104 dist_type)->GetDisplayName() | 104 dist_type)->GetDisplayName() |
| 105 << " is somehow already set to the desired new value of " | 105 << " is somehow already set to the desired new value of " |
| 106 << channel_info.value(); | 106 << channel_info.value(); |
| 107 } | 107 } |
| 108 } | 108 } |
| 109 } | 109 } |
| 110 | 110 |
| 111 // Makes appropriate changes to the Google Update "ap" value in the registry. | 111 // Makes appropriate changes to the Google Update "ap" value in the registry. |
| 112 // Specifically, removes the flags associated with this product ("-chrome" or | 112 // Specifically, removes the flags associated with this product ("-chrome" or |
| 113 // "-chromeframe") from the "ap" values for all other installed products and for | 113 // "-chromeframe") from the "ap" values for all other installed products and for |
| 114 // the multi-installer package. | 114 // the multi-installer package. |
| 115 void ProcessGoogleUpdateItems( | 115 void ProcessGoogleUpdateItems(const InstallationState& original_state, |
| 116 const installer::InstallationState& original_state, | 116 const InstallerState& installer_state, |
| 117 const installer::InstallerState& installer_state, | 117 const Product& product) { |
| 118 const installer::Product& product) { | |
| 119 DCHECK(installer_state.is_multi_install()); | 118 DCHECK(installer_state.is_multi_install()); |
| 120 const bool system_level = installer_state.system_install(); | 119 const bool system_level = installer_state.system_install(); |
| 121 BrowserDistribution* distribution = product.distribution(); | 120 BrowserDistribution* distribution = product.distribution(); |
| 122 const installer::ProductState* product_state = | 121 const ProductState* product_state = |
| 123 original_state.GetProductState(system_level, distribution->GetType()); | 122 original_state.GetProductState(system_level, distribution->GetType()); |
| 124 DCHECK(product_state != NULL); | 123 DCHECK(product_state != NULL); |
| 125 installer::ChannelInfo channel_info; | 124 ChannelInfo channel_info; |
| 126 | 125 |
| 127 // Remove product's flags from the channel value. | 126 // Remove product's flags from the channel value. |
| 128 channel_info.set_value(product_state->channel().value()); | 127 channel_info.set_value(product_state->channel().value()); |
| 129 const bool modified = product.SetChannelFlags(false, &channel_info); | 128 const bool modified = product.SetChannelFlags(false, &channel_info); |
| 130 | 129 |
| 131 // Apply the new channel value to all other products and to the multi package. | 130 // Apply the new channel value to all other products and to the multi package. |
| 132 if (modified) { | 131 if (modified) { |
| 133 scoped_ptr<WorkItemList> | 132 scoped_ptr<WorkItemList> |
| 134 update_list(WorkItem::CreateNoRollbackWorkItemList()); | 133 update_list(WorkItem::CreateNoRollbackWorkItemList()); |
| 135 std::vector<BrowserDistribution::Type> dist_types; | 134 std::vector<BrowserDistribution::Type> dist_types; |
| 136 for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { | 135 for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { |
| 137 BrowserDistribution::Type other_dist_type = | 136 BrowserDistribution::Type other_dist_type = |
| 138 static_cast<BrowserDistribution::Type>(i); | 137 static_cast<BrowserDistribution::Type>(i); |
| 139 if (distribution->GetType() != other_dist_type) | 138 if (distribution->GetType() != other_dist_type) |
| 140 dist_types.push_back(other_dist_type); | 139 dist_types.push_back(other_dist_type); |
| 141 } | 140 } |
| 142 AddChannelValueUpdateWorkItems(original_state, installer_state, | 141 AddChannelValueUpdateWorkItems(original_state, installer_state, |
| 143 channel_info, dist_types, | 142 channel_info, dist_types, |
| 144 update_list.get()); | 143 update_list.get()); |
| 145 bool success = update_list->Do(); | 144 bool success = update_list->Do(); |
| 146 LOG_IF(ERROR, !success) << "Failed updating channel values."; | 145 LOG_IF(ERROR, !success) << "Failed updating channel values."; |
| 147 } | 146 } |
| 148 } | 147 } |
| 149 | 148 |
| 150 void ProcessOnOsUpgradeWorkItems( | 149 void ProcessOnOsUpgradeWorkItems(const InstallerState& installer_state, |
| 151 const installer::InstallerState& installer_state, | 150 const Product& product) { |
| 152 const installer::Product& product) { | |
| 153 scoped_ptr<WorkItemList> work_item_list( | 151 scoped_ptr<WorkItemList> work_item_list( |
| 154 WorkItem::CreateNoRollbackWorkItemList()); | 152 WorkItem::CreateNoRollbackWorkItemList()); |
| 155 AddOsUpgradeWorkItems(installer_state, base::FilePath(), Version(), product, | 153 AddOsUpgradeWorkItems(installer_state, base::FilePath(), Version(), product, |
| 156 work_item_list.get()); | 154 work_item_list.get()); |
| 157 if (!work_item_list->Do()) | 155 if (!work_item_list->Do()) |
| 158 LOG(ERROR) << "Failed to remove on-os-upgrade command."; | 156 LOG(ERROR) << "Failed to remove on-os-upgrade command."; |
| 159 } | 157 } |
| 160 | 158 |
| 161 void ProcessIELowRightsPolicyWorkItems( | 159 void ProcessIELowRightsPolicyWorkItems(const InstallerState& installer_state) { |
| 162 const installer::InstallerState& installer_state) { | |
| 163 scoped_ptr<WorkItemList> work_items(WorkItem::CreateNoRollbackWorkItemList()); | 160 scoped_ptr<WorkItemList> work_items(WorkItem::CreateNoRollbackWorkItemList()); |
| 164 AddDeleteOldIELowRightsPolicyWorkItems(installer_state, work_items.get()); | 161 AddDeleteOldIELowRightsPolicyWorkItems(installer_state, work_items.get()); |
| 165 work_items->Do(); | 162 work_items->Do(); |
| 166 installer::RefreshElevationPolicy(); | 163 RefreshElevationPolicy(); |
| 167 } | 164 } |
| 168 | 165 |
| 169 void ClearRlzProductState() { | 166 void ClearRlzProductState() { |
| 170 const rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX, | 167 const rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX, |
| 171 rlz_lib::CHROME_HOME_PAGE, | 168 rlz_lib::CHROME_HOME_PAGE, |
| 172 rlz_lib::NO_ACCESS_POINT}; | 169 rlz_lib::NO_ACCESS_POINT}; |
| 173 | 170 |
| 174 rlz_lib::ClearProductState(rlz_lib::CHROME, points); | 171 rlz_lib::ClearProductState(rlz_lib::CHROME, points); |
| 175 | 172 |
| 176 // If chrome has been reactivated, clear all events for this brand as well. | 173 // If chrome has been reactivated, clear all events for this brand as well. |
| 177 base::string16 reactivation_brand_wide; | 174 base::string16 reactivation_brand_wide; |
| 178 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand_wide)) { | 175 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand_wide)) { |
| 179 std::string reactivation_brand(base::UTF16ToASCII(reactivation_brand_wide)); | 176 std::string reactivation_brand(base::UTF16ToASCII(reactivation_brand_wide)); |
| 180 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str()); | 177 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str()); |
| 181 rlz_lib::ClearProductState(rlz_lib::CHROME, points); | 178 rlz_lib::ClearProductState(rlz_lib::CHROME, points); |
| 182 } | 179 } |
| 183 } | 180 } |
| 184 | 181 |
| 185 // Decides whether setup.exe and the installer archive should be removed based | 182 // Decides whether setup.exe and the installer archive should be removed based |
| 186 // on the original and installer states: | 183 // on the original and installer states: |
| 187 // * non-multi product being uninstalled: remove both | 184 // * non-multi product being uninstalled: remove both |
| 188 // * any multi product left besides App Host: keep both | 185 // * any multi product left besides App Host: keep both |
| 189 // * only App Host left: keep setup.exe | 186 // * only App Host left: keep setup.exe |
| 190 void CheckShouldRemoveSetupAndArchive( | 187 void CheckShouldRemoveSetupAndArchive(const InstallationState& original_state, |
| 191 const installer::InstallationState& original_state, | 188 const InstallerState& installer_state, |
| 192 const installer::InstallerState& installer_state, | 189 bool* remove_setup, |
| 193 bool* remove_setup, | 190 bool* remove_archive) { |
| 194 bool* remove_archive) { | |
| 195 *remove_setup = true; | 191 *remove_setup = true; |
| 196 *remove_archive = true; | 192 *remove_archive = true; |
| 197 | 193 |
| 198 // If any multi-install product is left (other than App Host) we must leave | 194 // If any multi-install product is left (other than App Host) we must leave |
| 199 // the installer and archive. For the App Host, we only leave the installer. | 195 // the installer and archive. For the App Host, we only leave the installer. |
| 200 if (!installer_state.is_multi_install()) { | 196 if (!installer_state.is_multi_install()) { |
| 201 VLOG(1) << "Removing all installer files for a non-multi installation."; | 197 VLOG(1) << "Removing all installer files for a non-multi installation."; |
| 202 } else { | 198 } else { |
| 203 // Loop through all known products... | 199 // Loop through all known products... |
| 204 for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { | 200 for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { |
| 205 BrowserDistribution::Type dist_type = | 201 BrowserDistribution::Type dist_type = |
| 206 static_cast<BrowserDistribution::Type>(i); | 202 static_cast<BrowserDistribution::Type>(i); |
| 207 const installer::ProductState* product_state = | 203 const ProductState* product_state = original_state.GetProductState( |
| 208 original_state.GetProductState( | 204 installer_state.system_install(), dist_type); |
| 209 installer_state.system_install(), dist_type); | |
| 210 // If the product is installed, in multi mode, and is not part of the | 205 // If the product is installed, in multi mode, and is not part of the |
| 211 // active uninstallation... | 206 // active uninstallation... |
| 212 if (product_state && product_state->is_multi_install() && | 207 if (product_state && product_state->is_multi_install() && |
| 213 !installer_state.FindProduct(dist_type)) { | 208 !installer_state.FindProduct(dist_type)) { |
| 214 // setup.exe will not be removed as there is a remaining multi-install | 209 // setup.exe will not be removed as there is a remaining multi-install |
| 215 // product. | 210 // product. |
| 216 *remove_setup = false; | 211 *remove_setup = false; |
| 217 // As a special case, we can still remove the actual archive if the | 212 // As a special case, we can still remove the actual archive if the |
| 218 // only remaining product is the App Host. | 213 // only remaining product is the App Host. |
| 219 if (dist_type != BrowserDistribution::CHROME_APP_HOST) { | 214 if (dist_type != BrowserDistribution::CHROME_APP_HOST) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 VLOG(1) << "Deleting installer path " << to_delete.value(); | 248 VLOG(1) << "Deleting installer path " << to_delete.value(); |
| 254 if (!base::DeleteFile(to_delete, true)) { | 249 if (!base::DeleteFile(to_delete, true)) { |
| 255 LOG(ERROR) << "Failed to delete path: " << to_delete.value(); | 250 LOG(ERROR) << "Failed to delete path: " << to_delete.value(); |
| 256 success = false; | 251 success = false; |
| 257 } | 252 } |
| 258 } | 253 } |
| 259 | 254 |
| 260 return success; | 255 return success; |
| 261 } | 256 } |
| 262 | 257 |
| 263 } // namespace | |
| 264 | |
| 265 namespace installer { | |
| 266 | |
| 267 // Kills all Chrome processes, immediately. | 258 // Kills all Chrome processes, immediately. |
| 268 void CloseAllChromeProcesses() { | 259 void CloseAllChromeProcesses() { |
| 269 base::CleanupProcesses(installer::kChromeExe, base::TimeDelta(), | 260 base::CleanupProcesses(installer::kChromeExe, base::TimeDelta(), |
| 270 content::RESULT_CODE_HUNG, NULL); | 261 content::RESULT_CODE_HUNG, NULL); |
| 271 base::CleanupProcesses(installer::kNaClExe, base::TimeDelta(), | 262 base::CleanupProcesses(installer::kNaClExe, base::TimeDelta(), |
| 272 content::RESULT_CODE_HUNG, NULL); | 263 content::RESULT_CODE_HUNG, NULL); |
| 273 } | 264 } |
| 274 | 265 |
| 275 // Attempts to close the Chrome Frame helper process by sending WM_CLOSE | 266 // Attempts to close the Chrome Frame helper process by sending WM_CLOSE |
| 276 // messages to its window, or just killing it if that doesn't work. | 267 // messages to its window, or just killing it if that doesn't work. |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 388 if (!base::IsDirectoryEmpty(path)) | 379 if (!base::IsDirectoryEmpty(path)) |
| 389 return DELETE_NOT_EMPTY; | 380 return DELETE_NOT_EMPTY; |
| 390 | 381 |
| 391 if (base::DeleteFile(path, true)) | 382 if (base::DeleteFile(path, true)) |
| 392 return DELETE_SUCCEEDED; | 383 return DELETE_SUCCEEDED; |
| 393 | 384 |
| 394 LOG(ERROR) << "Failed to delete folder: " << path.value(); | 385 LOG(ERROR) << "Failed to delete folder: " << path.value(); |
| 395 return DELETE_FAILED; | 386 return DELETE_FAILED; |
| 396 } | 387 } |
| 397 | 388 |
| 398 void GetLocalStateFolders(const Product& product, | 389 base::FilePath GetUserDataDir(const Product& product) { |
| 399 std::vector<base::FilePath>* paths) { | |
| 400 // Obtain the location of the user profile data. | 390 // Obtain the location of the user profile data. |
| 401 product.GetUserDataPaths(paths); | 391 base::FilePath user_data_dir = product.GetUserDataPath(); |
| 402 LOG_IF(ERROR, paths->empty()) | 392 LOG_IF(ERROR, user_data_dir.empty()) |
| 403 << "Could not retrieve user's profile directory."; | 393 << "Could not retrieve user's profile directory."; |
| 394 | |
| 395 return user_data_dir; | |
| 404 } | 396 } |
| 405 | 397 |
| 406 // Creates a copy of the local state file and returns a path to the copy. | 398 // Creates a copy of the local state file and returns a path to the copy. |
| 407 base::FilePath BackupLocalStateFile( | 399 base::FilePath BackupLocalStateFile(const base::FilePath& user_data_dir) { |
| 408 const std::vector<base::FilePath>& local_state_folders) { | |
| 409 base::FilePath backup; | 400 base::FilePath backup; |
| 410 | 401 base::FilePath state_file( |
| 411 // Copy the first local state file that is found. | 402 user_data_dir.Append(chrome::kLocalStateFilename)); |
| 412 for (size_t i = 0; i < local_state_folders.size(); ++i) { | 403 if (!base::CreateTemporaryFile(&backup)) |
| 413 const base::FilePath& local_state_folder = local_state_folders[i]; | 404 LOG(ERROR) << "Failed to create temporary file for Local State."; |
| 414 base::FilePath state_file( | 405 else |
| 415 local_state_folder.Append(chrome::kLocalStateFilename)); | 406 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; | 407 return backup; |
| 425 } | 408 } |
| 426 | 409 |
| 427 // Deletes all user data directories for a product. | 410 // Deletes a product's user data directory. |
|
gab
2014/04/02 17:20:14
I think this method used to take a |product| argum
grt (UTC plus 2)
2014/04/02 18:04:12
Done.
| |
| 428 DeleteResult DeleteLocalState( | 411 DeleteResult DeleteUserDataDir(const base::FilePath& user_data_dir, |
| 429 const std::vector<base::FilePath>& local_state_folders, | 412 bool schedule_on_failure) { |
| 430 bool schedule_on_failure) { | 413 if (user_data_dir.empty()) |
| 431 if (local_state_folders.empty()) | |
| 432 return DELETE_SUCCEEDED; | 414 return DELETE_SUCCEEDED; |
| 433 | 415 |
| 434 DeleteResult result = DELETE_SUCCEEDED; | 416 DeleteResult result = DELETE_SUCCEEDED; |
| 435 for (size_t i = 0; i < local_state_folders.size(); ++i) { | 417 VLOG(1) << "Deleting user profile " << user_data_dir.value(); |
| 436 const base::FilePath& user_local_state = local_state_folders[i]; | 418 if (!base::DeleteFile(user_data_dir, true)) { |
| 437 VLOG(1) << "Deleting user profile " << user_local_state.value(); | 419 LOG(ERROR) << "Failed to delete user profile dir: " |
| 438 if (!base::DeleteFile(user_local_state, true)) { | 420 << user_data_dir.value(); |
| 439 LOG(ERROR) << "Failed to delete user profile dir: " | 421 if (schedule_on_failure) { |
| 440 << user_local_state.value(); | 422 ScheduleDirectoryForDeletion(user_data_dir); |
| 441 if (schedule_on_failure) { | 423 result = DELETE_REQUIRES_REBOOT; |
| 442 ScheduleDirectoryForDeletion(user_local_state); | 424 } else { |
| 443 result = DELETE_REQUIRES_REBOOT; | 425 result = DELETE_FAILED; |
| 444 } else { | |
| 445 result = DELETE_FAILED; | |
| 446 } | |
| 447 } | 426 } |
| 448 } | 427 } |
| 449 | 428 |
| 450 if (result == DELETE_REQUIRES_REBOOT) { | 429 if (result == DELETE_REQUIRES_REBOOT) { |
| 451 ScheduleParentAndGrandparentForDeletion(local_state_folders[0]); | 430 ScheduleParentAndGrandparentForDeletion(user_data_dir); |
| 452 } else { | 431 } else { |
| 453 const base::FilePath user_data_dir(local_state_folders[0].DirName()); | 432 const base::FilePath user_data_dir(user_data_dir.DirName()); |
| 454 if (!user_data_dir.empty() && | 433 if (!user_data_dir.empty() && |
| 455 DeleteEmptyDir(user_data_dir) == DELETE_SUCCEEDED) { | 434 DeleteEmptyDir(user_data_dir) == DELETE_SUCCEEDED) { |
| 456 const base::FilePath product_dir(user_data_dir.DirName()); | 435 const base::FilePath product_dir(user_data_dir.DirName()); |
| 457 if (!product_dir.empty()) | 436 if (!product_dir.empty()) |
| 458 DeleteEmptyDir(product_dir); | 437 DeleteEmptyDir(product_dir); |
| 459 } | 438 } |
| 460 } | 439 } |
| 461 | 440 |
| 462 return result; | 441 return result; |
| 463 } | 442 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 // We cannot delete the file right away, but try to delete it some other | 494 // We cannot delete the file right away, but try to delete it some other |
| 516 // way. Either with the help of a different process or the system. | 495 // way. Either with the help of a different process or the system. |
| 517 if (!base::DeleteFileAfterReboot(temp_file)) { | 496 if (!base::DeleteFileAfterReboot(temp_file)) { |
| 518 const uint32 kDeleteAfterMs = 10 * 1000; | 497 const uint32 kDeleteAfterMs = 10 * 1000; |
| 519 installer::DeleteFileFromTempProcess(temp_file, kDeleteAfterMs); | 498 installer::DeleteFileFromTempProcess(temp_file, kDeleteAfterMs); |
| 520 } | 499 } |
| 521 } | 500 } |
| 522 return true; | 501 return true; |
| 523 } | 502 } |
| 524 | 503 |
| 525 DeleteResult DeleteChromeDirectoriesIfEmpty( | |
| 526 const base::FilePath& application_directory) { | |
| 527 DeleteResult result(DeleteEmptyDir(application_directory)); | |
| 528 if (result == DELETE_SUCCEEDED) { | |
| 529 // Now check and delete if the parent directories are empty | |
| 530 // For example Google\Chrome or Chromium | |
| 531 const base::FilePath product_directory(application_directory.DirName()); | |
| 532 if (!product_directory.empty()) { | |
| 533 result = DeleteEmptyDir(product_directory); | |
| 534 if (result == DELETE_SUCCEEDED) { | |
| 535 const base::FilePath vendor_directory(product_directory.DirName()); | |
| 536 if (!vendor_directory.empty()) | |
| 537 result = DeleteEmptyDir(vendor_directory); | |
| 538 } | |
| 539 } | |
| 540 } | |
| 541 if (result == DELETE_NOT_EMPTY) | |
| 542 result = DELETE_SUCCEEDED; | |
| 543 return result; | |
| 544 } | |
| 545 | |
| 546 DeleteResult DeleteAppHostFilesAndFolders(const InstallerState& installer_state, | 504 DeleteResult DeleteAppHostFilesAndFolders(const InstallerState& installer_state, |
| 547 const Version& installed_version) { | 505 const Version& installed_version) { |
| 548 const base::FilePath& target_path = installer_state.target_path(); | 506 const base::FilePath& target_path = installer_state.target_path(); |
| 549 if (target_path.empty()) { | 507 if (target_path.empty()) { |
| 550 LOG(ERROR) << "DeleteAppHostFilesAndFolders: no installation destination " | 508 LOG(ERROR) << "DeleteAppHostFilesAndFolders: no installation destination " |
| 551 << "path."; | 509 << "path."; |
| 552 return DELETE_FAILED; // Nothing else we can do to uninstall, so we return. | 510 return DELETE_FAILED; // Nothing else we can do to uninstall, so we return. |
| 553 } | 511 } |
| 554 | 512 |
| 555 DeleteInstallTempDir(target_path); | 513 DeleteInstallTempDir(target_path); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 751 key.WriteValue(NULL, replacement_prog_id) != ERROR_SUCCESS)) { | 709 key.WriteValue(NULL, replacement_prog_id) != ERROR_SUCCESS)) { |
| 752 // The replacement ProgID is registered on the computer but the attempt | 710 // The replacement ProgID is registered on the computer but the attempt |
| 753 // to set it for the filetype failed. | 711 // to set it for the filetype failed. |
| 754 LOG(ERROR) << "Failed to restore system-level filetype association " | 712 LOG(ERROR) << "Failed to restore system-level filetype association " |
| 755 << assoc << " = " << replacement_prog_id; | 713 << assoc << " = " << replacement_prog_id; |
| 756 } | 714 } |
| 757 } | 715 } |
| 758 } | 716 } |
| 759 } | 717 } |
| 760 | 718 |
| 719 // Builds and executes a work item list to remove DelegateExecute verb handler | |
| 720 // work items for |product|. This will be a noop for products whose | |
| 721 // corresponding BrowserDistribution implementations do not publish a CLSID via | |
| 722 // GetCommandExecuteImplClsid. | |
| 723 bool ProcessDelegateExecuteWorkItems(const InstallerState& installer_state, | |
| 724 const Product& product) { | |
| 725 scoped_ptr<WorkItemList> item_list(WorkItem::CreateNoRollbackWorkItemList()); | |
| 726 AddDelegateExecuteWorkItems(installer_state, base::FilePath(), Version(), | |
| 727 product, item_list.get()); | |
| 728 return item_list->Do(); | |
| 729 } | |
| 730 | |
| 731 // Removes Active Setup entries from the registry. This cannot be done through | |
| 732 // a work items list as usual because of different paths based on conditionals, | |
| 733 // but otherwise respects the no rollback/best effort uninstall mentality. | |
| 734 // This will only apply for system-level installs of Chrome/Chromium and will be | |
| 735 // a no-op for all other types of installs. | |
| 736 void UninstallActiveSetupEntries(const InstallerState& installer_state, | |
| 737 const Product& product) { | |
| 738 VLOG(1) << "Uninstalling registry entries for ActiveSetup."; | |
| 739 BrowserDistribution* distribution = product.distribution(); | |
| 740 | |
| 741 if (!product.is_chrome() || !installer_state.system_install()) { | |
| 742 const char* install_level = | |
| 743 installer_state.system_install() ? "system" : "user"; | |
| 744 VLOG(1) << "No Active Setup processing to do for " << install_level | |
| 745 << "-level " << distribution->GetDisplayName(); | |
| 746 return; | |
| 747 } | |
| 748 | |
| 749 const base::string16 active_setup_path( | |
| 750 InstallUtil::GetActiveSetupPath(distribution)); | |
| 751 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path); | |
| 752 | |
| 753 // Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\ | |
| 754 // Active Setup\\Installed Components\\{guid} | |
| 755 // for every user that logged in since system-level Chrome was installed. | |
| 756 // This is a problem because Windows compares the value of the Version subkey | |
| 757 // in there with the value of the Version subkey in the matching HKLM entries | |
| 758 // before running Chrome's Active Setup so if Chrome was to be reinstalled | |
| 759 // with a lesser version (e.g. switching back to a more stable channel), the | |
| 760 // affected users would not have Chrome's Active Setup called until Chrome | |
| 761 // eventually updated passed that user's registered Version. | |
| 762 // | |
| 763 // It is however very hard to delete those values as the registry hives for | |
| 764 // other users are not loaded by default under HKEY_USERS (unless a user is | |
| 765 // logged on or has a process impersonating him). | |
| 766 // | |
| 767 // Following our best effort uninstall practices, try to delete the value in | |
| 768 // all users hives. If a given user's hive is not loaded, try to load it to | |
| 769 // proceed with the deletion (failure to do so is ignored). | |
| 770 | |
| 771 static const wchar_t kProfileList[] = | |
| 772 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"; | |
| 773 | |
| 774 // Windows automatically adds Wow6432Node when creating/deleting the HKLM key, | |
| 775 // but doesn't seem to do so when manually deleting the user-level keys it | |
| 776 // created. | |
| 777 base::string16 alternate_active_setup_path(active_setup_path); | |
| 778 alternate_active_setup_path.insert(arraysize("Software\\") - 1, | |
| 779 L"Wow6432Node\\"); | |
| 780 | |
| 781 // These two privileges are required by RegLoadKey() and RegUnloadKey() below. | |
| 782 ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME); | |
| 783 ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME); | |
| 784 if (!se_restore_name_privilege.is_enabled() || | |
| 785 !se_backup_name_privilege.is_enabled()) { | |
| 786 // This is not a critical failure as those privileges aren't required to | |
| 787 // clean hives that are already loaded, but attempts to LoadRegKey() below | |
| 788 // will fail. | |
| 789 LOG(WARNING) << "Failed to enable privileges required to load registry " | |
| 790 "hives."; | |
| 791 } | |
| 792 | |
| 793 for (base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE, kProfileList); | |
| 794 it.Valid(); ++it) { | |
| 795 const wchar_t* profile_sid = it.Name(); | |
| 796 | |
| 797 // First check if this user's registry hive needs to be loaded in | |
| 798 // HKEY_USERS. | |
| 799 base::win::RegKey user_reg_root_probe( | |
| 800 HKEY_USERS, profile_sid, KEY_READ); | |
| 801 bool loaded_hive = false; | |
| 802 if (!user_reg_root_probe.Valid()) { | |
| 803 VLOG(1) << "Attempting to load registry hive for " << profile_sid; | |
| 804 | |
| 805 base::string16 reg_profile_info_path(kProfileList); | |
| 806 reg_profile_info_path.append(profile_sid); | |
| 807 base::win::RegKey reg_profile_info_key( | |
| 808 HKEY_LOCAL_MACHINE, reg_profile_info_path.c_str(), KEY_READ); | |
| 809 | |
| 810 base::string16 profile_path; | |
| 811 LONG result = reg_profile_info_key.ReadValue(L"ProfileImagePath", | |
| 812 &profile_path); | |
| 813 if (result != ERROR_SUCCESS) { | |
| 814 LOG(ERROR) << "Error reading ProfileImagePath: " << result; | |
| 815 continue; | |
| 816 } | |
| 817 base::FilePath registry_hive_file(profile_path); | |
| 818 registry_hive_file = registry_hive_file.AppendASCII("NTUSER.DAT"); | |
| 819 | |
| 820 result = RegLoadKey(HKEY_USERS, profile_sid, | |
| 821 registry_hive_file.value().c_str()); | |
| 822 if (result != ERROR_SUCCESS) { | |
| 823 LOG(ERROR) << "Error loading registry hive: " << result; | |
| 824 continue; | |
| 825 } | |
| 826 | |
| 827 VLOG(1) << "Loaded registry hive for " << profile_sid; | |
| 828 loaded_hive = true; | |
| 829 } | |
| 830 | |
| 831 base::win::RegKey user_reg_root( | |
| 832 HKEY_USERS, profile_sid, KEY_ALL_ACCESS); | |
| 833 | |
| 834 LONG result = user_reg_root.DeleteKey(active_setup_path.c_str()); | |
| 835 if (result != ERROR_SUCCESS) { | |
| 836 result = user_reg_root.DeleteKey(alternate_active_setup_path.c_str()); | |
| 837 if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { | |
| 838 LOG(ERROR) << "Failed to delete key at " << active_setup_path | |
| 839 << " and at " << alternate_active_setup_path | |
| 840 << ", result: " << result; | |
| 841 } | |
| 842 } | |
| 843 | |
| 844 if (loaded_hive) { | |
| 845 user_reg_root.Close(); | |
| 846 if (RegUnLoadKey(HKEY_USERS, profile_sid) == ERROR_SUCCESS) | |
| 847 VLOG(1) << "Unloaded registry hive for " << profile_sid; | |
| 848 else | |
| 849 LOG(ERROR) << "Error unloading registry hive for " << profile_sid; | |
| 850 } | |
| 851 } | |
| 852 } | |
| 853 | |
| 854 } // namespace | |
| 855 | |
| 856 DeleteResult DeleteChromeDirectoriesIfEmpty( | |
| 857 const base::FilePath& application_directory) { | |
| 858 DeleteResult result(DeleteEmptyDir(application_directory)); | |
| 859 if (result == DELETE_SUCCEEDED) { | |
| 860 // Now check and delete if the parent directories are empty | |
| 861 // For example Google\Chrome or Chromium | |
| 862 const base::FilePath product_directory(application_directory.DirName()); | |
| 863 if (!product_directory.empty()) { | |
| 864 result = DeleteEmptyDir(product_directory); | |
| 865 if (result == DELETE_SUCCEEDED) { | |
| 866 const base::FilePath vendor_directory(product_directory.DirName()); | |
| 867 if (!vendor_directory.empty()) | |
| 868 result = DeleteEmptyDir(vendor_directory); | |
| 869 } | |
| 870 } | |
| 871 } | |
| 872 if (result == DELETE_NOT_EMPTY) | |
| 873 result = DELETE_SUCCEEDED; | |
| 874 return result; | |
| 875 } | |
| 876 | |
| 761 bool DeleteChromeRegistrationKeys(const InstallerState& installer_state, | 877 bool DeleteChromeRegistrationKeys(const InstallerState& installer_state, |
| 762 BrowserDistribution* dist, | 878 BrowserDistribution* dist, |
| 763 HKEY root, | 879 HKEY root, |
| 764 const base::string16& browser_entry_suffix, | 880 const base::string16& browser_entry_suffix, |
| 765 InstallStatus* exit_code) { | 881 InstallStatus* exit_code) { |
| 766 DCHECK(exit_code); | 882 DCHECK(exit_code); |
| 767 if (dist->GetDefaultBrowserControlPolicy() == | 883 if (dist->GetDefaultBrowserControlPolicy() == |
| 768 BrowserDistribution::DEFAULT_BROWSER_UNSUPPORTED) { | 884 BrowserDistribution::DEFAULT_BROWSER_UNSUPPORTED) { |
| 769 // We should have never set those keys. | 885 // We should have never set those keys. |
| 770 return true; | 886 return true; |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 922 InstallUtil::DeleteRegistryKey(roots[i], ext_prog_id); | 1038 InstallUtil::DeleteRegistryKey(roots[i], ext_prog_id); |
| 923 | 1039 |
| 924 // Delete Software\Classes\.crx, | 1040 // Delete Software\Classes\.crx, |
| 925 base::string16 ext_association(ShellUtil::kRegClasses); | 1041 base::string16 ext_association(ShellUtil::kRegClasses); |
| 926 ext_association.append(L"\\"); | 1042 ext_association.append(L"\\"); |
| 927 ext_association.append(extensions::kExtensionFileExtension); | 1043 ext_association.append(extensions::kExtensionFileExtension); |
| 928 InstallUtil::DeleteRegistryKey(roots[i], ext_association); | 1044 InstallUtil::DeleteRegistryKey(roots[i], ext_association); |
| 929 } | 1045 } |
| 930 } | 1046 } |
| 931 | 1047 |
| 932 // Builds and executes a work item list to remove DelegateExecute verb handler | |
| 933 // work items for |product|. This will be a noop for products whose | |
| 934 // corresponding BrowserDistribution implementations do not publish a CLSID via | |
| 935 // GetCommandExecuteImplClsid. | |
| 936 bool ProcessDelegateExecuteWorkItems(const InstallerState& installer_state, | |
| 937 const Product& product) { | |
| 938 scoped_ptr<WorkItemList> item_list(WorkItem::CreateNoRollbackWorkItemList()); | |
| 939 AddDelegateExecuteWorkItems(installer_state, base::FilePath(), Version(), | |
| 940 product, item_list.get()); | |
| 941 return item_list->Do(); | |
| 942 } | |
| 943 | |
| 944 // Removes Active Setup entries from the registry. This cannot be done through | |
| 945 // a work items list as usual because of different paths based on conditionals, | |
| 946 // but otherwise respects the no rollback/best effort uninstall mentality. | |
| 947 // This will only apply for system-level installs of Chrome/Chromium and will be | |
| 948 // a no-op for all other types of installs. | |
| 949 void UninstallActiveSetupEntries(const InstallerState& installer_state, | |
| 950 const Product& product) { | |
| 951 VLOG(1) << "Uninstalling registry entries for ActiveSetup."; | |
| 952 BrowserDistribution* distribution = product.distribution(); | |
| 953 | |
| 954 if (!product.is_chrome() || !installer_state.system_install()) { | |
| 955 const char* install_level = | |
| 956 installer_state.system_install() ? "system" : "user"; | |
| 957 VLOG(1) << "No Active Setup processing to do for " << install_level | |
| 958 << "-level " << distribution->GetDisplayName(); | |
| 959 return; | |
| 960 } | |
| 961 | |
| 962 const base::string16 active_setup_path( | |
| 963 InstallUtil::GetActiveSetupPath(distribution)); | |
| 964 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path); | |
| 965 | |
| 966 // Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\ | |
| 967 // Active Setup\\Installed Components\\{guid} | |
| 968 // for every user that logged in since system-level Chrome was installed. | |
| 969 // This is a problem because Windows compares the value of the Version subkey | |
| 970 // in there with the value of the Version subkey in the matching HKLM entries | |
| 971 // before running Chrome's Active Setup so if Chrome was to be reinstalled | |
| 972 // with a lesser version (e.g. switching back to a more stable channel), the | |
| 973 // affected users would not have Chrome's Active Setup called until Chrome | |
| 974 // eventually updated passed that user's registered Version. | |
| 975 // | |
| 976 // It is however very hard to delete those values as the registry hives for | |
| 977 // other users are not loaded by default under HKEY_USERS (unless a user is | |
| 978 // logged on or has a process impersonating him). | |
| 979 // | |
| 980 // Following our best effort uninstall practices, try to delete the value in | |
| 981 // all users hives. If a given user's hive is not loaded, try to load it to | |
| 982 // proceed with the deletion (failure to do so is ignored). | |
| 983 | |
| 984 static const wchar_t kProfileList[] = | |
| 985 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"; | |
| 986 | |
| 987 // Windows automatically adds Wow6432Node when creating/deleting the HKLM key, | |
| 988 // but doesn't seem to do so when manually deleting the user-level keys it | |
| 989 // created. | |
| 990 base::string16 alternate_active_setup_path(active_setup_path); | |
| 991 alternate_active_setup_path.insert(arraysize("Software\\") - 1, | |
| 992 L"Wow6432Node\\"); | |
| 993 | |
| 994 // These two privileges are required by RegLoadKey() and RegUnloadKey() below. | |
| 995 ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME); | |
| 996 ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME); | |
| 997 if (!se_restore_name_privilege.is_enabled() || | |
| 998 !se_backup_name_privilege.is_enabled()) { | |
| 999 // This is not a critical failure as those privileges aren't required to | |
| 1000 // clean hives that are already loaded, but attempts to LoadRegKey() below | |
| 1001 // will fail. | |
| 1002 LOG(WARNING) << "Failed to enable privileges required to load registry " | |
| 1003 "hives."; | |
| 1004 } | |
| 1005 | |
| 1006 for (base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE, kProfileList); | |
| 1007 it.Valid(); ++it) { | |
| 1008 const wchar_t* profile_sid = it.Name(); | |
| 1009 | |
| 1010 // First check if this user's registry hive needs to be loaded in | |
| 1011 // HKEY_USERS. | |
| 1012 base::win::RegKey user_reg_root_probe( | |
| 1013 HKEY_USERS, profile_sid, KEY_READ); | |
| 1014 bool loaded_hive = false; | |
| 1015 if (!user_reg_root_probe.Valid()) { | |
| 1016 VLOG(1) << "Attempting to load registry hive for " << profile_sid; | |
| 1017 | |
| 1018 base::string16 reg_profile_info_path(kProfileList); | |
| 1019 reg_profile_info_path.append(profile_sid); | |
| 1020 base::win::RegKey reg_profile_info_key( | |
| 1021 HKEY_LOCAL_MACHINE, reg_profile_info_path.c_str(), KEY_READ); | |
| 1022 | |
| 1023 base::string16 profile_path; | |
| 1024 LONG result = reg_profile_info_key.ReadValue(L"ProfileImagePath", | |
| 1025 &profile_path); | |
| 1026 if (result != ERROR_SUCCESS) { | |
| 1027 LOG(ERROR) << "Error reading ProfileImagePath: " << result; | |
| 1028 continue; | |
| 1029 } | |
| 1030 base::FilePath registry_hive_file(profile_path); | |
| 1031 registry_hive_file = registry_hive_file.AppendASCII("NTUSER.DAT"); | |
| 1032 | |
| 1033 result = RegLoadKey(HKEY_USERS, profile_sid, | |
| 1034 registry_hive_file.value().c_str()); | |
| 1035 if (result != ERROR_SUCCESS) { | |
| 1036 LOG(ERROR) << "Error loading registry hive: " << result; | |
| 1037 continue; | |
| 1038 } | |
| 1039 | |
| 1040 VLOG(1) << "Loaded registry hive for " << profile_sid; | |
| 1041 loaded_hive = true; | |
| 1042 } | |
| 1043 | |
| 1044 base::win::RegKey user_reg_root( | |
| 1045 HKEY_USERS, profile_sid, KEY_ALL_ACCESS); | |
| 1046 | |
| 1047 LONG result = user_reg_root.DeleteKey(active_setup_path.c_str()); | |
| 1048 if (result != ERROR_SUCCESS) { | |
| 1049 result = user_reg_root.DeleteKey(alternate_active_setup_path.c_str()); | |
| 1050 if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { | |
| 1051 LOG(ERROR) << "Failed to delete key at " << active_setup_path | |
| 1052 << " and at " << alternate_active_setup_path | |
| 1053 << ", result: " << result; | |
| 1054 } | |
| 1055 } | |
| 1056 | |
| 1057 if (loaded_hive) { | |
| 1058 user_reg_root.Close(); | |
| 1059 if (RegUnLoadKey(HKEY_USERS, profile_sid) == ERROR_SUCCESS) | |
| 1060 VLOG(1) << "Unloaded registry hive for " << profile_sid; | |
| 1061 else | |
| 1062 LOG(ERROR) << "Error unloading registry hive for " << profile_sid; | |
| 1063 } | |
| 1064 } | |
| 1065 } | |
| 1066 | |
| 1067 InstallStatus UninstallProduct(const InstallationState& original_state, | 1048 InstallStatus UninstallProduct(const InstallationState& original_state, |
| 1068 const InstallerState& installer_state, | 1049 const InstallerState& installer_state, |
| 1069 const base::FilePath& setup_exe, | 1050 const base::FilePath& setup_exe, |
| 1070 const Product& product, | 1051 const Product& product, |
| 1071 bool remove_all, | 1052 bool remove_all, |
| 1072 bool force_uninstall, | 1053 bool force_uninstall, |
| 1073 const CommandLine& cmd_line) { | 1054 const CommandLine& cmd_line) { |
| 1074 InstallStatus status = installer::UNINSTALL_CONFIRMED; | 1055 InstallStatus status = installer::UNINSTALL_CONFIRMED; |
| 1075 BrowserDistribution* browser_dist = product.distribution(); | 1056 BrowserDistribution* browser_dist = product.distribution(); |
| 1076 const base::string16 chrome_exe( | 1057 const base::string16 chrome_exe( |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1325 | 1306 |
| 1326 // Finally delete all the files from Chrome folder after moving setup.exe | 1307 // Finally delete all the files from Chrome folder after moving setup.exe |
| 1327 // and the user's Local State to a temp location. | 1308 // and the user's Local State to a temp location. |
| 1328 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, | 1309 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, |
| 1329 product); | 1310 product); |
| 1330 ret = installer::UNINSTALL_SUCCESSFUL; | 1311 ret = installer::UNINSTALL_SUCCESSFUL; |
| 1331 | 1312 |
| 1332 // When deleting files, we must make sure that we're either a "single" | 1313 // When deleting files, we must make sure that we're either a "single" |
| 1333 // (aka non-multi) installation or we are the Chrome Binaries. | 1314 // (aka non-multi) installation or we are the Chrome Binaries. |
| 1334 | 1315 |
| 1335 std::vector<base::FilePath> local_state_folders; | 1316 base::FilePath user_data_dir(GetUserDataDir(product)); |
| 1336 GetLocalStateFolders(product, &local_state_folders); | 1317 base::FilePath backup_state_file(BackupLocalStateFile(user_data_dir)); |
| 1337 base::FilePath backup_state_file(BackupLocalStateFile(local_state_folders)); | |
| 1338 | 1318 |
| 1339 if (product.is_chrome_app_host()) { | 1319 if (product.is_chrome_app_host()) { |
| 1340 DeleteAppHostFilesAndFolders(installer_state, product_state->version()); | 1320 DeleteAppHostFilesAndFolders(installer_state, product_state->version()); |
| 1341 } else if (!installer_state.is_multi_install() || | 1321 } else if (!installer_state.is_multi_install() || |
| 1342 product.is_chrome_binaries()) { | 1322 product.is_chrome_binaries()) { |
| 1343 DeleteResult delete_result = DeleteChromeFilesAndFolders( | 1323 DeleteResult delete_result = DeleteChromeFilesAndFolders( |
| 1344 installer_state, base::MakeAbsoluteFilePath(setup_exe)); | 1324 installer_state, base::MakeAbsoluteFilePath(setup_exe)); |
| 1345 if (delete_result == DELETE_FAILED) { | 1325 if (delete_result == DELETE_FAILED) { |
| 1346 ret = installer::UNINSTALL_FAILED; | 1326 ret = installer::UNINSTALL_FAILED; |
| 1347 } else if (delete_result == DELETE_REQUIRES_REBOOT) { | 1327 } else if (delete_result == DELETE_REQUIRES_REBOOT) { |
| 1348 ret = installer::UNINSTALL_REQUIRES_REBOOT; | 1328 ret = installer::UNINSTALL_REQUIRES_REBOOT; |
| 1349 } | 1329 } |
| 1350 } | 1330 } |
| 1351 | 1331 |
| 1352 if (delete_profile) | 1332 if (delete_profile) |
| 1353 DeleteLocalState(local_state_folders, product.is_chrome_frame()); | 1333 DeleteUserDataDir(user_data_dir, product.is_chrome_frame()); |
| 1354 | 1334 |
| 1355 if (!force_uninstall) { | 1335 if (!force_uninstall) { |
| 1356 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; | 1336 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; |
| 1357 browser_dist->DoPostUninstallOperations(product_state->version(), | 1337 browser_dist->DoPostUninstallOperations(product_state->version(), |
| 1358 backup_state_file, distribution_data); | 1338 backup_state_file, distribution_data); |
| 1359 } | 1339 } |
| 1360 | 1340 |
| 1361 // Try and delete the preserved local state once the post-install | 1341 // Try and delete the preserved local state once the post-install |
| 1362 // operations are complete. | 1342 // operations are complete. |
| 1363 if (!backup_state_file.empty()) | 1343 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 | 1414 // If we need a reboot to continue, schedule the parent directories for |
| 1435 // deletion unconditionally. If they are not empty, the session manager | 1415 // deletion unconditionally. If they are not empty, the session manager |
| 1436 // will not delete them on reboot. | 1416 // will not delete them on reboot. |
| 1437 ScheduleParentAndGrandparentForDeletion(target_path); | 1417 ScheduleParentAndGrandparentForDeletion(target_path); |
| 1438 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { | 1418 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { |
| 1439 *uninstall_status = UNINSTALL_FAILED; | 1419 *uninstall_status = UNINSTALL_FAILED; |
| 1440 } | 1420 } |
| 1441 } | 1421 } |
| 1442 | 1422 |
| 1443 } // namespace installer | 1423 } // namespace installer |
| OLD | NEW |