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 { |
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 given user data directory as well as the containing product |
428 DeleteResult DeleteLocalState( | 411 // directories if they are empty (e.g., "Google\Chrome"). |
429 const std::vector<base::FilePath>& local_state_folders, | 412 DeleteResult DeleteUserDataDir(const base::FilePath& user_data_dir, |
430 bool schedule_on_failure) { | 413 bool schedule_on_failure) { |
431 if (local_state_folders.empty()) | 414 if (user_data_dir.empty()) |
432 return DELETE_SUCCEEDED; | 415 return DELETE_SUCCEEDED; |
433 | 416 |
434 DeleteResult result = DELETE_SUCCEEDED; | 417 DeleteResult result = DELETE_SUCCEEDED; |
435 for (size_t i = 0; i < local_state_folders.size(); ++i) { | 418 VLOG(1) << "Deleting user profile " << user_data_dir.value(); |
436 const base::FilePath& user_local_state = local_state_folders[i]; | 419 if (!base::DeleteFile(user_data_dir, true)) { |
437 VLOG(1) << "Deleting user profile " << user_local_state.value(); | 420 LOG(ERROR) << "Failed to delete user profile dir: " |
438 if (!base::DeleteFile(user_local_state, true)) { | 421 << user_data_dir.value(); |
439 LOG(ERROR) << "Failed to delete user profile dir: " | 422 if (schedule_on_failure) { |
440 << user_local_state.value(); | 423 ScheduleDirectoryForDeletion(user_data_dir); |
441 if (schedule_on_failure) { | 424 result = DELETE_REQUIRES_REBOOT; |
442 ScheduleDirectoryForDeletion(user_local_state); | 425 } else { |
443 result = DELETE_REQUIRES_REBOOT; | 426 result = DELETE_FAILED; |
444 } else { | |
445 result = DELETE_FAILED; | |
446 } | |
447 } | 427 } |
448 } | 428 } |
449 | 429 |
450 if (result == DELETE_REQUIRES_REBOOT) { | 430 if (result == DELETE_REQUIRES_REBOOT) { |
451 ScheduleParentAndGrandparentForDeletion(local_state_folders[0]); | 431 ScheduleParentAndGrandparentForDeletion(user_data_dir); |
452 } else { | 432 } else { |
453 const base::FilePath user_data_dir(local_state_folders[0].DirName()); | 433 const base::FilePath user_data_dir(user_data_dir.DirName()); |
Nico
2014/07/21 14:47:44
clang remarks:
..\..\chrome\installer\setup\unins
| |
454 if (!user_data_dir.empty() && | 434 if (!user_data_dir.empty() && |
455 DeleteEmptyDir(user_data_dir) == DELETE_SUCCEEDED) { | 435 DeleteEmptyDir(user_data_dir) == DELETE_SUCCEEDED) { |
456 const base::FilePath product_dir(user_data_dir.DirName()); | 436 const base::FilePath product_dir(user_data_dir.DirName()); |
457 if (!product_dir.empty()) | 437 if (!product_dir.empty()) |
458 DeleteEmptyDir(product_dir); | 438 DeleteEmptyDir(product_dir); |
459 } | 439 } |
460 } | 440 } |
461 | 441 |
462 return result; | 442 return result; |
463 } | 443 } |
(...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 | 495 // 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. | 496 // way. Either with the help of a different process or the system. |
517 if (!base::DeleteFileAfterReboot(temp_file)) { | 497 if (!base::DeleteFileAfterReboot(temp_file)) { |
518 const uint32 kDeleteAfterMs = 10 * 1000; | 498 const uint32 kDeleteAfterMs = 10 * 1000; |
519 installer::DeleteFileFromTempProcess(temp_file, kDeleteAfterMs); | 499 installer::DeleteFileFromTempProcess(temp_file, kDeleteAfterMs); |
520 } | 500 } |
521 } | 501 } |
522 return true; | 502 return true; |
523 } | 503 } |
524 | 504 |
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, | 505 DeleteResult DeleteAppHostFilesAndFolders(const InstallerState& installer_state, |
547 const Version& installed_version) { | 506 const Version& installed_version) { |
548 const base::FilePath& target_path = installer_state.target_path(); | 507 const base::FilePath& target_path = installer_state.target_path(); |
549 if (target_path.empty()) { | 508 if (target_path.empty()) { |
550 LOG(ERROR) << "DeleteAppHostFilesAndFolders: no installation destination " | 509 LOG(ERROR) << "DeleteAppHostFilesAndFolders: no installation destination " |
551 << "path."; | 510 << "path."; |
552 return DELETE_FAILED; // Nothing else we can do to uninstall, so we return. | 511 return DELETE_FAILED; // Nothing else we can do to uninstall, so we return. |
553 } | 512 } |
554 | 513 |
555 DeleteInstallTempDir(target_path); | 514 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)) { | 710 key.WriteValue(NULL, replacement_prog_id) != ERROR_SUCCESS)) { |
752 // The replacement ProgID is registered on the computer but the attempt | 711 // The replacement ProgID is registered on the computer but the attempt |
753 // to set it for the filetype failed. | 712 // to set it for the filetype failed. |
754 LOG(ERROR) << "Failed to restore system-level filetype association " | 713 LOG(ERROR) << "Failed to restore system-level filetype association " |
755 << assoc << " = " << replacement_prog_id; | 714 << assoc << " = " << replacement_prog_id; |
756 } | 715 } |
757 } | 716 } |
758 } | 717 } |
759 } | 718 } |
760 | 719 |
720 // Builds and executes a work item list to remove DelegateExecute verb handler | |
721 // work items for |product|. This will be a noop for products whose | |
722 // corresponding BrowserDistribution implementations do not publish a CLSID via | |
723 // GetCommandExecuteImplClsid. | |
724 bool ProcessDelegateExecuteWorkItems(const InstallerState& installer_state, | |
725 const Product& product) { | |
726 scoped_ptr<WorkItemList> item_list(WorkItem::CreateNoRollbackWorkItemList()); | |
727 AddDelegateExecuteWorkItems(installer_state, base::FilePath(), Version(), | |
728 product, item_list.get()); | |
729 return item_list->Do(); | |
730 } | |
731 | |
732 // Removes Active Setup entries from the registry. This cannot be done through | |
733 // a work items list as usual because of different paths based on conditionals, | |
734 // but otherwise respects the no rollback/best effort uninstall mentality. | |
735 // This will only apply for system-level installs of Chrome/Chromium and will be | |
736 // a no-op for all other types of installs. | |
737 void UninstallActiveSetupEntries(const InstallerState& installer_state, | |
738 const Product& product) { | |
739 VLOG(1) << "Uninstalling registry entries for ActiveSetup."; | |
740 BrowserDistribution* distribution = product.distribution(); | |
741 | |
742 if (!product.is_chrome() || !installer_state.system_install()) { | |
743 const char* install_level = | |
744 installer_state.system_install() ? "system" : "user"; | |
745 VLOG(1) << "No Active Setup processing to do for " << install_level | |
746 << "-level " << distribution->GetDisplayName(); | |
747 return; | |
748 } | |
749 | |
750 const base::string16 active_setup_path( | |
751 InstallUtil::GetActiveSetupPath(distribution)); | |
752 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path); | |
753 | |
754 // Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\ | |
755 // Active Setup\\Installed Components\\{guid} | |
756 // for every user that logged in since system-level Chrome was installed. | |
757 // This is a problem because Windows compares the value of the Version subkey | |
758 // in there with the value of the Version subkey in the matching HKLM entries | |
759 // before running Chrome's Active Setup so if Chrome was to be reinstalled | |
760 // with a lesser version (e.g. switching back to a more stable channel), the | |
761 // affected users would not have Chrome's Active Setup called until Chrome | |
762 // eventually updated passed that user's registered Version. | |
763 // | |
764 // It is however very hard to delete those values as the registry hives for | |
765 // other users are not loaded by default under HKEY_USERS (unless a user is | |
766 // logged on or has a process impersonating him). | |
767 // | |
768 // Following our best effort uninstall practices, try to delete the value in | |
769 // all users hives. If a given user's hive is not loaded, try to load it to | |
770 // proceed with the deletion (failure to do so is ignored). | |
771 | |
772 static const wchar_t kProfileList[] = | |
773 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"; | |
774 | |
775 // Windows automatically adds Wow6432Node when creating/deleting the HKLM key, | |
776 // but doesn't seem to do so when manually deleting the user-level keys it | |
777 // created. | |
778 base::string16 alternate_active_setup_path(active_setup_path); | |
779 alternate_active_setup_path.insert(arraysize("Software\\") - 1, | |
780 L"Wow6432Node\\"); | |
781 | |
782 // These two privileges are required by RegLoadKey() and RegUnloadKey() below. | |
783 ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME); | |
784 ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME); | |
785 if (!se_restore_name_privilege.is_enabled() || | |
786 !se_backup_name_privilege.is_enabled()) { | |
787 // This is not a critical failure as those privileges aren't required to | |
788 // clean hives that are already loaded, but attempts to LoadRegKey() below | |
789 // will fail. | |
790 LOG(WARNING) << "Failed to enable privileges required to load registry " | |
791 "hives."; | |
792 } | |
793 | |
794 for (base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE, kProfileList); | |
795 it.Valid(); ++it) { | |
796 const wchar_t* profile_sid = it.Name(); | |
797 | |
798 // First check if this user's registry hive needs to be loaded in | |
799 // HKEY_USERS. | |
800 base::win::RegKey user_reg_root_probe( | |
801 HKEY_USERS, profile_sid, KEY_READ); | |
802 bool loaded_hive = false; | |
803 if (!user_reg_root_probe.Valid()) { | |
804 VLOG(1) << "Attempting to load registry hive for " << profile_sid; | |
805 | |
806 base::string16 reg_profile_info_path(kProfileList); | |
807 reg_profile_info_path.append(profile_sid); | |
808 base::win::RegKey reg_profile_info_key( | |
809 HKEY_LOCAL_MACHINE, reg_profile_info_path.c_str(), KEY_READ); | |
810 | |
811 base::string16 profile_path; | |
812 LONG result = reg_profile_info_key.ReadValue(L"ProfileImagePath", | |
813 &profile_path); | |
814 if (result != ERROR_SUCCESS) { | |
815 LOG(ERROR) << "Error reading ProfileImagePath: " << result; | |
816 continue; | |
817 } | |
818 base::FilePath registry_hive_file(profile_path); | |
819 registry_hive_file = registry_hive_file.AppendASCII("NTUSER.DAT"); | |
820 | |
821 result = RegLoadKey(HKEY_USERS, profile_sid, | |
822 registry_hive_file.value().c_str()); | |
823 if (result != ERROR_SUCCESS) { | |
824 LOG(ERROR) << "Error loading registry hive: " << result; | |
825 continue; | |
826 } | |
827 | |
828 VLOG(1) << "Loaded registry hive for " << profile_sid; | |
829 loaded_hive = true; | |
830 } | |
831 | |
832 base::win::RegKey user_reg_root( | |
833 HKEY_USERS, profile_sid, KEY_ALL_ACCESS); | |
834 | |
835 LONG result = user_reg_root.DeleteKey(active_setup_path.c_str()); | |
836 if (result != ERROR_SUCCESS) { | |
837 result = user_reg_root.DeleteKey(alternate_active_setup_path.c_str()); | |
838 if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { | |
839 LOG(ERROR) << "Failed to delete key at " << active_setup_path | |
840 << " and at " << alternate_active_setup_path | |
841 << ", result: " << result; | |
842 } | |
843 } | |
844 | |
845 if (loaded_hive) { | |
846 user_reg_root.Close(); | |
847 if (RegUnLoadKey(HKEY_USERS, profile_sid) == ERROR_SUCCESS) | |
848 VLOG(1) << "Unloaded registry hive for " << profile_sid; | |
849 else | |
850 LOG(ERROR) << "Error unloading registry hive for " << profile_sid; | |
851 } | |
852 } | |
853 } | |
854 | |
855 } // namespace | |
856 | |
857 DeleteResult DeleteChromeDirectoriesIfEmpty( | |
858 const base::FilePath& application_directory) { | |
859 DeleteResult result(DeleteEmptyDir(application_directory)); | |
860 if (result == DELETE_SUCCEEDED) { | |
861 // Now check and delete if the parent directories are empty | |
862 // For example Google\Chrome or Chromium | |
863 const base::FilePath product_directory(application_directory.DirName()); | |
864 if (!product_directory.empty()) { | |
865 result = DeleteEmptyDir(product_directory); | |
866 if (result == DELETE_SUCCEEDED) { | |
867 const base::FilePath vendor_directory(product_directory.DirName()); | |
868 if (!vendor_directory.empty()) | |
869 result = DeleteEmptyDir(vendor_directory); | |
870 } | |
871 } | |
872 } | |
873 if (result == DELETE_NOT_EMPTY) | |
874 result = DELETE_SUCCEEDED; | |
875 return result; | |
876 } | |
877 | |
761 bool DeleteChromeRegistrationKeys(const InstallerState& installer_state, | 878 bool DeleteChromeRegistrationKeys(const InstallerState& installer_state, |
762 BrowserDistribution* dist, | 879 BrowserDistribution* dist, |
763 HKEY root, | 880 HKEY root, |
764 const base::string16& browser_entry_suffix, | 881 const base::string16& browser_entry_suffix, |
765 InstallStatus* exit_code) { | 882 InstallStatus* exit_code) { |
766 DCHECK(exit_code); | 883 DCHECK(exit_code); |
767 if (dist->GetDefaultBrowserControlPolicy() == | 884 if (dist->GetDefaultBrowserControlPolicy() == |
768 BrowserDistribution::DEFAULT_BROWSER_UNSUPPORTED) { | 885 BrowserDistribution::DEFAULT_BROWSER_UNSUPPORTED) { |
769 // We should have never set those keys. | 886 // We should have never set those keys. |
770 return true; | 887 return true; |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
922 InstallUtil::DeleteRegistryKey(roots[i], ext_prog_id); | 1039 InstallUtil::DeleteRegistryKey(roots[i], ext_prog_id); |
923 | 1040 |
924 // Delete Software\Classes\.crx, | 1041 // Delete Software\Classes\.crx, |
925 base::string16 ext_association(ShellUtil::kRegClasses); | 1042 base::string16 ext_association(ShellUtil::kRegClasses); |
926 ext_association.append(L"\\"); | 1043 ext_association.append(L"\\"); |
927 ext_association.append(extensions::kExtensionFileExtension); | 1044 ext_association.append(extensions::kExtensionFileExtension); |
928 InstallUtil::DeleteRegistryKey(roots[i], ext_association); | 1045 InstallUtil::DeleteRegistryKey(roots[i], ext_association); |
929 } | 1046 } |
930 } | 1047 } |
931 | 1048 |
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, | 1049 InstallStatus UninstallProduct(const InstallationState& original_state, |
1068 const InstallerState& installer_state, | 1050 const InstallerState& installer_state, |
1069 const base::FilePath& setup_exe, | 1051 const base::FilePath& setup_exe, |
1070 const Product& product, | 1052 const Product& product, |
1071 bool remove_all, | 1053 bool remove_all, |
1072 bool force_uninstall, | 1054 bool force_uninstall, |
1073 const CommandLine& cmd_line) { | 1055 const CommandLine& cmd_line) { |
1074 InstallStatus status = installer::UNINSTALL_CONFIRMED; | 1056 InstallStatus status = installer::UNINSTALL_CONFIRMED; |
1075 BrowserDistribution* browser_dist = product.distribution(); | 1057 BrowserDistribution* browser_dist = product.distribution(); |
1076 const base::string16 chrome_exe( | 1058 const base::string16 chrome_exe( |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1325 | 1307 |
1326 // Finally delete all the files from Chrome folder after moving setup.exe | 1308 // Finally delete all the files from Chrome folder after moving setup.exe |
1327 // and the user's Local State to a temp location. | 1309 // and the user's Local State to a temp location. |
1328 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, | 1310 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, |
1329 product); | 1311 product); |
1330 ret = installer::UNINSTALL_SUCCESSFUL; | 1312 ret = installer::UNINSTALL_SUCCESSFUL; |
1331 | 1313 |
1332 // When deleting files, we must make sure that we're either a "single" | 1314 // When deleting files, we must make sure that we're either a "single" |
1333 // (aka non-multi) installation or we are the Chrome Binaries. | 1315 // (aka non-multi) installation or we are the Chrome Binaries. |
1334 | 1316 |
1335 std::vector<base::FilePath> local_state_folders; | 1317 base::FilePath user_data_dir(GetUserDataDir(product)); |
1336 GetLocalStateFolders(product, &local_state_folders); | 1318 base::FilePath backup_state_file(BackupLocalStateFile(user_data_dir)); |
1337 base::FilePath backup_state_file(BackupLocalStateFile(local_state_folders)); | |
1338 | 1319 |
1339 if (product.is_chrome_app_host()) { | 1320 if (product.is_chrome_app_host()) { |
1340 DeleteAppHostFilesAndFolders(installer_state, product_state->version()); | 1321 DeleteAppHostFilesAndFolders(installer_state, product_state->version()); |
1341 } else if (!installer_state.is_multi_install() || | 1322 } else if (!installer_state.is_multi_install() || |
1342 product.is_chrome_binaries()) { | 1323 product.is_chrome_binaries()) { |
1343 DeleteResult delete_result = DeleteChromeFilesAndFolders( | 1324 DeleteResult delete_result = DeleteChromeFilesAndFolders( |
1344 installer_state, base::MakeAbsoluteFilePath(setup_exe)); | 1325 installer_state, base::MakeAbsoluteFilePath(setup_exe)); |
1345 if (delete_result == DELETE_FAILED) { | 1326 if (delete_result == DELETE_FAILED) { |
1346 ret = installer::UNINSTALL_FAILED; | 1327 ret = installer::UNINSTALL_FAILED; |
1347 } else if (delete_result == DELETE_REQUIRES_REBOOT) { | 1328 } else if (delete_result == DELETE_REQUIRES_REBOOT) { |
1348 ret = installer::UNINSTALL_REQUIRES_REBOOT; | 1329 ret = installer::UNINSTALL_REQUIRES_REBOOT; |
1349 } | 1330 } |
1350 } | 1331 } |
1351 | 1332 |
1352 if (delete_profile) | 1333 if (delete_profile) |
1353 DeleteLocalState(local_state_folders, product.is_chrome_frame()); | 1334 DeleteUserDataDir(user_data_dir, product.is_chrome_frame()); |
1354 | 1335 |
1355 if (!force_uninstall) { | 1336 if (!force_uninstall) { |
1356 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; | 1337 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; |
1357 browser_dist->DoPostUninstallOperations(product_state->version(), | 1338 browser_dist->DoPostUninstallOperations(product_state->version(), |
1358 backup_state_file, distribution_data); | 1339 backup_state_file, distribution_data); |
1359 } | 1340 } |
1360 | 1341 |
1361 // Try and delete the preserved local state once the post-install | 1342 // Try and delete the preserved local state once the post-install |
1362 // operations are complete. | 1343 // operations are complete. |
1363 if (!backup_state_file.empty()) | 1344 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 | 1415 // If we need a reboot to continue, schedule the parent directories for |
1435 // deletion unconditionally. If they are not empty, the session manager | 1416 // deletion unconditionally. If they are not empty, the session manager |
1436 // will not delete them on reboot. | 1417 // will not delete them on reboot. |
1437 ScheduleParentAndGrandparentForDeletion(target_path); | 1418 ScheduleParentAndGrandparentForDeletion(target_path); |
1438 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { | 1419 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { |
1439 *uninstall_status = UNINSTALL_FAILED; | 1420 *uninstall_status = UNINSTALL_FAILED; |
1440 } | 1421 } |
1441 } | 1422 } |
1442 | 1423 |
1443 } // namespace installer | 1424 } // namespace installer |
OLD | NEW |