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 #include <stddef.h> | 10 #include <stddef.h> |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 if (base::DirectoryExists(temp_path)) { | 72 if (base::DirectoryExists(temp_path)) { |
73 SelfCleaningTempDir temp_dir; | 73 SelfCleaningTempDir temp_dir; |
74 if (!temp_dir.Initialize(target_path.DirName(), | 74 if (!temp_dir.Initialize(target_path.DirName(), |
75 installer::kInstallTempDir) || | 75 installer::kInstallTempDir) || |
76 !temp_dir.Delete()) { | 76 !temp_dir.Delete()) { |
77 LOG(ERROR) << "Failed to delete temp dir " << temp_path.value(); | 77 LOG(ERROR) << "Failed to delete temp dir " << temp_path.value(); |
78 } | 78 } |
79 } | 79 } |
80 } | 80 } |
81 | 81 |
82 // Iterates over the list of distribution types in |dist_types|, and | |
83 // adds to |update_list| the work item to update the corresponding "ap" | |
84 // registry value specified in |channel_info|. | |
85 void AddChannelValueUpdateWorkItems( | |
86 const InstallationState& original_state, | |
87 const InstallerState& installer_state, | |
88 const ChannelInfo& channel_info, | |
89 const std::vector<BrowserDistribution::Type>& dist_types, | |
90 WorkItemList* update_list) { | |
91 const bool system_level = installer_state.system_install(); | |
92 const HKEY reg_root = installer_state.root_key(); | |
93 for (size_t i = 0; i < dist_types.size(); ++i) { | |
94 BrowserDistribution::Type dist_type = dist_types[i]; | |
95 const ProductState* product_state = | |
96 original_state.GetProductState(system_level, dist_type); | |
97 // Only modify other products if they're installed and multi. | |
98 if (product_state != NULL && | |
99 product_state->is_multi_install() && | |
100 !product_state->channel().Equals(channel_info)) { | |
101 BrowserDistribution* other_dist = | |
102 BrowserDistribution::GetSpecificDistribution(dist_type); | |
103 update_list->AddSetRegValueWorkItem(reg_root, | |
104 other_dist->GetStateKey(), | |
105 KEY_WOW64_32KEY, | |
106 google_update::kRegApField, | |
107 channel_info.value(), | |
108 true); | |
109 } else { | |
110 LOG_IF(ERROR, | |
111 product_state != NULL && product_state->is_multi_install()) | |
112 << "Channel value for " | |
113 << BrowserDistribution::GetSpecificDistribution( | |
114 dist_type)->GetDisplayName() | |
115 << " is somehow already set to the desired new value of " | |
116 << channel_info.value(); | |
117 } | |
118 } | |
119 } | |
120 | |
121 // Makes appropriate changes to the Google Update "ap" value in the registry. | |
122 // Specifically, removes the flags associated with this product ("-chrome" or | |
123 // "-chromeframe") from the "ap" values for all other installed products and for | |
124 // the multi-installer package. | |
125 void ProcessGoogleUpdateItems(const InstallationState& original_state, | |
126 const InstallerState& installer_state, | |
127 const Product& product) { | |
128 DCHECK(installer_state.is_multi_install()); | |
129 const bool system_level = installer_state.system_install(); | |
130 BrowserDistribution* distribution = product.distribution(); | |
131 const ProductState* product_state = | |
132 original_state.GetNonVersionedProductState(system_level, | |
133 distribution->GetType()); | |
134 ChannelInfo channel_info; | |
135 | |
136 // Remove product's flags from the channel value. | |
137 channel_info.set_value(product_state->channel().value()); | |
138 const bool modified = product.SetChannelFlags(false, &channel_info); | |
139 | |
140 // Apply the new channel value to all other products and to the multi package. | |
141 if (modified) { | |
142 std::unique_ptr<WorkItemList> update_list(WorkItem::CreateWorkItemList()); | |
143 update_list->set_log_message("Channel Value Update"); | |
144 update_list->set_best_effort(true); | |
145 update_list->set_rollback_enabled(false); | |
146 std::vector<BrowserDistribution::Type> dist_types; | |
147 for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { | |
148 BrowserDistribution::Type other_dist_type = | |
149 static_cast<BrowserDistribution::Type>(i); | |
150 if (distribution->GetType() != other_dist_type) | |
151 dist_types.push_back(other_dist_type); | |
152 } | |
153 AddChannelValueUpdateWorkItems(original_state, installer_state, | |
154 channel_info, dist_types, | |
155 update_list.get()); | |
156 update_list->Do(); | |
157 } | |
158 } | |
159 | |
160 // Processes uninstall WorkItems from install_worker in no-rollback-list. | 82 // Processes uninstall WorkItems from install_worker in no-rollback-list. |
161 void ProcessChromeWorkItems(const InstallerState& installer_state, | 83 void ProcessChromeWorkItems(const InstallerState& installer_state, |
162 const Product& product) { | 84 const Product& product) { |
163 std::unique_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList()); | 85 std::unique_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList()); |
164 work_item_list->set_log_message( | 86 work_item_list->set_log_message( |
165 "Cleanup OS upgrade command and deprecated per-user registrations"); | 87 "Cleanup OS upgrade command and deprecated per-user registrations"); |
166 work_item_list->set_best_effort(true); | 88 work_item_list->set_best_effort(true); |
167 work_item_list->set_rollback_enabled(false); | 89 work_item_list->set_rollback_enabled(false); |
168 AddOsUpgradeWorkItems(installer_state, base::FilePath(), base::Version(), | 90 AddOsUpgradeWorkItems(installer_state, base::FilePath(), base::Version(), |
169 product, work_item_list.get()); | 91 product, work_item_list.get()); |
170 // Perform a best-effort cleanup of per-user keys. On system-level installs | 92 // Perform a best-effort cleanup of per-user keys. On system-level installs |
171 // this will only cleanup keys for the user running the uninstall but it was | 93 // this will only cleanup keys for the user running the uninstall but it was |
172 // considered that this was good enough (better than triggering Active Setup | 94 // considered that this was good enough (better than triggering Active Setup |
173 // for all users solely for this cleanup). | 95 // for all users solely for this cleanup). |
174 AddCleanupDeprecatedPerUserRegistrationsWorkItems(product, | 96 AddCleanupDeprecatedPerUserRegistrationsWorkItems(product, |
175 work_item_list.get()); | 97 work_item_list.get()); |
176 work_item_list->Do(); | 98 work_item_list->Do(); |
177 } | 99 } |
178 | 100 |
179 void ProcessIELowRightsPolicyWorkItems(const InstallerState& installer_state) { | |
180 std::unique_ptr<WorkItemList> work_items(WorkItem::CreateWorkItemList()); | |
181 work_items->set_log_message("Delete old IE low rights policy"); | |
182 work_items->set_best_effort(true); | |
183 work_items->set_rollback_enabled(false); | |
184 AddDeleteOldIELowRightsPolicyWorkItems(installer_state, work_items.get()); | |
185 work_items->Do(); | |
186 RefreshElevationPolicy(); | |
187 } | |
188 | |
189 void ClearRlzProductState() { | 101 void ClearRlzProductState() { |
190 const rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX, | 102 const rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX, |
191 rlz_lib::CHROME_HOME_PAGE, | 103 rlz_lib::CHROME_HOME_PAGE, |
192 rlz_lib::CHROME_APP_LIST, | 104 rlz_lib::CHROME_APP_LIST, |
193 rlz_lib::NO_ACCESS_POINT}; | 105 rlz_lib::NO_ACCESS_POINT}; |
194 | 106 |
195 rlz_lib::ClearProductState(rlz_lib::CHROME, points); | 107 rlz_lib::ClearProductState(rlz_lib::CHROME, points); |
196 | 108 |
197 // If chrome has been reactivated, clear all events for this brand as well. | 109 // If chrome has been reactivated, clear all events for this brand as well. |
198 base::string16 reactivation_brand_wide; | 110 base::string16 reactivation_brand_wide; |
199 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand_wide)) { | 111 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand_wide)) { |
200 std::string reactivation_brand(base::UTF16ToASCII(reactivation_brand_wide)); | 112 std::string reactivation_brand(base::UTF16ToASCII(reactivation_brand_wide)); |
201 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str()); | 113 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str()); |
202 rlz_lib::ClearProductState(rlz_lib::CHROME, points); | 114 rlz_lib::ClearProductState(rlz_lib::CHROME, points); |
203 } | 115 } |
204 } | 116 } |
205 | 117 |
206 // Returns whether setup.exe should be removed based on the original and | 118 // Removes all files from the installer directory. Returns false in case of an |
207 // installer states: | 119 // error. |
208 // * non-multi product being uninstalled: remove setup.exe | 120 bool RemoveInstallerFiles(const base::FilePath& installer_directory) { |
209 // * any multi product left: keep setup.exe | |
210 bool CheckShouldRemoveSetup(const InstallationState& original_state, | |
211 const InstallerState& installer_state) { | |
212 // If any multi-install product is left we must leave the installer and | |
213 // archive. | |
214 if (!installer_state.is_multi_install()) { | |
215 VLOG(1) << "Removing all installer files for a non-multi installation."; | |
216 } else { | |
217 // Loop through all known products... | |
218 for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { | |
219 BrowserDistribution::Type dist_type = | |
220 static_cast<BrowserDistribution::Type>(i); | |
221 const ProductState* product_state = original_state.GetProductState( | |
222 installer_state.system_install(), dist_type); | |
223 // If the product is installed, in multi mode, and is not part of the | |
224 // active uninstallation... | |
225 if (product_state && product_state->is_multi_install() && | |
226 !installer_state.FindProduct(dist_type)) { | |
227 // setup.exe will not be removed as there is a remaining multi-install | |
228 // product. | |
229 VLOG(1) << "Keeping all installer files due to a remaining " | |
230 << "multi-install product."; | |
231 return false; | |
232 } | |
233 } | |
234 VLOG(1) << "Removing all installer files."; | |
235 } | |
236 return true; | |
237 } | |
238 | |
239 // Removes all files from the installer directory, leaving setup.exe iff | |
240 // |remove_setup| is false. | |
241 // Returns false in case of an error. | |
242 bool RemoveInstallerFiles(const base::FilePath& installer_directory, | |
243 bool remove_setup) { | |
244 base::FileEnumerator file_enumerator( | 121 base::FileEnumerator file_enumerator( |
245 installer_directory, | 122 installer_directory, |
246 false, | 123 false, |
247 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); | 124 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); |
248 bool success = true; | 125 bool success = true; |
249 | 126 |
250 base::FilePath setup_exe_base_name(installer::kSetupExe); | 127 base::FilePath setup_exe_base_name(installer::kSetupExe); |
251 | 128 |
252 for (base::FilePath to_delete = file_enumerator.Next(); !to_delete.empty(); | 129 for (base::FilePath to_delete = file_enumerator.Next(); !to_delete.empty(); |
253 to_delete = file_enumerator.Next()) { | 130 to_delete = file_enumerator.Next()) { |
254 if (!remove_setup && to_delete.BaseName() == setup_exe_base_name) | |
255 continue; | |
256 | |
257 VLOG(1) << "Deleting installer path " << to_delete.value(); | 131 VLOG(1) << "Deleting installer path " << to_delete.value(); |
258 if (!base::DeleteFile(to_delete, true)) { | 132 if (!base::DeleteFile(to_delete, true)) { |
259 LOG(ERROR) << "Failed to delete path: " << to_delete.value(); | 133 LOG(ERROR) << "Failed to delete path: " << to_delete.value(); |
260 success = false; | 134 success = false; |
261 } | 135 } |
262 } | 136 } |
263 | 137 |
264 return success; | 138 return success; |
265 } | 139 } |
266 | 140 |
267 // Kills all Chrome processes, immediately. | 141 // Kills all Chrome processes, immediately. |
268 void CloseAllChromeProcesses() { | 142 void CloseAllChromeProcesses() { |
269 base::CleanupProcesses(installer::kChromeExe, base::TimeDelta(), | 143 base::CleanupProcesses(installer::kChromeExe, base::TimeDelta(), |
270 content::RESULT_CODE_HUNG, NULL); | 144 content::RESULT_CODE_HUNG, NULL); |
271 base::CleanupProcesses(installer::kNaClExe, base::TimeDelta(), | 145 base::CleanupProcesses(installer::kNaClExe, base::TimeDelta(), |
272 content::RESULT_CODE_HUNG, NULL); | 146 content::RESULT_CODE_HUNG, NULL); |
273 } | 147 } |
274 | 148 |
275 // 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. | |
277 void CloseChromeFrameHelperProcess() { | |
278 HWND window = FindWindow(installer::kChromeFrameHelperWndClass, NULL); | |
279 if (!::IsWindow(window)) | |
280 return; | |
281 | |
282 const DWORD kWaitMs = 3000; | |
283 | |
284 DWORD pid = 0; | |
285 ::GetWindowThreadProcessId(window, &pid); | |
286 DCHECK_NE(pid, 0U); | |
287 base::win::ScopedHandle process(::OpenProcess(SYNCHRONIZE, FALSE, pid)); | |
288 PLOG_IF(INFO, !process.IsValid()) << "Failed to open process: " << pid; | |
289 | |
290 bool kill = true; | |
291 if (SendMessageTimeout(window, WM_CLOSE, 0, 0, SMTO_BLOCK, kWaitMs, NULL) && | |
292 process.IsValid()) { | |
293 VLOG(1) << "Waiting for " << installer::kChromeFrameHelperExe; | |
294 DWORD wait = ::WaitForSingleObject(process.Get(), kWaitMs); | |
295 if (wait != WAIT_OBJECT_0) { | |
296 LOG(WARNING) << "Wait for " << installer::kChromeFrameHelperExe | |
297 << " to exit failed or timed out."; | |
298 } else { | |
299 kill = false; | |
300 VLOG(1) << installer::kChromeFrameHelperExe << " exited normally."; | |
301 } | |
302 } | |
303 | |
304 if (kill) { | |
305 VLOG(1) << installer::kChromeFrameHelperExe << " hung. Killing."; | |
306 base::CleanupProcesses(installer::kChromeFrameHelperExe, base::TimeDelta(), | |
307 content::RESULT_CODE_HUNG, NULL); | |
308 } | |
309 } | |
310 | |
311 // Updates shortcuts to |old_target_exe| that have non-empty args, making them | 149 // Updates shortcuts to |old_target_exe| that have non-empty args, making them |
312 // target |new_target_exe| instead. The non-empty args requirement is a | 150 // target |new_target_exe| instead. The non-empty args requirement is a |
313 // heuristic to determine whether a shortcut is "user-generated". This routine | 151 // heuristic to determine whether a shortcut is "user-generated". This routine |
314 // can only be called for user-level installs. | 152 // can only be called for user-level installs. |
315 void RetargetUserShortcutsWithArgs(const InstallerState& installer_state, | 153 void RetargetUserShortcutsWithArgs(const InstallerState& installer_state, |
316 const Product& product, | 154 const Product& product, |
317 const base::FilePath& old_target_exe, | 155 const base::FilePath& old_target_exe, |
318 const base::FilePath& new_target_exe) { | 156 const base::FilePath& new_target_exe) { |
319 if (installer_state.system_install()) { | 157 if (installer_state.system_install()) { |
320 NOTREACHED(); | 158 NOTREACHED(); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 if (!base::IsDirectoryEmpty(path)) | 226 if (!base::IsDirectoryEmpty(path)) |
389 return DELETE_NOT_EMPTY; | 227 return DELETE_NOT_EMPTY; |
390 | 228 |
391 if (base::DeleteFile(path, true)) | 229 if (base::DeleteFile(path, true)) |
392 return DELETE_SUCCEEDED; | 230 return DELETE_SUCCEEDED; |
393 | 231 |
394 LOG(ERROR) << "Failed to delete folder: " << path.value(); | 232 LOG(ERROR) << "Failed to delete folder: " << path.value(); |
395 return DELETE_FAILED; | 233 return DELETE_FAILED; |
396 } | 234 } |
397 | 235 |
398 // Get the user data directory, which is *not* DIR_USER_DATA for Chrome Frame. | 236 // Get the user data directory. |
399 // TODO(grt): Remove Chrome Frame uninstall support when usage is low enough. | |
400 base::FilePath GetUserDataDir(const Product& product) { | 237 base::FilePath GetUserDataDir(const Product& product) { |
401 base::FilePath path; | 238 base::FilePath path; |
402 bool is_chrome_frame = product.is_chrome_frame(); | 239 if (!PathService::Get(chrome::DIR_USER_DATA, &path)) |
403 int key = is_chrome_frame ? base::DIR_LOCAL_APP_DATA : chrome::DIR_USER_DATA; | |
404 if (!PathService::Get(key, &path)) | |
405 return base::FilePath(); | 240 return base::FilePath(); |
406 if (is_chrome_frame) { | |
407 path = path.Append(product.distribution()->GetInstallSubDir()); | |
408 path = path.Append(chrome::kUserDataDirname); | |
409 } | |
410 return path; | 241 return path; |
411 } | 242 } |
412 | 243 |
413 // Creates a copy of the local state file and returns a path to the copy. | 244 // Creates a copy of the local state file and returns a path to the copy. |
414 base::FilePath BackupLocalStateFile(const base::FilePath& user_data_dir) { | 245 base::FilePath BackupLocalStateFile(const base::FilePath& user_data_dir) { |
415 base::FilePath backup; | 246 base::FilePath backup; |
416 base::FilePath state_file(user_data_dir.Append(chrome::kLocalStateFilename)); | 247 base::FilePath state_file(user_data_dir.Append(chrome::kLocalStateFilename)); |
417 if (!base::CreateTemporaryFile(&backup)) | 248 if (!base::CreateTemporaryFile(&backup)) |
418 LOG(ERROR) << "Failed to create temporary file for Local State."; | 249 LOG(ERROR) << "Failed to create temporary file for Local State."; |
419 else | 250 else |
420 base::CopyFile(state_file, backup); | 251 base::CopyFile(state_file, backup); |
421 return backup; | 252 return backup; |
422 } | 253 } |
423 | 254 |
424 // Deletes a given user data directory as well as the containing product | 255 // Deletes a given user data directory as well as the containing product |
425 // directories if they are empty (e.g., "Google\Chrome"). | 256 // directories if they are empty (e.g., "Google\Chrome"). |
426 DeleteResult DeleteUserDataDir(const base::FilePath& user_data_dir, | 257 DeleteResult DeleteUserDataDir(const base::FilePath& user_data_dir) { |
427 bool schedule_on_failure) { | |
428 if (user_data_dir.empty()) | 258 if (user_data_dir.empty()) |
429 return DELETE_SUCCEEDED; | 259 return DELETE_SUCCEEDED; |
430 | 260 |
431 DeleteResult result = DELETE_SUCCEEDED; | 261 DeleteResult result = DELETE_SUCCEEDED; |
432 VLOG(1) << "Deleting user profile " << user_data_dir.value(); | 262 VLOG(1) << "Deleting user profile " << user_data_dir.value(); |
433 if (!base::DeleteFile(user_data_dir, true)) { | 263 if (!base::DeleteFile(user_data_dir, true)) { |
434 LOG(ERROR) << "Failed to delete user profile dir: " | 264 LOG(ERROR) << "Failed to delete user profile dir: " |
435 << user_data_dir.value(); | 265 << user_data_dir.value(); |
436 if (schedule_on_failure) { | 266 result = DELETE_FAILED; |
437 ScheduleDirectoryForDeletion(user_data_dir); | |
438 result = DELETE_REQUIRES_REBOOT; | |
439 } else { | |
440 result = DELETE_FAILED; | |
441 } | |
442 } | 267 } |
443 | 268 |
444 if (result == DELETE_REQUIRES_REBOOT) { | 269 const base::FilePath product_dir1(user_data_dir.DirName()); |
445 ScheduleParentAndGrandparentForDeletion(user_data_dir); | 270 if (!product_dir1.empty() && |
446 } else { | 271 DeleteEmptyDir(product_dir1) == DELETE_SUCCEEDED) { |
447 const base::FilePath product_dir1(user_data_dir.DirName()); | 272 const base::FilePath product_dir2(product_dir1.DirName()); |
448 if (!product_dir1.empty() && | 273 if (!product_dir2.empty()) |
449 DeleteEmptyDir(product_dir1) == DELETE_SUCCEEDED) { | 274 DeleteEmptyDir(product_dir2); |
450 const base::FilePath product_dir2(product_dir1.DirName()); | |
451 if (!product_dir2.empty()) | |
452 DeleteEmptyDir(product_dir2); | |
453 } | |
454 } | 275 } |
455 | 276 |
456 return result; | 277 return result; |
457 } | 278 } |
458 | 279 |
459 // Moves setup to a temporary file, outside of the install folder. Also attempts | 280 // Moves setup to a temporary file, outside of the install folder. Also attempts |
460 // to change the current directory to the TMP directory. On Windows, each | 281 // to change the current directory to the TMP directory. On Windows, each |
461 // process has a handle to its CWD. If setup.exe's CWD happens to be within the | 282 // process has a handle to its CWD. If setup.exe's CWD happens to be within the |
462 // install directory, deletion will fail as a result of the open handle. | 283 // install directory, deletion will fail as a result of the open handle. |
463 bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state, | 284 bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state, |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 if (!installer_directory.empty() && | 366 if (!installer_directory.empty() && |
546 (to_delete == installer_directory || | 367 (to_delete == installer_directory || |
547 installer_directory.IsParent(to_delete) || | 368 installer_directory.IsParent(to_delete) || |
548 to_delete.IsParent(installer_directory))) { | 369 to_delete.IsParent(installer_directory))) { |
549 continue; | 370 continue; |
550 } | 371 } |
551 | 372 |
552 VLOG(1) << "Deleting install path " << to_delete.value(); | 373 VLOG(1) << "Deleting install path " << to_delete.value(); |
553 if (!base::DeleteFile(to_delete, true)) { | 374 if (!base::DeleteFile(to_delete, true)) { |
554 LOG(ERROR) << "Failed to delete path (1st try): " << to_delete.value(); | 375 LOG(ERROR) << "Failed to delete path (1st try): " << to_delete.value(); |
555 if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) { | 376 // Try closing any running Chrome processes and deleting files once |
556 // We don't try killing Chrome processes for Chrome Frame builds since | 377 // again. |
557 // that is unlikely to help. Instead, schedule files for deletion and | 378 CloseAllChromeProcesses(); |
558 // return a value that will trigger a reboot prompt. | 379 if (!base::DeleteFile(to_delete, true)) { |
559 base::FileEnumerator::FileInfo find_info = file_enumerator.GetInfo(); | 380 LOG(ERROR) << "Failed to delete path (2nd try): " << to_delete.value(); |
560 if (find_info.IsDirectory()) | 381 result = DELETE_FAILED; |
561 ScheduleDirectoryForDeletion(to_delete); | 382 break; |
562 else | |
563 ScheduleFileSystemEntityForDeletion(to_delete); | |
564 result = DELETE_REQUIRES_REBOOT; | |
565 } else { | |
566 // Try closing any running Chrome processes and deleting files once | |
567 // again. | |
568 CloseAllChromeProcesses(); | |
569 if (!base::DeleteFile(to_delete, true)) { | |
570 LOG(ERROR) << "Failed to delete path (2nd try): " | |
571 << to_delete.value(); | |
572 result = DELETE_FAILED; | |
573 break; | |
574 } | |
575 } | 383 } |
576 } | 384 } |
577 } | 385 } |
578 | 386 |
579 return result; | 387 return result; |
580 } | 388 } |
581 | 389 |
582 // This method checks if Chrome is currently running or if the user has | 390 // This method checks if Chrome is currently running or if the user has |
583 // cancelled the uninstall operation by clicking Cancel on the confirmation | 391 // cancelled the uninstall operation by clicking Cancel on the confirmation |
584 // box that Chrome pops up. | 392 // box that Chrome pops up. |
(...skipping 24 matching lines...) Expand all Loading... |
609 | 417 |
610 if (exit_code == chrome::RESULT_CODE_UNINSTALL_DELETE_PROFILE) | 418 if (exit_code == chrome::RESULT_CODE_UNINSTALL_DELETE_PROFILE) |
611 return installer::UNINSTALL_DELETE_PROFILE; | 419 return installer::UNINSTALL_DELETE_PROFILE; |
612 } else { | 420 } else { |
613 PLOG(ERROR) << "Failed to launch chrome.exe for uninstall confirmation."; | 421 PLOG(ERROR) << "Failed to launch chrome.exe for uninstall confirmation."; |
614 } | 422 } |
615 | 423 |
616 return installer::UNINSTALL_CONFIRMED; | 424 return installer::UNINSTALL_CONFIRMED; |
617 } | 425 } |
618 | 426 |
619 bool ShouldDeleteProfile(const InstallerState& installer_state, | 427 bool ShouldDeleteProfile(const base::CommandLine& cmd_line, |
620 const base::CommandLine& cmd_line, | 428 InstallStatus status) { |
621 InstallStatus status, | 429 return status == installer::UNINSTALL_DELETE_PROFILE || |
622 const Product& product) { | 430 cmd_line.HasSwitch(installer::switches::kDeleteProfile); |
623 bool should_delete = false; | |
624 | |
625 // Chrome Frame uninstallations always want to delete the profile (we have no | |
626 // UI to prompt otherwise and the profile stores no useful data anyway) | |
627 // unless they are managed by MSI. MSI uninstalls will explicitly include | |
628 // the --delete-profile flag to distinguish them from MSI upgrades. | |
629 if (product.is_chrome_frame() && !installer_state.is_msi()) { | |
630 should_delete = true; | |
631 } else if (product.is_chrome()) { | |
632 should_delete = | |
633 status == installer::UNINSTALL_DELETE_PROFILE || | |
634 cmd_line.HasSwitch(installer::switches::kDeleteProfile); | |
635 } | |
636 | |
637 return should_delete; | |
638 } | 431 } |
639 | 432 |
640 // Removes XP-era filetype registration making Chrome the default browser. | 433 // Removes XP-era filetype registration making Chrome the default browser. |
641 // MSDN (see http://msdn.microsoft.com/library/windows/desktop/cc144148.aspx) | 434 // MSDN (see http://msdn.microsoft.com/library/windows/desktop/cc144148.aspx) |
642 // tells us not to do this, but certain applications break following | 435 // tells us not to do this, but certain applications break following |
643 // uninstallation if we don't. | 436 // uninstallation if we don't. |
644 void RemoveFiletypeRegistration(const InstallerState& installer_state, | 437 void RemoveFiletypeRegistration(const InstallerState& installer_state, |
645 HKEY root, | 438 HKEY root, |
646 const base::string16& browser_entry_suffix) { | 439 const base::string16& browser_entry_suffix) { |
647 base::string16 classes_path(ShellUtil::kRegClasses); | 440 base::string16 classes_path(ShellUtil::kRegClasses); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 // Removes Active Setup entries from the registry. This cannot be done through | 519 // Removes Active Setup entries from the registry. This cannot be done through |
727 // a work items list as usual because of different paths based on conditionals, | 520 // a work items list as usual because of different paths based on conditionals, |
728 // but otherwise respects the no rollback/best effort uninstall mentality. | 521 // but otherwise respects the no rollback/best effort uninstall mentality. |
729 // This will only apply for system-level installs of Chrome/Chromium and will be | 522 // This will only apply for system-level installs of Chrome/Chromium and will be |
730 // a no-op for all other types of installs. | 523 // a no-op for all other types of installs. |
731 void UninstallActiveSetupEntries(const InstallerState& installer_state, | 524 void UninstallActiveSetupEntries(const InstallerState& installer_state, |
732 const Product& product) { | 525 const Product& product) { |
733 VLOG(1) << "Uninstalling registry entries for Active Setup."; | 526 VLOG(1) << "Uninstalling registry entries for Active Setup."; |
734 BrowserDistribution* distribution = product.distribution(); | 527 BrowserDistribution* distribution = product.distribution(); |
735 | 528 |
736 if (!product.is_chrome() || !installer_state.system_install()) { | 529 if (!installer_state.system_install()) { |
737 const char* install_level = | 530 const char* install_level = |
738 installer_state.system_install() ? "system" : "user"; | 531 installer_state.system_install() ? "system" : "user"; |
739 VLOG(1) << "No Active Setup processing to do for " << install_level | 532 VLOG(1) << "No Active Setup processing to do for " << install_level |
740 << "-level " << distribution->GetDisplayName(); | 533 << "-level " << distribution->GetDisplayName(); |
741 return; | 534 return; |
742 } | 535 } |
743 | 536 |
744 const base::string16 active_setup_path( | 537 const base::string16 active_setup_path( |
745 InstallUtil::GetActiveSetupPath(distribution)); | 538 InstallUtil::GetActiveSetupPath(distribution)); |
746 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path, | 539 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 #endif | 589 #endif |
797 InstallUtil::DeleteRegistryKey(HKEY_CURRENT_USER, | 590 InstallUtil::DeleteRegistryKey(HKEY_CURRENT_USER, |
798 kRegistryFinchListPath, | 591 kRegistryFinchListPath, |
799 0); // wow64_access | 592 0); // wow64_access |
800 } | 593 } |
801 | 594 |
802 // Removes the persistent state for |distribution| for the current user. Note: | 595 // Removes the persistent state for |distribution| for the current user. Note: |
803 // this will not remove the state for users other than the one uninstalling | 596 // this will not remove the state for users other than the one uninstalling |
804 // Chrome on a system-level install; see RemoveBlacklistState for details. | 597 // Chrome on a system-level install; see RemoveBlacklistState for details. |
805 void RemoveDistributionRegistryState(BrowserDistribution* distribution) { | 598 void RemoveDistributionRegistryState(BrowserDistribution* distribution) { |
806 // Binaries do not store per-user state. | 599 static const base::char16* const kKeysToPreserve[] = { |
807 if (distribution->GetType() != BrowserDistribution::CHROME_BINARIES) { | 600 L"Extensions", L"NativeMessagingHosts", |
808 static const base::char16* const kKeysToPreserve[] = { | 601 }; |
809 L"Extensions", | 602 // Delete the contents of the distribution key except for those parts used by |
810 L"NativeMessagingHosts", | 603 // outsiders to configure Chrome. |
811 }; | 604 DeleteRegistryKeyPartial( |
812 // Delete the contents of the distribution key except for those parts used | 605 HKEY_CURRENT_USER, distribution->GetRegistryPath(), |
813 // by outsiders to configure Chrome. | 606 std::vector<base::string16>( |
814 DeleteRegistryKeyPartial( | 607 &kKeysToPreserve[0], |
815 HKEY_CURRENT_USER, distribution->GetRegistryPath(), | 608 &kKeysToPreserve[arraysize(kKeysToPreserve) - 1])); |
816 std::vector<base::string16>( | |
817 &kKeysToPreserve[0], | |
818 &kKeysToPreserve[arraysize(kKeysToPreserve) - 1])); | |
819 } | |
820 } | 609 } |
821 | 610 |
822 } // namespace | 611 } // namespace |
823 | 612 |
824 DeleteResult DeleteChromeDirectoriesIfEmpty( | 613 DeleteResult DeleteChromeDirectoriesIfEmpty( |
825 const base::FilePath& application_directory) { | 614 const base::FilePath& application_directory) { |
826 DeleteResult result(DeleteEmptyDir(application_directory)); | 615 DeleteResult result(DeleteEmptyDir(application_directory)); |
827 if (result == DELETE_SUCCEEDED) { | 616 if (result == DELETE_SUCCEEDED) { |
828 // Now check and delete if the parent directories are empty | 617 // Now check and delete if the parent directories are empty |
829 // For example Google\Chrome or Chromium | 618 // For example Google\Chrome or Chromium |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1034 const base::FilePath& setup_exe, | 823 const base::FilePath& setup_exe, |
1035 const Product& product, | 824 const Product& product, |
1036 bool remove_all, | 825 bool remove_all, |
1037 bool force_uninstall, | 826 bool force_uninstall, |
1038 const base::CommandLine& cmd_line) { | 827 const base::CommandLine& cmd_line) { |
1039 InstallStatus status = installer::UNINSTALL_CONFIRMED; | 828 InstallStatus status = installer::UNINSTALL_CONFIRMED; |
1040 BrowserDistribution* browser_dist = product.distribution(); | 829 BrowserDistribution* browser_dist = product.distribution(); |
1041 const base::FilePath chrome_exe( | 830 const base::FilePath chrome_exe( |
1042 installer_state.target_path().Append(installer::kChromeExe)); | 831 installer_state.target_path().Append(installer::kChromeExe)); |
1043 | 832 |
1044 bool is_chrome = product.is_chrome(); | |
1045 | |
1046 VLOG(1) << "UninstallProduct: " << browser_dist->GetDisplayName(); | 833 VLOG(1) << "UninstallProduct: " << browser_dist->GetDisplayName(); |
1047 | 834 |
1048 if (force_uninstall) { | 835 if (force_uninstall) { |
1049 // Since --force-uninstall command line option is used, we are going to | 836 // Since --force-uninstall command line option is used, we are going to |
1050 // do silent uninstall. Try to close all running Chrome instances. | 837 // do silent uninstall. Try to close all running Chrome instances. |
1051 // NOTE: We don't do this for Chrome Frame. | 838 CloseAllChromeProcesses(); |
1052 if (is_chrome) | 839 } else { |
1053 CloseAllChromeProcesses(); | |
1054 } else if (is_chrome) { | |
1055 // no --force-uninstall so lets show some UI dialog boxes. | 840 // no --force-uninstall so lets show some UI dialog boxes. |
1056 status = IsChromeActiveOrUserCancelled(installer_state, product); | 841 status = IsChromeActiveOrUserCancelled(installer_state, product); |
1057 if (status != installer::UNINSTALL_CONFIRMED && | 842 if (status != installer::UNINSTALL_CONFIRMED && |
1058 status != installer::UNINSTALL_DELETE_PROFILE) | 843 status != installer::UNINSTALL_DELETE_PROFILE) |
1059 return status; | 844 return status; |
1060 | 845 |
1061 const base::string16 suffix( | 846 const base::string16 suffix( |
1062 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe)); | 847 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe)); |
1063 | 848 |
1064 // Check if we need admin rights to cleanup HKLM (the conditions for | 849 // Check if we need admin rights to cleanup HKLM (the conditions for |
(...skipping 17 matching lines...) Expand all Loading... |
1082 new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration); | 867 new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration); |
1083 if (!suffix.empty()) { | 868 if (!suffix.empty()) { |
1084 new_cmd.AppendSwitchNative( | 869 new_cmd.AppendSwitchNative( |
1085 installer::switches::kRegisterChromeBrowserSuffix, suffix); | 870 installer::switches::kRegisterChromeBrowserSuffix, suffix); |
1086 } | 871 } |
1087 DWORD exit_code = installer::UNKNOWN_STATUS; | 872 DWORD exit_code = installer::UNKNOWN_STATUS; |
1088 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); | 873 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); |
1089 } | 874 } |
1090 } | 875 } |
1091 | 876 |
1092 if (is_chrome) { | 877 // Chrome is not in use so lets uninstall Chrome by deleting various files |
1093 // Chrome is not in use so lets uninstall Chrome by deleting various files | 878 // and registry entries. Here we will just make best effort and keep going |
1094 // and registry entries. Here we will just make best effort and keep going | 879 // in case of errors. |
1095 // in case of errors. | 880 ClearRlzProductState(); |
1096 ClearRlzProductState(); | |
1097 | 881 |
1098 auto_launch_util::DisableBackgroundStartAtLogin(); | 882 auto_launch_util::DisableBackgroundStartAtLogin(); |
1099 | 883 |
1100 // If user-level chrome is self-destructing as a result of encountering a | 884 // If user-level chrome is self-destructing as a result of encountering a |
1101 // system-level chrome, retarget owned non-default shortcuts (app shortcuts, | 885 // system-level chrome, retarget owned non-default shortcuts (app shortcuts, |
1102 // profile shortcuts, etc.) to the system-level chrome. | 886 // profile shortcuts, etc.) to the system-level chrome. |
1103 if (cmd_line.HasSwitch(installer::switches::kSelfDestruct) && | 887 if (cmd_line.HasSwitch(installer::switches::kSelfDestruct) && |
1104 !installer_state.system_install()) { | 888 !installer_state.system_install()) { |
1105 const base::FilePath system_chrome_path( | 889 const base::FilePath system_chrome_path( |
1106 GetChromeInstallPath(true, browser_dist). | 890 GetChromeInstallPath(true, browser_dist).Append(installer::kChromeExe)); |
1107 Append(installer::kChromeExe)); | 891 VLOG(1) << "Retargeting user-generated Chrome shortcuts."; |
1108 VLOG(1) << "Retargeting user-generated Chrome shortcuts."; | 892 if (base::PathExists(system_chrome_path)) { |
1109 if (base::PathExists(system_chrome_path)) { | 893 RetargetUserShortcutsWithArgs(installer_state, product, chrome_exe, |
1110 RetargetUserShortcutsWithArgs(installer_state, product, chrome_exe, | 894 system_chrome_path); |
1111 system_chrome_path); | 895 } else { |
1112 } else { | 896 LOG(ERROR) << "Retarget failed: system-level Chrome not found."; |
1113 LOG(ERROR) << "Retarget failed: system-level Chrome not found."; | |
1114 } | |
1115 } | 897 } |
| 898 } |
1116 | 899 |
1117 DeleteShortcuts(installer_state, product, chrome_exe); | 900 DeleteShortcuts(installer_state, product, chrome_exe); |
1118 } | |
1119 | 901 |
1120 // Delete the registry keys (Uninstall key and Version key). | 902 // Delete the registry keys (Uninstall key and Version key). |
1121 HKEY reg_root = installer_state.root_key(); | 903 HKEY reg_root = installer_state.root_key(); |
1122 | 904 |
1123 // Note that we must retrieve the distribution-specific data before deleting | 905 // Note that we must retrieve the distribution-specific data before deleting |
1124 // product.GetVersionKey(). | 906 // product.GetVersionKey(). |
1125 base::string16 distribution_data(browser_dist->GetDistributionData(reg_root)); | 907 base::string16 distribution_data(browser_dist->GetDistributionData(reg_root)); |
1126 | 908 |
1127 // Remove Control Panel uninstall link. | 909 // Remove Control Panel uninstall link. |
1128 if (product.ShouldCreateUninstallEntry()) { | 910 if (product.ShouldCreateUninstallEntry()) { |
1129 InstallUtil::DeleteRegistryKey( | 911 InstallUtil::DeleteRegistryKey( |
1130 reg_root, browser_dist->GetUninstallRegPath(), KEY_WOW64_32KEY); | 912 reg_root, browser_dist->GetUninstallRegPath(), KEY_WOW64_32KEY); |
1131 } | 913 } |
1132 | 914 |
1133 // Remove Omaha product key. | 915 // Remove Omaha product key. |
1134 InstallUtil::DeleteRegistryKey( | 916 InstallUtil::DeleteRegistryKey( |
1135 reg_root, browser_dist->GetVersionKey(), KEY_WOW64_32KEY); | 917 reg_root, browser_dist->GetVersionKey(), KEY_WOW64_32KEY); |
1136 | 918 |
1137 // Also try to delete the MSI value in the ClientState key (it might not be | 919 // Also try to delete the MSI value in the ClientState key (it might not be |
1138 // there). This is due to a Google Update behaviour where an uninstall and a | 920 // there). This is due to a Google Update behaviour where an uninstall and a |
1139 // rapid reinstall might result in stale values from the old ClientState key | 921 // rapid reinstall might result in stale values from the old ClientState key |
1140 // being picked up on reinstall. | 922 // being picked up on reinstall. |
1141 product.SetMsiMarker(installer_state.system_install(), false); | 923 product.SetMsiMarker(installer_state.system_install(), false); |
1142 | 924 |
1143 InstallStatus ret = installer::UNKNOWN_STATUS; | 925 InstallStatus ret = installer::UNKNOWN_STATUS; |
1144 | 926 |
1145 if (is_chrome) { | 927 const base::string16 suffix( |
1146 const base::string16 suffix( | 928 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe)); |
1147 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe)); | |
1148 | 929 |
1149 // Remove all Chrome registration keys. | 930 // Remove all Chrome registration keys. |
1150 // Registration data is put in HKCU for both system level and user level | 931 // Registration data is put in HKCU for both system level and user level |
1151 // installs. | 932 // installs. |
| 933 DeleteChromeRegistrationKeys(installer_state, browser_dist, HKEY_CURRENT_USER, |
| 934 suffix, &ret); |
| 935 |
| 936 // If the user's Chrome is registered with a suffix: it is possible that old |
| 937 // unsuffixed registrations were left in HKCU (e.g. if this install was |
| 938 // previously installed with no suffix in HKCU (old suffix rules if the user |
| 939 // is not an admin (or declined UAC at first run)) and later had to be |
| 940 // suffixed when fully registered in HKLM (e.g. when later making Chrome |
| 941 // default through the UI)). |
| 942 // Remove remaining HKCU entries with no suffix if any. |
| 943 if (!suffix.empty()) { |
1152 DeleteChromeRegistrationKeys(installer_state, browser_dist, | 944 DeleteChromeRegistrationKeys(installer_state, browser_dist, |
1153 HKEY_CURRENT_USER, suffix, &ret); | 945 HKEY_CURRENT_USER, base::string16(), &ret); |
1154 | 946 |
1155 // If the user's Chrome is registered with a suffix: it is possible that old | 947 // For similar reasons it is possible in very few installs (from |
1156 // unsuffixed registrations were left in HKCU (e.g. if this install was | 948 // 21.0.1180.0 and fixed shortly after) to be installed with the new-style |
1157 // previously installed with no suffix in HKCU (old suffix rules if the user | 949 // suffix, but have some old-style suffix registrations left behind. |
1158 // is not an admin (or declined UAC at first run)) and later had to be | 950 base::string16 old_style_suffix; |
1159 // suffixed when fully registered in HKLM (e.g. when later making Chrome | 951 if (ShellUtil::GetOldUserSpecificRegistrySuffix(&old_style_suffix) && |
1160 // default through the UI)). | 952 suffix != old_style_suffix) { |
1161 // Remove remaining HKCU entries with no suffix if any. | |
1162 if (!suffix.empty()) { | |
1163 DeleteChromeRegistrationKeys(installer_state, browser_dist, | 953 DeleteChromeRegistrationKeys(installer_state, browser_dist, |
1164 HKEY_CURRENT_USER, base::string16(), &ret); | 954 HKEY_CURRENT_USER, old_style_suffix, &ret); |
1165 | |
1166 // For similar reasons it is possible in very few installs (from | |
1167 // 21.0.1180.0 and fixed shortly after) to be installed with the new-style | |
1168 // suffix, but have some old-style suffix registrations left behind. | |
1169 base::string16 old_style_suffix; | |
1170 if (ShellUtil::GetOldUserSpecificRegistrySuffix(&old_style_suffix) && | |
1171 suffix != old_style_suffix) { | |
1172 DeleteChromeRegistrationKeys(installer_state, browser_dist, | |
1173 HKEY_CURRENT_USER, old_style_suffix, &ret); | |
1174 } | |
1175 } | 955 } |
1176 | 956 |
1177 // Chrome is registered in HKLM for all system-level installs and for | 957 // Chrome is registered in HKLM for all system-level installs and for |
1178 // user-level installs for which Chrome has been made the default browser. | 958 // user-level installs for which Chrome has been made the default browser. |
1179 // Always remove the HKLM registration for system-level installs. For | 959 // Always remove the HKLM registration for system-level installs. For |
1180 // user-level installs, only remove it if both: 1) this uninstall isn't a | 960 // user-level installs, only remove it if both: 1) this uninstall isn't a |
1181 // self destruct following the installation of a system-level Chrome | 961 // self destruct following the installation of a system-level Chrome |
1182 // (because the system-level Chrome owns the HKLM registration now), and 2) | 962 // (because the system-level Chrome owns the HKLM registration now), and 2) |
1183 // this user has made Chrome their default browser (i.e. has shell | 963 // this user has made Chrome their default browser (i.e. has shell |
1184 // integration entries registered with |suffix| (note: |suffix| will be the | 964 // integration entries registered with |suffix| (note: |suffix| will be the |
(...skipping 18 matching lines...) Expand all Loading... |
1203 | 983 |
1204 UninstallFirewallRules(browser_dist, chrome_exe); | 984 UninstallFirewallRules(browser_dist, chrome_exe); |
1205 | 985 |
1206 RemoveBlacklistState(); | 986 RemoveBlacklistState(); |
1207 | 987 |
1208 // Notify the shell that associations have changed since Chrome was likely | 988 // Notify the shell that associations have changed since Chrome was likely |
1209 // unregistered. | 989 // unregistered. |
1210 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); | 990 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); |
1211 } | 991 } |
1212 | 992 |
1213 if (installer_state.is_multi_install()) | |
1214 ProcessGoogleUpdateItems(original_state, installer_state, product); | |
1215 | |
1216 // Get the state of the installed product (if any) | 993 // Get the state of the installed product (if any) |
1217 const ProductState* product_state = | 994 const ProductState* product_state = |
1218 original_state.GetProductState(installer_state.system_install(), | 995 original_state.GetProductState(installer_state.system_install(), |
1219 browser_dist->GetType()); | 996 browser_dist->GetType()); |
1220 | 997 |
1221 // Delete shared registry keys as well (these require admin rights) if | 998 // Delete shared registry keys as well (these require admin rights) if |
1222 // remove_all option is specified. | 999 // remove_all option is specified. |
1223 if (remove_all) { | 1000 if (remove_all) { |
1224 if (!InstallUtil::IsChromeSxSProcess() && is_chrome) { | 1001 if (!InstallUtil::IsChromeSxSProcess()) { |
1225 // Delete media player registry key that exists only in HKLM. | 1002 // Delete media player registry key that exists only in HKLM. We don't |
1226 // We don't delete this key in SxS uninstall or Chrome Frame uninstall | 1003 // delete this key in SxS uninstall as we never set the key for it. |
1227 // as we never set the key for those products. | |
1228 base::string16 reg_path(installer::kMediaPlayerRegPath); | 1004 base::string16 reg_path(installer::kMediaPlayerRegPath); |
1229 reg_path.push_back(base::FilePath::kSeparators[0]); | 1005 reg_path.push_back(base::FilePath::kSeparators[0]); |
1230 reg_path.append(installer::kChromeExe); | 1006 reg_path.append(installer::kChromeExe); |
1231 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, reg_path, | 1007 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, reg_path, |
1232 WorkItem::kWow64Default); | 1008 WorkItem::kWow64Default); |
1233 | 1009 |
1234 // Remove the event log provider registration as we are going to delete | 1010 // Remove the event log provider registration as we are going to delete |
1235 // the file which serves the resources anyways. | 1011 // the file which serves the resources anyways. |
1236 DeRegisterEventLogProvider(); | 1012 DeRegisterEventLogProvider(); |
1237 } | 1013 } |
1238 | |
1239 // Unregister any dll servers that we may have registered for this | |
1240 // product. | |
1241 if (product_state) { | |
1242 std::vector<base::FilePath> com_dll_list; | |
1243 product.AddComDllList(&com_dll_list); | |
1244 base::FilePath dll_folder = installer_state.target_path().AppendASCII( | |
1245 product_state->version().GetString()); | |
1246 | |
1247 std::unique_ptr<WorkItemList> unreg_work_item_list( | |
1248 WorkItem::CreateWorkItemList()); | |
1249 | |
1250 AddRegisterComDllWorkItems(dll_folder, | |
1251 com_dll_list, | |
1252 installer_state.system_install(), | |
1253 false, // Unregister | |
1254 true, // May fail | |
1255 unreg_work_item_list.get()); | |
1256 unreg_work_item_list->Do(); | |
1257 } | |
1258 | |
1259 if (product.is_chrome_frame()) | |
1260 ProcessIELowRightsPolicyWorkItems(installer_state); | |
1261 } | |
1262 | |
1263 // Close any Chrome Frame helper processes that may be running. | |
1264 if (product.is_chrome_frame()) { | |
1265 VLOG(1) << "Closing the Chrome Frame helper process"; | |
1266 CloseChromeFrameHelperProcess(); | |
1267 } | 1014 } |
1268 | 1015 |
1269 // Finally delete all the files from Chrome folder after moving setup.exe | 1016 // Finally delete all the files from Chrome folder after moving setup.exe |
1270 // and the user's Local State to a temp location. | 1017 // and the user's Local State to a temp location. |
1271 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, | 1018 bool delete_profile = ShouldDeleteProfile(cmd_line, status); |
1272 product); | |
1273 ret = installer::UNINSTALL_SUCCESSFUL; | 1019 ret = installer::UNINSTALL_SUCCESSFUL; |
1274 | 1020 |
1275 // When deleting files, we must make sure that we're either a "single" | |
1276 // (aka non-multi) installation or we are the Chrome Binaries. | |
1277 | |
1278 base::FilePath user_data_dir(GetUserDataDir(product)); | 1021 base::FilePath user_data_dir(GetUserDataDir(product)); |
1279 base::FilePath backup_state_file; | 1022 base::FilePath backup_state_file; |
1280 if (!user_data_dir.empty()) { | 1023 if (!user_data_dir.empty()) { |
1281 backup_state_file = BackupLocalStateFile(user_data_dir); | 1024 backup_state_file = BackupLocalStateFile(user_data_dir); |
1282 } else { | 1025 } else { |
1283 LOG(ERROR) << "Could not retrieve the user's profile directory."; | 1026 LOG(ERROR) << "Could not retrieve the user's profile directory."; |
1284 ret = installer::UNINSTALL_FAILED; | 1027 ret = installer::UNINSTALL_FAILED; |
1285 delete_profile = false; | 1028 delete_profile = false; |
1286 } | 1029 } |
1287 | 1030 |
1288 if (!installer_state.is_multi_install() || product.is_chrome_binaries()) { | 1031 DeleteResult delete_result = DeleteChromeFilesAndFolders( |
1289 DeleteResult delete_result = DeleteChromeFilesAndFolders( | 1032 installer_state, base::MakeAbsoluteFilePath(setup_exe)); |
1290 installer_state, base::MakeAbsoluteFilePath(setup_exe)); | 1033 if (delete_result == DELETE_FAILED) |
1291 if (delete_result == DELETE_FAILED) { | 1034 ret = installer::UNINSTALL_FAILED; |
1292 ret = installer::UNINSTALL_FAILED; | 1035 else if (delete_result == DELETE_REQUIRES_REBOOT) |
1293 } else if (delete_result == DELETE_REQUIRES_REBOOT) { | 1036 ret = installer::UNINSTALL_REQUIRES_REBOOT; |
1294 ret = installer::UNINSTALL_REQUIRES_REBOOT; | |
1295 } | |
1296 } | |
1297 | 1037 |
1298 if (delete_profile) { | 1038 if (delete_profile) { |
1299 DeleteUserDataDir(user_data_dir, product.is_chrome_frame()); | 1039 DeleteUserDataDir(user_data_dir); |
1300 RemoveDistributionRegistryState(browser_dist); | 1040 RemoveDistributionRegistryState(browser_dist); |
1301 } | 1041 } |
1302 | 1042 |
1303 if (!force_uninstall && product_state) { | 1043 if (!force_uninstall && product_state) { |
1304 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; | 1044 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; |
1305 browser_dist->DoPostUninstallOperations(product_state->version(), | 1045 browser_dist->DoPostUninstallOperations(product_state->version(), |
1306 backup_state_file, distribution_data); | 1046 backup_state_file, distribution_data); |
1307 } | 1047 } |
1308 | 1048 |
1309 // Try and delete the preserved local state once the post-install | 1049 // Try and delete the preserved local state once the post-install |
(...skipping 18 matching lines...) Expand all Loading... |
1328 LOG(ERROR) << "No installation destination path."; | 1068 LOG(ERROR) << "No installation destination path."; |
1329 *uninstall_status = UNINSTALL_FAILED; | 1069 *uninstall_status = UNINSTALL_FAILED; |
1330 return; | 1070 return; |
1331 } | 1071 } |
1332 if (!target_path.IsParent(base::MakeAbsoluteFilePath(setup_exe))) { | 1072 if (!target_path.IsParent(base::MakeAbsoluteFilePath(setup_exe))) { |
1333 VLOG(1) << "setup.exe is not in target path. Skipping installer cleanup."; | 1073 VLOG(1) << "setup.exe is not in target path. Skipping installer cleanup."; |
1334 return; | 1074 return; |
1335 } | 1075 } |
1336 base::FilePath install_directory(setup_exe.DirName()); | 1076 base::FilePath install_directory(setup_exe.DirName()); |
1337 | 1077 |
1338 bool remove_setup = CheckShouldRemoveSetup(original_state, installer_state); | 1078 // In order to be able to remove the folder in which we're running, we need to |
1339 | 1079 // move setup.exe out of the install folder. |
1340 if (remove_setup) { | 1080 // TODO(tommi): What if the temp folder is on a different volume? |
1341 // In order to be able to remove the folder in which we're running, we | 1081 MoveSetupOutOfInstallFolder(installer_state, setup_exe); |
1342 // need to move setup.exe out of the install folder. | |
1343 // TODO(tommi): What if the temp folder is on a different volume? | |
1344 MoveSetupOutOfInstallFolder(installer_state, setup_exe); | |
1345 } | |
1346 | 1082 |
1347 // Remove files from "...\<product>\Application\<version>\Installer" | 1083 // Remove files from "...\<product>\Application\<version>\Installer" |
1348 if (!RemoveInstallerFiles(install_directory, remove_setup)) { | 1084 if (!RemoveInstallerFiles(install_directory)) { |
1349 *uninstall_status = UNINSTALL_FAILED; | 1085 *uninstall_status = UNINSTALL_FAILED; |
1350 return; | 1086 return; |
1351 } | 1087 } |
1352 | 1088 |
1353 if (!remove_setup) | |
1354 return; | |
1355 | |
1356 // Try to remove the empty directory hierarchy. | 1089 // Try to remove the empty directory hierarchy. |
1357 | 1090 |
1358 // Delete "...\<product>\Application\<version>\Installer" | 1091 // Delete "...\<product>\Application\<version>\Installer" |
1359 if (DeleteEmptyDir(install_directory) != DELETE_SUCCEEDED) { | 1092 if (DeleteEmptyDir(install_directory) != DELETE_SUCCEEDED) { |
1360 *uninstall_status = UNINSTALL_FAILED; | 1093 *uninstall_status = UNINSTALL_FAILED; |
1361 return; | 1094 return; |
1362 } | 1095 } |
1363 | 1096 |
1364 // Delete "...\<product>\Application\<version>" | 1097 // Delete "...\<product>\Application\<version>" |
1365 DeleteResult delete_result = DeleteEmptyDir(install_directory.DirName()); | 1098 DeleteResult delete_result = DeleteEmptyDir(install_directory.DirName()); |
(...skipping 11 matching lines...) Expand all Loading... |
1377 // If we need a reboot to continue, schedule the parent directories for | 1110 // If we need a reboot to continue, schedule the parent directories for |
1378 // deletion unconditionally. If they are not empty, the session manager | 1111 // deletion unconditionally. If they are not empty, the session manager |
1379 // will not delete them on reboot. | 1112 // will not delete them on reboot. |
1380 ScheduleParentAndGrandparentForDeletion(target_path); | 1113 ScheduleParentAndGrandparentForDeletion(target_path); |
1381 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { | 1114 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { |
1382 *uninstall_status = UNINSTALL_FAILED; | 1115 *uninstall_status = UNINSTALL_FAILED; |
1383 } | 1116 } |
1384 } | 1117 } |
1385 | 1118 |
1386 } // namespace installer | 1119 } // namespace installer |
OLD | NEW |