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

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

Issue 2589753002: Remove multi-install from chrome/installer/setup. (Closed)
Patch Set: sync to position 441108 Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // This file defines the methods useful for uninstalling Chrome. 5 // This file defines the methods useful for uninstalling Chrome.
6 6
7 #include "chrome/installer/setup/uninstall.h" 7 #include "chrome/installer/setup/uninstall.h"
8 8
9 #include <windows.h> 9 #include <windows.h>
10 #include <stddef.h> 10 #include <stddef.h>
11 #include <stdint.h> 11 #include <stdint.h>
12 12
13 #include <memory>
14 #include <string>
13 #include <vector> 15 #include <vector>
14 16
15 #include "base/base_paths.h" 17 #include "base/base_paths.h"
16 #include "base/bind.h" 18 #include "base/bind.h"
17 #include "base/files/file_enumerator.h" 19 #include "base/files/file_enumerator.h"
18 #include "base/files/file_util.h" 20 #include "base/files/file_util.h"
19 #include "base/macros.h" 21 #include "base/macros.h"
20 #include "base/path_service.h" 22 #include "base/path_service.h"
21 #include "base/process/kill.h" 23 #include "base/process/kill.h"
22 #include "base/strings/string16.h" 24 #include "base/strings/string16.h"
23 #include "base/strings/string_number_conversions.h" 25 #include "base/strings/string_number_conversions.h"
24 #include "base/strings/string_util.h" 26 #include "base/strings/string_util.h"
25 #include "base/strings/utf_string_conversions.h" 27 #include "base/strings/utf_string_conversions.h"
26 #include "base/win/registry.h" 28 #include "base/win/registry.h"
27 #include "base/win/scoped_handle.h"
28 #include "base/win/shortcut.h" 29 #include "base/win/shortcut.h"
29 #include "base/win/windows_version.h" 30 #include "base/win/windows_version.h"
30 #include "chrome/common/chrome_constants.h" 31 #include "chrome/common/chrome_constants.h"
31 #include "chrome/common/chrome_paths.h" 32 #include "chrome/common/chrome_paths.h"
32 #include "chrome/common/chrome_result_codes.h" 33 #include "chrome/common/chrome_result_codes.h"
33 #include "chrome/installer/setup/install.h" 34 #include "chrome/installer/setup/install.h"
34 #include "chrome/installer/setup/install_worker.h" 35 #include "chrome/installer/setup/install_worker.h"
35 #include "chrome/installer/setup/installer_state.h" 36 #include "chrome/installer/setup/installer_state.h"
36 #include "chrome/installer/setup/setup_constants.h" 37 #include "chrome/installer/setup/setup_constants.h"
37 #include "chrome/installer/setup/setup_util.h" 38 #include "chrome/installer/setup/setup_util.h"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 if (base::DirectoryExists(temp_path)) { 73 if (base::DirectoryExists(temp_path)) {
73 SelfCleaningTempDir temp_dir; 74 SelfCleaningTempDir temp_dir;
74 if (!temp_dir.Initialize(target_path.DirName(), 75 if (!temp_dir.Initialize(target_path.DirName(),
75 installer::kInstallTempDir) || 76 installer::kInstallTempDir) ||
76 !temp_dir.Delete()) { 77 !temp_dir.Delete()) {
77 LOG(ERROR) << "Failed to delete temp dir " << temp_path.value(); 78 LOG(ERROR) << "Failed to delete temp dir " << temp_path.value();
78 } 79 }
79 } 80 }
80 } 81 }
81 82
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. 83 // Processes uninstall WorkItems from install_worker in no-rollback-list.
161 void ProcessChromeWorkItems(const InstallerState& installer_state, 84 void ProcessChromeWorkItems(const InstallerState& installer_state,
162 const Product& product) { 85 const Product& product) {
163 std::unique_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList()); 86 std::unique_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList());
164 work_item_list->set_log_message( 87 work_item_list->set_log_message(
165 "Cleanup OS upgrade command and deprecated per-user registrations"); 88 "Cleanup OS upgrade command and deprecated per-user registrations");
166 work_item_list->set_best_effort(true); 89 work_item_list->set_best_effort(true);
167 work_item_list->set_rollback_enabled(false); 90 work_item_list->set_rollback_enabled(false);
168 AddOsUpgradeWorkItems(installer_state, base::FilePath(), base::Version(), 91 AddOsUpgradeWorkItems(installer_state, base::FilePath(), base::Version(),
169 product, work_item_list.get()); 92 product, work_item_list.get());
170 // Perform a best-effort cleanup of per-user keys. On system-level installs 93 // 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 94 // 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 95 // considered that this was good enough (better than triggering Active Setup
173 // for all users solely for this cleanup). 96 // for all users solely for this cleanup).
174 AddCleanupDeprecatedPerUserRegistrationsWorkItems(product, 97 AddCleanupDeprecatedPerUserRegistrationsWorkItems(product,
175 work_item_list.get()); 98 work_item_list.get());
176 work_item_list->Do(); 99 work_item_list->Do();
177 } 100 }
178 101
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() { 102 void ClearRlzProductState() {
190 const rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX, 103 const rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX,
191 rlz_lib::CHROME_HOME_PAGE, 104 rlz_lib::CHROME_HOME_PAGE,
192 rlz_lib::CHROME_APP_LIST, 105 rlz_lib::CHROME_APP_LIST,
193 rlz_lib::NO_ACCESS_POINT}; 106 rlz_lib::NO_ACCESS_POINT};
194 107
195 rlz_lib::ClearProductState(rlz_lib::CHROME, points); 108 rlz_lib::ClearProductState(rlz_lib::CHROME, points);
196 109
197 // If chrome has been reactivated, clear all events for this brand as well. 110 // If chrome has been reactivated, clear all events for this brand as well.
198 base::string16 reactivation_brand_wide; 111 base::string16 reactivation_brand_wide;
199 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand_wide)) { 112 if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand_wide)) {
200 std::string reactivation_brand(base::UTF16ToASCII(reactivation_brand_wide)); 113 std::string reactivation_brand(base::UTF16ToASCII(reactivation_brand_wide));
201 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str()); 114 rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str());
202 rlz_lib::ClearProductState(rlz_lib::CHROME, points); 115 rlz_lib::ClearProductState(rlz_lib::CHROME, points);
203 } 116 }
204 } 117 }
205 118
206 // Returns whether setup.exe should be removed based on the original and 119 // Removes all files from the installer directory. Returns false in case of an
207 // installer states: 120 // error.
208 // * non-multi product being uninstalled: remove setup.exe 121 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( 122 base::FileEnumerator file_enumerator(
245 installer_directory, 123 installer_directory,
246 false, 124 false,
247 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); 125 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
248 bool success = true; 126 bool success = true;
249 127
250 base::FilePath setup_exe_base_name(installer::kSetupExe);
251
252 for (base::FilePath to_delete = file_enumerator.Next(); !to_delete.empty(); 128 for (base::FilePath to_delete = file_enumerator.Next(); !to_delete.empty();
253 to_delete = file_enumerator.Next()) { 129 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(); 130 VLOG(1) << "Deleting installer path " << to_delete.value();
258 if (!base::DeleteFile(to_delete, true)) { 131 if (!base::DeleteFile(to_delete, true)) {
259 LOG(ERROR) << "Failed to delete path: " << to_delete.value(); 132 LOG(ERROR) << "Failed to delete path: " << to_delete.value();
260 success = false; 133 success = false;
261 } 134 }
262 } 135 }
263 136
264 return success; 137 return success;
265 } 138 }
266 139
267 // Kills all Chrome processes, immediately. 140 // Kills all Chrome processes, immediately.
268 void CloseAllChromeProcesses() { 141 void CloseAllChromeProcesses() {
269 base::CleanupProcesses(installer::kChromeExe, base::TimeDelta(), 142 base::CleanupProcesses(installer::kChromeExe, base::TimeDelta(),
270 content::RESULT_CODE_HUNG, NULL); 143 content::RESULT_CODE_HUNG, NULL);
271 base::CleanupProcesses(installer::kNaClExe, base::TimeDelta(), 144 base::CleanupProcesses(installer::kNaClExe, base::TimeDelta(),
272 content::RESULT_CODE_HUNG, NULL); 145 content::RESULT_CODE_HUNG, NULL);
273 } 146 }
274 147
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 148 // 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 149 // target |new_target_exe| instead. The non-empty args requirement is a
313 // heuristic to determine whether a shortcut is "user-generated". This routine 150 // heuristic to determine whether a shortcut is "user-generated". This routine
314 // can only be called for user-level installs. 151 // can only be called for user-level installs.
315 void RetargetUserShortcutsWithArgs(const InstallerState& installer_state, 152 void RetargetUserShortcutsWithArgs(const InstallerState& installer_state,
316 const Product& product, 153 const Product& product,
317 const base::FilePath& old_target_exe, 154 const base::FilePath& old_target_exe,
318 const base::FilePath& new_target_exe) { 155 const base::FilePath& new_target_exe) {
319 if (installer_state.system_install()) { 156 if (installer_state.system_install()) {
320 NOTREACHED(); 157 NOTREACHED();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 if (!base::IsDirectoryEmpty(path)) 225 if (!base::IsDirectoryEmpty(path))
389 return DELETE_NOT_EMPTY; 226 return DELETE_NOT_EMPTY;
390 227
391 if (base::DeleteFile(path, true)) 228 if (base::DeleteFile(path, true))
392 return DELETE_SUCCEEDED; 229 return DELETE_SUCCEEDED;
393 230
394 LOG(ERROR) << "Failed to delete folder: " << path.value(); 231 LOG(ERROR) << "Failed to delete folder: " << path.value();
395 return DELETE_FAILED; 232 return DELETE_FAILED;
396 } 233 }
397 234
398 // Get the user data directory, which is *not* DIR_USER_DATA for Chrome Frame. 235 // 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) { 236 base::FilePath GetUserDataDir(const Product& product) {
401 base::FilePath path; 237 base::FilePath path;
402 bool is_chrome_frame = product.is_chrome_frame(); 238 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(); 239 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; 240 return path;
411 } 241 }
412 242
413 // Creates a copy of the local state file and returns a path to the copy. 243 // 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) { 244 base::FilePath BackupLocalStateFile(const base::FilePath& user_data_dir) {
415 base::FilePath backup; 245 base::FilePath backup;
416 base::FilePath state_file(user_data_dir.Append(chrome::kLocalStateFilename)); 246 base::FilePath state_file(user_data_dir.Append(chrome::kLocalStateFilename));
417 if (!base::CreateTemporaryFile(&backup)) 247 if (!base::CreateTemporaryFile(&backup))
418 LOG(ERROR) << "Failed to create temporary file for Local State."; 248 LOG(ERROR) << "Failed to create temporary file for Local State.";
419 else 249 else
420 base::CopyFile(state_file, backup); 250 base::CopyFile(state_file, backup);
421 return backup; 251 return backup;
422 } 252 }
423 253
424 // Deletes a given user data directory as well as the containing product 254 // Deletes a given user data directory as well as the containing product
425 // directories if they are empty (e.g., "Google\Chrome"). 255 // directories if they are empty (e.g., "Google\Chrome").
426 DeleteResult DeleteUserDataDir(const base::FilePath& user_data_dir, 256 DeleteResult DeleteUserDataDir(const base::FilePath& user_data_dir) {
427 bool schedule_on_failure) {
428 if (user_data_dir.empty()) 257 if (user_data_dir.empty())
429 return DELETE_SUCCEEDED; 258 return DELETE_SUCCEEDED;
430 259
431 DeleteResult result = DELETE_SUCCEEDED; 260 DeleteResult result = DELETE_SUCCEEDED;
432 VLOG(1) << "Deleting user profile " << user_data_dir.value(); 261 VLOG(1) << "Deleting user profile " << user_data_dir.value();
433 if (!base::DeleteFile(user_data_dir, true)) { 262 if (!base::DeleteFile(user_data_dir, true)) {
434 LOG(ERROR) << "Failed to delete user profile dir: " 263 LOG(ERROR) << "Failed to delete user profile dir: "
435 << user_data_dir.value(); 264 << user_data_dir.value();
436 if (schedule_on_failure) { 265 result = DELETE_FAILED;
437 ScheduleDirectoryForDeletion(user_data_dir);
438 result = DELETE_REQUIRES_REBOOT;
439 } else {
440 result = DELETE_FAILED;
441 }
442 } 266 }
443 267
444 if (result == DELETE_REQUIRES_REBOOT) { 268 const base::FilePath product_dir1(user_data_dir.DirName());
445 ScheduleParentAndGrandparentForDeletion(user_data_dir); 269 if (!product_dir1.empty() &&
446 } else { 270 DeleteEmptyDir(product_dir1) == DELETE_SUCCEEDED) {
447 const base::FilePath product_dir1(user_data_dir.DirName()); 271 const base::FilePath product_dir2(product_dir1.DirName());
448 if (!product_dir1.empty() && 272 if (!product_dir2.empty())
449 DeleteEmptyDir(product_dir1) == DELETE_SUCCEEDED) { 273 DeleteEmptyDir(product_dir2);
450 const base::FilePath product_dir2(product_dir1.DirName());
451 if (!product_dir2.empty())
452 DeleteEmptyDir(product_dir2);
453 }
454 } 274 }
455 275
456 return result; 276 return result;
457 } 277 }
458 278
459 // Moves setup to a temporary file, outside of the install folder. Also attempts 279 // 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 280 // 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 281 // 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. 282 // install directory, deletion will fail as a result of the open handle.
463 bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state, 283 bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state,
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 if (!installer_directory.empty() && 365 if (!installer_directory.empty() &&
546 (to_delete == installer_directory || 366 (to_delete == installer_directory ||
547 installer_directory.IsParent(to_delete) || 367 installer_directory.IsParent(to_delete) ||
548 to_delete.IsParent(installer_directory))) { 368 to_delete.IsParent(installer_directory))) {
549 continue; 369 continue;
550 } 370 }
551 371
552 VLOG(1) << "Deleting install path " << to_delete.value(); 372 VLOG(1) << "Deleting install path " << to_delete.value();
553 if (!base::DeleteFile(to_delete, true)) { 373 if (!base::DeleteFile(to_delete, true)) {
554 LOG(ERROR) << "Failed to delete path (1st try): " << to_delete.value(); 374 LOG(ERROR) << "Failed to delete path (1st try): " << to_delete.value();
555 if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) { 375 // Try closing any running Chrome processes and deleting files once
556 // We don't try killing Chrome processes for Chrome Frame builds since 376 // again.
557 // that is unlikely to help. Instead, schedule files for deletion and 377 CloseAllChromeProcesses();
558 // return a value that will trigger a reboot prompt. 378 if (!base::DeleteFile(to_delete, true)) {
559 base::FileEnumerator::FileInfo find_info = file_enumerator.GetInfo(); 379 LOG(ERROR) << "Failed to delete path (2nd try): " << to_delete.value();
560 if (find_info.IsDirectory()) 380 result = DELETE_FAILED;
561 ScheduleDirectoryForDeletion(to_delete); 381 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 } 382 }
576 } 383 }
577 } 384 }
578 385
579 return result; 386 return result;
580 } 387 }
581 388
582 // This method checks if Chrome is currently running or if the user has 389 // This method checks if Chrome is currently running or if the user has
583 // cancelled the uninstall operation by clicking Cancel on the confirmation 390 // cancelled the uninstall operation by clicking Cancel on the confirmation
584 // box that Chrome pops up. 391 // box that Chrome pops up.
(...skipping 24 matching lines...) Expand all
609 416
610 if (exit_code == chrome::RESULT_CODE_UNINSTALL_DELETE_PROFILE) 417 if (exit_code == chrome::RESULT_CODE_UNINSTALL_DELETE_PROFILE)
611 return installer::UNINSTALL_DELETE_PROFILE; 418 return installer::UNINSTALL_DELETE_PROFILE;
612 } else { 419 } else {
613 PLOG(ERROR) << "Failed to launch chrome.exe for uninstall confirmation."; 420 PLOG(ERROR) << "Failed to launch chrome.exe for uninstall confirmation.";
614 } 421 }
615 422
616 return installer::UNINSTALL_CONFIRMED; 423 return installer::UNINSTALL_CONFIRMED;
617 } 424 }
618 425
619 bool ShouldDeleteProfile(const InstallerState& installer_state, 426 bool ShouldDeleteProfile(const base::CommandLine& cmd_line,
620 const base::CommandLine& cmd_line, 427 InstallStatus status) {
621 InstallStatus status, 428 return status == installer::UNINSTALL_DELETE_PROFILE ||
622 const Product& product) { 429 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 } 430 }
639 431
640 // Removes XP-era filetype registration making Chrome the default browser. 432 // Removes XP-era filetype registration making Chrome the default browser.
641 // MSDN (see http://msdn.microsoft.com/library/windows/desktop/cc144148.aspx) 433 // MSDN (see http://msdn.microsoft.com/library/windows/desktop/cc144148.aspx)
642 // tells us not to do this, but certain applications break following 434 // tells us not to do this, but certain applications break following
643 // uninstallation if we don't. 435 // uninstallation if we don't.
644 void RemoveFiletypeRegistration(const InstallerState& installer_state, 436 void RemoveFiletypeRegistration(const InstallerState& installer_state,
645 HKEY root, 437 HKEY root,
646 const base::string16& browser_entry_suffix) { 438 const base::string16& browser_entry_suffix) {
647 base::string16 classes_path(ShellUtil::kRegClasses); 439 base::string16 classes_path(ShellUtil::kRegClasses);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 // Removes Active Setup entries from the registry. This cannot be done through 518 // 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, 519 // a work items list as usual because of different paths based on conditionals,
728 // but otherwise respects the no rollback/best effort uninstall mentality. 520 // 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 521 // This will only apply for system-level installs of Chrome/Chromium and will be
730 // a no-op for all other types of installs. 522 // a no-op for all other types of installs.
731 void UninstallActiveSetupEntries(const InstallerState& installer_state, 523 void UninstallActiveSetupEntries(const InstallerState& installer_state,
732 const Product& product) { 524 const Product& product) {
733 VLOG(1) << "Uninstalling registry entries for Active Setup."; 525 VLOG(1) << "Uninstalling registry entries for Active Setup.";
734 BrowserDistribution* distribution = product.distribution(); 526 BrowserDistribution* distribution = product.distribution();
735 527
736 if (!product.is_chrome() || !installer_state.system_install()) { 528 if (!installer_state.system_install()) {
737 const char* install_level = 529 VLOG(1) << "No Active Setup processing to do for user-level "
738 installer_state.system_install() ? "system" : "user"; 530 << distribution->GetDisplayName();
739 VLOG(1) << "No Active Setup processing to do for " << install_level
740 << "-level " << distribution->GetDisplayName();
741 return; 531 return;
742 } 532 }
743 533
744 const base::string16 active_setup_path( 534 const base::string16 active_setup_path(
745 InstallUtil::GetActiveSetupPath(distribution)); 535 InstallUtil::GetActiveSetupPath(distribution));
746 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path, 536 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path,
747 WorkItem::kWow64Default); 537 WorkItem::kWow64Default);
748 538
749 // Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\ 539 // Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\
750 // Active Setup\\Installed Components\\{guid} 540 // Active Setup\\Installed Components\\{guid}
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 #endif 586 #endif
797 InstallUtil::DeleteRegistryKey(HKEY_CURRENT_USER, 587 InstallUtil::DeleteRegistryKey(HKEY_CURRENT_USER,
798 kRegistryFinchListPath, 588 kRegistryFinchListPath,
799 0); // wow64_access 589 0); // wow64_access
800 } 590 }
801 591
802 // Removes the persistent state for |distribution| for the current user. Note: 592 // 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 593 // this will not remove the state for users other than the one uninstalling
804 // Chrome on a system-level install; see RemoveBlacklistState for details. 594 // Chrome on a system-level install; see RemoveBlacklistState for details.
805 void RemoveDistributionRegistryState(BrowserDistribution* distribution) { 595 void RemoveDistributionRegistryState(BrowserDistribution* distribution) {
806 // Binaries do not store per-user state. 596 static const base::char16* const kKeysToPreserve[] = {
807 if (distribution->GetType() != BrowserDistribution::CHROME_BINARIES) { 597 L"Extensions", L"NativeMessagingHosts",
808 static const base::char16* const kKeysToPreserve[] = { 598 };
809 L"Extensions", 599 // Delete the contents of the distribution key except for those parts used by
810 L"NativeMessagingHosts", 600 // outsiders to configure Chrome.
811 }; 601 DeleteRegistryKeyPartial(
812 // Delete the contents of the distribution key except for those parts used 602 HKEY_CURRENT_USER, distribution->GetRegistryPath(),
813 // by outsiders to configure Chrome. 603 std::vector<base::string16>(
814 DeleteRegistryKeyPartial( 604 &kKeysToPreserve[0],
815 HKEY_CURRENT_USER, distribution->GetRegistryPath(), 605 &kKeysToPreserve[arraysize(kKeysToPreserve) - 1]));
816 std::vector<base::string16>(
817 &kKeysToPreserve[0],
818 &kKeysToPreserve[arraysize(kKeysToPreserve) - 1]));
819 }
820 } 606 }
821 607
822 } // namespace 608 } // namespace
823 609
824 DeleteResult DeleteChromeDirectoriesIfEmpty( 610 DeleteResult DeleteChromeDirectoriesIfEmpty(
825 const base::FilePath& application_directory) { 611 const base::FilePath& application_directory) {
826 DeleteResult result(DeleteEmptyDir(application_directory)); 612 DeleteResult result(DeleteEmptyDir(application_directory));
827 if (result == DELETE_SUCCEEDED) { 613 if (result == DELETE_SUCCEEDED) {
828 // Now check and delete if the parent directories are empty 614 // Now check and delete if the parent directories are empty
829 // For example Google\Chrome or Chromium 615 // For example Google\Chrome or Chromium
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 const base::FilePath& setup_exe, 820 const base::FilePath& setup_exe,
1035 const Product& product, 821 const Product& product,
1036 bool remove_all, 822 bool remove_all,
1037 bool force_uninstall, 823 bool force_uninstall,
1038 const base::CommandLine& cmd_line) { 824 const base::CommandLine& cmd_line) {
1039 InstallStatus status = installer::UNINSTALL_CONFIRMED; 825 InstallStatus status = installer::UNINSTALL_CONFIRMED;
1040 BrowserDistribution* browser_dist = product.distribution(); 826 BrowserDistribution* browser_dist = product.distribution();
1041 const base::FilePath chrome_exe( 827 const base::FilePath chrome_exe(
1042 installer_state.target_path().Append(installer::kChromeExe)); 828 installer_state.target_path().Append(installer::kChromeExe));
1043 829
1044 bool is_chrome = product.is_chrome();
1045
1046 VLOG(1) << "UninstallProduct: " << browser_dist->GetDisplayName(); 830 VLOG(1) << "UninstallProduct: " << browser_dist->GetDisplayName();
1047 831
1048 if (force_uninstall) { 832 if (force_uninstall) {
1049 // Since --force-uninstall command line option is used, we are going to 833 // Since --force-uninstall command line option is used, we are going to
1050 // do silent uninstall. Try to close all running Chrome instances. 834 // do silent uninstall. Try to close all running Chrome instances.
1051 // NOTE: We don't do this for Chrome Frame. 835 CloseAllChromeProcesses();
1052 if (is_chrome) 836 } else {
1053 CloseAllChromeProcesses();
1054 } else if (is_chrome) {
1055 // no --force-uninstall so lets show some UI dialog boxes. 837 // no --force-uninstall so lets show some UI dialog boxes.
1056 status = IsChromeActiveOrUserCancelled(installer_state, product); 838 status = IsChromeActiveOrUserCancelled(installer_state, product);
1057 if (status != installer::UNINSTALL_CONFIRMED && 839 if (status != installer::UNINSTALL_CONFIRMED &&
1058 status != installer::UNINSTALL_DELETE_PROFILE) 840 status != installer::UNINSTALL_DELETE_PROFILE)
1059 return status; 841 return status;
1060 842
1061 const base::string16 suffix( 843 const base::string16 suffix(
1062 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe)); 844 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe));
1063 845
1064 // Check if we need admin rights to cleanup HKLM (the conditions for 846 // Check if we need admin rights to cleanup HKLM (the conditions for
(...skipping 17 matching lines...) Expand all
1082 new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration); 864 new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration);
1083 if (!suffix.empty()) { 865 if (!suffix.empty()) {
1084 new_cmd.AppendSwitchNative( 866 new_cmd.AppendSwitchNative(
1085 installer::switches::kRegisterChromeBrowserSuffix, suffix); 867 installer::switches::kRegisterChromeBrowserSuffix, suffix);
1086 } 868 }
1087 DWORD exit_code = installer::UNKNOWN_STATUS; 869 DWORD exit_code = installer::UNKNOWN_STATUS;
1088 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); 870 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code);
1089 } 871 }
1090 } 872 }
1091 873
1092 if (is_chrome) { 874 // 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 875 // 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 876 // in case of errors.
1095 // in case of errors. 877 ClearRlzProductState();
1096 ClearRlzProductState();
1097 878
1098 auto_launch_util::DisableBackgroundStartAtLogin(); 879 auto_launch_util::DisableBackgroundStartAtLogin();
1099 880
1100 // If user-level chrome is self-destructing as a result of encountering a 881 // If user-level chrome is self-destructing as a result of encountering a
1101 // system-level chrome, retarget owned non-default shortcuts (app shortcuts, 882 // system-level chrome, retarget owned non-default shortcuts (app shortcuts,
1102 // profile shortcuts, etc.) to the system-level chrome. 883 // profile shortcuts, etc.) to the system-level chrome.
1103 if (cmd_line.HasSwitch(installer::switches::kSelfDestruct) && 884 if (cmd_line.HasSwitch(installer::switches::kSelfDestruct) &&
1104 !installer_state.system_install()) { 885 !installer_state.system_install()) {
1105 const base::FilePath system_chrome_path( 886 const base::FilePath system_chrome_path(
1106 GetChromeInstallPath(true, browser_dist). 887 GetChromeInstallPath(true, browser_dist).Append(installer::kChromeExe));
1107 Append(installer::kChromeExe)); 888 VLOG(1) << "Retargeting user-generated Chrome shortcuts.";
1108 VLOG(1) << "Retargeting user-generated Chrome shortcuts."; 889 if (base::PathExists(system_chrome_path)) {
1109 if (base::PathExists(system_chrome_path)) { 890 RetargetUserShortcutsWithArgs(installer_state, product, chrome_exe,
1110 RetargetUserShortcutsWithArgs(installer_state, product, chrome_exe, 891 system_chrome_path);
1111 system_chrome_path); 892 } else {
1112 } else { 893 LOG(ERROR) << "Retarget failed: system-level Chrome not found.";
1113 LOG(ERROR) << "Retarget failed: system-level Chrome not found.";
1114 }
1115 } 894 }
895 }
1116 896
1117 DeleteShortcuts(installer_state, product, chrome_exe); 897 DeleteShortcuts(installer_state, product, chrome_exe);
1118 }
1119 898
1120 // Delete the registry keys (Uninstall key and Version key). 899 // Delete the registry keys (Uninstall key and Version key).
1121 HKEY reg_root = installer_state.root_key(); 900 HKEY reg_root = installer_state.root_key();
1122 901
1123 // Note that we must retrieve the distribution-specific data before deleting 902 // Note that we must retrieve the distribution-specific data before deleting
1124 // product.GetVersionKey(). 903 // product.GetVersionKey().
1125 base::string16 distribution_data(browser_dist->GetDistributionData(reg_root)); 904 base::string16 distribution_data(browser_dist->GetDistributionData(reg_root));
1126 905
1127 // Remove Control Panel uninstall link. 906 // Remove Control Panel uninstall link.
1128 if (product.ShouldCreateUninstallEntry()) { 907 if (product.ShouldCreateUninstallEntry()) {
1129 InstallUtil::DeleteRegistryKey( 908 InstallUtil::DeleteRegistryKey(
1130 reg_root, browser_dist->GetUninstallRegPath(), KEY_WOW64_32KEY); 909 reg_root, browser_dist->GetUninstallRegPath(), KEY_WOW64_32KEY);
1131 } 910 }
1132 911
1133 // Remove Omaha product key. 912 // Remove Omaha product key.
1134 InstallUtil::DeleteRegistryKey( 913 InstallUtil::DeleteRegistryKey(
1135 reg_root, browser_dist->GetVersionKey(), KEY_WOW64_32KEY); 914 reg_root, browser_dist->GetVersionKey(), KEY_WOW64_32KEY);
1136 915
1137 // Also try to delete the MSI value in the ClientState key (it might not be 916 // 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 917 // 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 918 // rapid reinstall might result in stale values from the old ClientState key
1140 // being picked up on reinstall. 919 // being picked up on reinstall.
1141 product.SetMsiMarker(installer_state.system_install(), false); 920 product.SetMsiMarker(installer_state.system_install(), false);
1142 921
1143 InstallStatus ret = installer::UNKNOWN_STATUS; 922 InstallStatus ret = installer::UNKNOWN_STATUS;
1144 923
1145 if (is_chrome) { 924 const base::string16 suffix(
1146 const base::string16 suffix( 925 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe));
1147 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe));
1148 926
1149 // Remove all Chrome registration keys. 927 // Remove all Chrome registration keys.
1150 // Registration data is put in HKCU for both system level and user level 928 // Registration data is put in HKCU for both system level and user level
1151 // installs. 929 // installs.
930 DeleteChromeRegistrationKeys(installer_state, browser_dist, HKEY_CURRENT_USER,
931 suffix, &ret);
932
933 // If the user's Chrome is registered with a suffix: it is possible that old
934 // unsuffixed registrations were left in HKCU (e.g. if this install was
935 // previously installed with no suffix in HKCU (old suffix rules if the user
936 // is not an admin (or declined UAC at first run)) and later had to be
937 // suffixed when fully registered in HKLM (e.g. when later making Chrome
938 // default through the UI)).
939 // Remove remaining HKCU entries with no suffix if any.
940 if (!suffix.empty()) {
1152 DeleteChromeRegistrationKeys(installer_state, browser_dist, 941 DeleteChromeRegistrationKeys(installer_state, browser_dist,
1153 HKEY_CURRENT_USER, suffix, &ret); 942 HKEY_CURRENT_USER, base::string16(), &ret);
1154 943
1155 // If the user's Chrome is registered with a suffix: it is possible that old 944 // For similar reasons it is possible in very few installs (from
1156 // unsuffixed registrations were left in HKCU (e.g. if this install was 945 // 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 946 // 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 947 base::string16 old_style_suffix;
1159 // suffixed when fully registered in HKLM (e.g. when later making Chrome 948 if (ShellUtil::GetOldUserSpecificRegistrySuffix(&old_style_suffix) &&
1160 // default through the UI)). 949 suffix != old_style_suffix) {
1161 // Remove remaining HKCU entries with no suffix if any.
1162 if (!suffix.empty()) {
1163 DeleteChromeRegistrationKeys(installer_state, browser_dist, 950 DeleteChromeRegistrationKeys(installer_state, browser_dist,
1164 HKEY_CURRENT_USER, base::string16(), &ret); 951 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 } 952 }
1176 953
1177 // Chrome is registered in HKLM for all system-level installs and for 954 // 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. 955 // user-level installs for which Chrome has been made the default browser.
1179 // Always remove the HKLM registration for system-level installs. For 956 // 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 957 // 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 958 // self destruct following the installation of a system-level Chrome
1182 // (because the system-level Chrome owns the HKLM registration now), and 2) 959 // (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 960 // this user has made Chrome their default browser (i.e. has shell
1184 // integration entries registered with |suffix| (note: |suffix| will be the 961 // integration entries registered with |suffix| (note: |suffix| will be the
(...skipping 18 matching lines...) Expand all
1203 980
1204 UninstallFirewallRules(browser_dist, chrome_exe); 981 UninstallFirewallRules(browser_dist, chrome_exe);
1205 982
1206 RemoveBlacklistState(); 983 RemoveBlacklistState();
1207 984
1208 // Notify the shell that associations have changed since Chrome was likely 985 // Notify the shell that associations have changed since Chrome was likely
1209 // unregistered. 986 // unregistered.
1210 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); 987 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
1211 } 988 }
1212 989
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) 990 // Get the state of the installed product (if any)
1217 const ProductState* product_state = 991 const ProductState* product_state =
1218 original_state.GetProductState(installer_state.system_install(), 992 original_state.GetProductState(installer_state.system_install(),
1219 browser_dist->GetType()); 993 browser_dist->GetType());
1220 994
1221 // Delete shared registry keys as well (these require admin rights) if 995 // Delete shared registry keys as well (these require admin rights) if
1222 // remove_all option is specified. 996 // remove_all option is specified.
1223 if (remove_all) { 997 if (remove_all) {
1224 if (!InstallUtil::IsChromeSxSProcess() && is_chrome) { 998 if (!InstallUtil::IsChromeSxSProcess()) {
1225 // Delete media player registry key that exists only in HKLM. 999 // 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 1000 // 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); 1001 base::string16 reg_path(installer::kMediaPlayerRegPath);
1229 reg_path.push_back(base::FilePath::kSeparators[0]); 1002 reg_path.push_back(base::FilePath::kSeparators[0]);
1230 reg_path.append(installer::kChromeExe); 1003 reg_path.append(installer::kChromeExe);
1231 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, reg_path, 1004 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, reg_path,
1232 WorkItem::kWow64Default); 1005 WorkItem::kWow64Default);
1233 1006
1234 // Remove the event log provider registration as we are going to delete 1007 // Remove the event log provider registration as we are going to delete
1235 // the file which serves the resources anyways. 1008 // the file which serves the resources anyways.
1236 DeRegisterEventLogProvider(); 1009 DeRegisterEventLogProvider();
1237 } 1010 }
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 } 1011 }
1268 1012
1269 // Finally delete all the files from Chrome folder after moving setup.exe 1013 // Finally delete all the files from Chrome folder after moving setup.exe
1270 // and the user's Local State to a temp location. 1014 // and the user's Local State to a temp location.
1271 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, 1015 bool delete_profile = ShouldDeleteProfile(cmd_line, status);
1272 product);
1273 ret = installer::UNINSTALL_SUCCESSFUL; 1016 ret = installer::UNINSTALL_SUCCESSFUL;
1274 1017
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)); 1018 base::FilePath user_data_dir(GetUserDataDir(product));
1279 base::FilePath backup_state_file; 1019 base::FilePath backup_state_file;
1280 if (!user_data_dir.empty()) { 1020 if (!user_data_dir.empty()) {
1281 backup_state_file = BackupLocalStateFile(user_data_dir); 1021 backup_state_file = BackupLocalStateFile(user_data_dir);
1282 } else { 1022 } else {
1283 LOG(ERROR) << "Could not retrieve the user's profile directory."; 1023 LOG(ERROR) << "Could not retrieve the user's profile directory.";
1284 ret = installer::UNINSTALL_FAILED; 1024 ret = installer::UNINSTALL_FAILED;
1285 delete_profile = false; 1025 delete_profile = false;
1286 } 1026 }
1287 1027
1288 if (!installer_state.is_multi_install() || product.is_chrome_binaries()) { 1028 DeleteResult delete_result = DeleteChromeFilesAndFolders(
1289 DeleteResult delete_result = DeleteChromeFilesAndFolders( 1029 installer_state, base::MakeAbsoluteFilePath(setup_exe));
1290 installer_state, base::MakeAbsoluteFilePath(setup_exe)); 1030 if (delete_result == DELETE_FAILED)
1291 if (delete_result == DELETE_FAILED) { 1031 ret = installer::UNINSTALL_FAILED;
1292 ret = installer::UNINSTALL_FAILED; 1032 else if (delete_result == DELETE_REQUIRES_REBOOT)
1293 } else if (delete_result == DELETE_REQUIRES_REBOOT) { 1033 ret = installer::UNINSTALL_REQUIRES_REBOOT;
1294 ret = installer::UNINSTALL_REQUIRES_REBOOT;
1295 }
1296 }
1297 1034
1298 if (delete_profile) { 1035 if (delete_profile) {
1299 DeleteUserDataDir(user_data_dir, product.is_chrome_frame()); 1036 DeleteUserDataDir(user_data_dir);
1300 RemoveDistributionRegistryState(browser_dist); 1037 RemoveDistributionRegistryState(browser_dist);
1301 } 1038 }
1302 1039
1303 if (!force_uninstall && product_state) { 1040 if (!force_uninstall && product_state) {
1304 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; 1041 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations.";
1305 browser_dist->DoPostUninstallOperations(product_state->version(), 1042 browser_dist->DoPostUninstallOperations(product_state->version(),
1306 backup_state_file, distribution_data); 1043 backup_state_file, distribution_data);
1307 } 1044 }
1308 1045
1309 // Try and delete the preserved local state once the post-install 1046 // Try and delete the preserved local state once the post-install
(...skipping 18 matching lines...) Expand all
1328 LOG(ERROR) << "No installation destination path."; 1065 LOG(ERROR) << "No installation destination path.";
1329 *uninstall_status = UNINSTALL_FAILED; 1066 *uninstall_status = UNINSTALL_FAILED;
1330 return; 1067 return;
1331 } 1068 }
1332 if (!target_path.IsParent(base::MakeAbsoluteFilePath(setup_exe))) { 1069 if (!target_path.IsParent(base::MakeAbsoluteFilePath(setup_exe))) {
1333 VLOG(1) << "setup.exe is not in target path. Skipping installer cleanup."; 1070 VLOG(1) << "setup.exe is not in target path. Skipping installer cleanup.";
1334 return; 1071 return;
1335 } 1072 }
1336 base::FilePath install_directory(setup_exe.DirName()); 1073 base::FilePath install_directory(setup_exe.DirName());
1337 1074
1338 bool remove_setup = CheckShouldRemoveSetup(original_state, installer_state); 1075 VLOG(1) << "Removing all installer files.";
1339 1076
1340 if (remove_setup) { 1077 // In order to be able to remove the folder in which we're running, we need to
1341 // In order to be able to remove the folder in which we're running, we 1078 // move setup.exe out of the install folder.
1342 // need to move setup.exe out of the install folder. 1079 // TODO(tommi): What if the temp folder is on a different volume?
1343 // TODO(tommi): What if the temp folder is on a different volume? 1080 MoveSetupOutOfInstallFolder(installer_state, setup_exe);
1344 MoveSetupOutOfInstallFolder(installer_state, setup_exe);
1345 }
1346 1081
1347 // Remove files from "...\<product>\Application\<version>\Installer" 1082 // Remove files from "...\<product>\Application\<version>\Installer"
1348 if (!RemoveInstallerFiles(install_directory, remove_setup)) { 1083 if (!RemoveInstallerFiles(install_directory)) {
1349 *uninstall_status = UNINSTALL_FAILED; 1084 *uninstall_status = UNINSTALL_FAILED;
1350 return; 1085 return;
1351 } 1086 }
1352 1087
1353 if (!remove_setup)
1354 return;
1355
1356 // Try to remove the empty directory hierarchy. 1088 // Try to remove the empty directory hierarchy.
1357 1089
1358 // Delete "...\<product>\Application\<version>\Installer" 1090 // Delete "...\<product>\Application\<version>\Installer"
1359 if (DeleteEmptyDir(install_directory) != DELETE_SUCCEEDED) { 1091 if (DeleteEmptyDir(install_directory) != DELETE_SUCCEEDED) {
1360 *uninstall_status = UNINSTALL_FAILED; 1092 *uninstall_status = UNINSTALL_FAILED;
1361 return; 1093 return;
1362 } 1094 }
1363 1095
1364 // Delete "...\<product>\Application\<version>" 1096 // Delete "...\<product>\Application\<version>"
1365 DeleteResult delete_result = DeleteEmptyDir(install_directory.DirName()); 1097 DeleteResult delete_result = DeleteEmptyDir(install_directory.DirName());
(...skipping 11 matching lines...) Expand all
1377 // If we need a reboot to continue, schedule the parent directories for 1109 // If we need a reboot to continue, schedule the parent directories for
1378 // deletion unconditionally. If they are not empty, the session manager 1110 // deletion unconditionally. If they are not empty, the session manager
1379 // will not delete them on reboot. 1111 // will not delete them on reboot.
1380 ScheduleParentAndGrandparentForDeletion(target_path); 1112 ScheduleParentAndGrandparentForDeletion(target_path);
1381 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { 1113 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) {
1382 *uninstall_status = UNINSTALL_FAILED; 1114 *uninstall_status = UNINSTALL_FAILED;
1383 } 1115 }
1384 } 1116 }
1385 1117
1386 } // namespace installer 1118 } // namespace installer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698