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

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

Issue 2589753002: Remove multi-install from chrome/installer/setup. (Closed)
Patch Set: sync to position 442053 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
« no previous file with comments | « chrome/installer/setup/setup_util_unittest.cc ('k') | chrome/installer/util/install_util.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 again.
556 // We don't try killing Chrome processes for Chrome Frame builds since 376 CloseAllChromeProcesses();
557 // that is unlikely to help. Instead, schedule files for deletion and 377 if (!base::DeleteFile(to_delete, true)) {
558 // return a value that will trigger a reboot prompt. 378 LOG(ERROR) << "Failed to delete path (2nd try): " << to_delete.value();
559 base::FileEnumerator::FileInfo find_info = file_enumerator.GetInfo(); 379 result = DELETE_FAILED;
560 if (find_info.IsDirectory()) 380 break;
561 ScheduleDirectoryForDeletion(to_delete);
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 } 381 }
576 } 382 }
577 } 383 }
578 384
579 return result; 385 return result;
580 } 386 }
581 387
582 // This method checks if Chrome is currently running or if the user has 388 // This method checks if Chrome is currently running or if the user has
583 // cancelled the uninstall operation by clicking Cancel on the confirmation 389 // cancelled the uninstall operation by clicking Cancel on the confirmation
584 // box that Chrome pops up. 390 // box that Chrome pops up.
(...skipping 24 matching lines...) Expand all
609 415
610 if (exit_code == chrome::RESULT_CODE_UNINSTALL_DELETE_PROFILE) 416 if (exit_code == chrome::RESULT_CODE_UNINSTALL_DELETE_PROFILE)
611 return installer::UNINSTALL_DELETE_PROFILE; 417 return installer::UNINSTALL_DELETE_PROFILE;
612 } else { 418 } else {
613 PLOG(ERROR) << "Failed to launch chrome.exe for uninstall confirmation."; 419 PLOG(ERROR) << "Failed to launch chrome.exe for uninstall confirmation.";
614 } 420 }
615 421
616 return installer::UNINSTALL_CONFIRMED; 422 return installer::UNINSTALL_CONFIRMED;
617 } 423 }
618 424
619 bool ShouldDeleteProfile(const InstallerState& installer_state, 425 bool ShouldDeleteProfile(const base::CommandLine& cmd_line,
620 const base::CommandLine& cmd_line, 426 InstallStatus status) {
621 InstallStatus status, 427 return status == installer::UNINSTALL_DELETE_PROFILE ||
622 const Product& product) { 428 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 } 429 }
639 430
640 // Removes XP-era filetype registration making Chrome the default browser. 431 // Removes XP-era filetype registration making Chrome the default browser.
641 // MSDN (see http://msdn.microsoft.com/library/windows/desktop/cc144148.aspx) 432 // MSDN (see http://msdn.microsoft.com/library/windows/desktop/cc144148.aspx)
642 // tells us not to do this, but certain applications break following 433 // tells us not to do this, but certain applications break following
643 // uninstallation if we don't. 434 // uninstallation if we don't.
644 void RemoveFiletypeRegistration(const InstallerState& installer_state, 435 void RemoveFiletypeRegistration(const InstallerState& installer_state,
645 HKEY root, 436 HKEY root,
646 const base::string16& browser_entry_suffix) { 437 const base::string16& browser_entry_suffix) {
647 base::string16 classes_path(ShellUtil::kRegClasses); 438 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 517 // 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, 518 // a work items list as usual because of different paths based on conditionals,
728 // but otherwise respects the no rollback/best effort uninstall mentality. 519 // 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 520 // This will only apply for system-level installs of Chrome/Chromium and will be
730 // a no-op for all other types of installs. 521 // a no-op for all other types of installs.
731 void UninstallActiveSetupEntries(const InstallerState& installer_state, 522 void UninstallActiveSetupEntries(const InstallerState& installer_state,
732 const Product& product) { 523 const Product& product) {
733 VLOG(1) << "Uninstalling registry entries for Active Setup."; 524 VLOG(1) << "Uninstalling registry entries for Active Setup.";
734 BrowserDistribution* distribution = product.distribution(); 525 BrowserDistribution* distribution = product.distribution();
735 526
736 if (!product.is_chrome() || !installer_state.system_install()) { 527 if (!installer_state.system_install()) {
737 const char* install_level = 528 VLOG(1) << "No Active Setup processing to do for user-level "
738 installer_state.system_install() ? "system" : "user"; 529 << distribution->GetDisplayName();
739 VLOG(1) << "No Active Setup processing to do for " << install_level
740 << "-level " << distribution->GetDisplayName();
741 return; 530 return;
742 } 531 }
743 532
744 const base::string16 active_setup_path( 533 const base::string16 active_setup_path(
745 InstallUtil::GetActiveSetupPath(distribution)); 534 InstallUtil::GetActiveSetupPath(distribution));
746 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path, 535 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path,
747 WorkItem::kWow64Default); 536 WorkItem::kWow64Default);
748 537
749 // Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\ 538 // Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\
750 // Active Setup\\Installed Components\\{guid} 539 // Active Setup\\Installed Components\\{guid}
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 #endif 585 #endif
797 InstallUtil::DeleteRegistryKey(HKEY_CURRENT_USER, 586 InstallUtil::DeleteRegistryKey(HKEY_CURRENT_USER,
798 kRegistryFinchListPath, 587 kRegistryFinchListPath,
799 0); // wow64_access 588 0); // wow64_access
800 } 589 }
801 590
802 // Removes the persistent state for |distribution| for the current user. Note: 591 // 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 592 // this will not remove the state for users other than the one uninstalling
804 // Chrome on a system-level install; see RemoveBlacklistState for details. 593 // Chrome on a system-level install; see RemoveBlacklistState for details.
805 void RemoveDistributionRegistryState(BrowserDistribution* distribution) { 594 void RemoveDistributionRegistryState(BrowserDistribution* distribution) {
806 // Binaries do not store per-user state. 595 static const base::char16* const kKeysToPreserve[] = {
807 if (distribution->GetType() != BrowserDistribution::CHROME_BINARIES) { 596 L"Extensions", L"NativeMessagingHosts",
808 static const base::char16* const kKeysToPreserve[] = { 597 };
809 L"Extensions", 598 // Delete the contents of the distribution key except for those parts used by
810 L"NativeMessagingHosts", 599 // outsiders to configure Chrome.
811 }; 600 DeleteRegistryKeyPartial(
812 // Delete the contents of the distribution key except for those parts used 601 HKEY_CURRENT_USER, distribution->GetRegistryPath(),
813 // by outsiders to configure Chrome. 602 std::vector<base::string16>(
814 DeleteRegistryKeyPartial( 603 &kKeysToPreserve[0],
815 HKEY_CURRENT_USER, distribution->GetRegistryPath(), 604 &kKeysToPreserve[arraysize(kKeysToPreserve) - 1]));
816 std::vector<base::string16>(
817 &kKeysToPreserve[0],
818 &kKeysToPreserve[arraysize(kKeysToPreserve) - 1]));
819 }
820 } 605 }
821 606
822 } // namespace 607 } // namespace
823 608
824 DeleteResult DeleteChromeDirectoriesIfEmpty( 609 DeleteResult DeleteChromeDirectoriesIfEmpty(
825 const base::FilePath& application_directory) { 610 const base::FilePath& application_directory) {
826 DeleteResult result(DeleteEmptyDir(application_directory)); 611 DeleteResult result(DeleteEmptyDir(application_directory));
827 if (result == DELETE_SUCCEEDED) { 612 if (result == DELETE_SUCCEEDED) {
828 // Now check and delete if the parent directories are empty 613 // Now check and delete if the parent directories are empty
829 // For example Google\Chrome or Chromium 614 // For example Google\Chrome or Chromium
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 const base::FilePath& setup_exe, 819 const base::FilePath& setup_exe,
1035 const Product& product, 820 const Product& product,
1036 bool remove_all, 821 bool remove_all,
1037 bool force_uninstall, 822 bool force_uninstall,
1038 const base::CommandLine& cmd_line) { 823 const base::CommandLine& cmd_line) {
1039 InstallStatus status = installer::UNINSTALL_CONFIRMED; 824 InstallStatus status = installer::UNINSTALL_CONFIRMED;
1040 BrowserDistribution* browser_dist = product.distribution(); 825 BrowserDistribution* browser_dist = product.distribution();
1041 const base::FilePath chrome_exe( 826 const base::FilePath chrome_exe(
1042 installer_state.target_path().Append(installer::kChromeExe)); 827 installer_state.target_path().Append(installer::kChromeExe));
1043 828
1044 bool is_chrome = product.is_chrome();
1045
1046 VLOG(1) << "UninstallProduct: " << browser_dist->GetDisplayName(); 829 VLOG(1) << "UninstallProduct: " << browser_dist->GetDisplayName();
1047 830
1048 if (force_uninstall) { 831 if (force_uninstall) {
1049 // Since --force-uninstall command line option is used, we are going to 832 // Since --force-uninstall command line option is used, we are going to
1050 // do silent uninstall. Try to close all running Chrome instances. 833 // do silent uninstall. Try to close all running Chrome instances.
1051 // NOTE: We don't do this for Chrome Frame. 834 CloseAllChromeProcesses();
1052 if (is_chrome) 835 } else {
1053 CloseAllChromeProcesses();
1054 } else if (is_chrome) {
1055 // no --force-uninstall so lets show some UI dialog boxes. 836 // no --force-uninstall so lets show some UI dialog boxes.
1056 status = IsChromeActiveOrUserCancelled(installer_state, product); 837 status = IsChromeActiveOrUserCancelled(installer_state, product);
1057 if (status != installer::UNINSTALL_CONFIRMED && 838 if (status != installer::UNINSTALL_CONFIRMED &&
1058 status != installer::UNINSTALL_DELETE_PROFILE) 839 status != installer::UNINSTALL_DELETE_PROFILE)
1059 return status; 840 return status;
1060 841
1061 const base::string16 suffix( 842 const base::string16 suffix(
1062 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe)); 843 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe));
1063 844
1064 // Check if we need admin rights to cleanup HKLM (the conditions for 845 // 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); 863 new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration);
1083 if (!suffix.empty()) { 864 if (!suffix.empty()) {
1084 new_cmd.AppendSwitchNative( 865 new_cmd.AppendSwitchNative(
1085 installer::switches::kRegisterChromeBrowserSuffix, suffix); 866 installer::switches::kRegisterChromeBrowserSuffix, suffix);
1086 } 867 }
1087 DWORD exit_code = installer::UNKNOWN_STATUS; 868 DWORD exit_code = installer::UNKNOWN_STATUS;
1088 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code); 869 InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code);
1089 } 870 }
1090 } 871 }
1091 872
1092 if (is_chrome) { 873 // 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 874 // 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 875 // in case of errors.
1095 // in case of errors. 876 ClearRlzProductState();
1096 ClearRlzProductState();
1097 877
1098 auto_launch_util::DisableBackgroundStartAtLogin(); 878 auto_launch_util::DisableBackgroundStartAtLogin();
1099 879
1100 // If user-level chrome is self-destructing as a result of encountering a 880 // If user-level chrome is self-destructing as a result of encountering a
1101 // system-level chrome, retarget owned non-default shortcuts (app shortcuts, 881 // system-level chrome, retarget owned non-default shortcuts (app shortcuts,
1102 // profile shortcuts, etc.) to the system-level chrome. 882 // profile shortcuts, etc.) to the system-level chrome.
1103 if (cmd_line.HasSwitch(installer::switches::kSelfDestruct) && 883 if (cmd_line.HasSwitch(installer::switches::kSelfDestruct) &&
1104 !installer_state.system_install()) { 884 !installer_state.system_install()) {
1105 const base::FilePath system_chrome_path( 885 const base::FilePath system_chrome_path(
1106 GetChromeInstallPath(true, browser_dist). 886 GetChromeInstallPath(true, browser_dist).Append(installer::kChromeExe));
1107 Append(installer::kChromeExe)); 887 VLOG(1) << "Retargeting user-generated Chrome shortcuts.";
1108 VLOG(1) << "Retargeting user-generated Chrome shortcuts."; 888 if (base::PathExists(system_chrome_path)) {
1109 if (base::PathExists(system_chrome_path)) { 889 RetargetUserShortcutsWithArgs(installer_state, product, chrome_exe,
1110 RetargetUserShortcutsWithArgs(installer_state, product, chrome_exe, 890 system_chrome_path);
1111 system_chrome_path); 891 } else {
1112 } else { 892 LOG(ERROR) << "Retarget failed: system-level Chrome not found.";
1113 LOG(ERROR) << "Retarget failed: system-level Chrome not found.";
1114 }
1115 } 893 }
894 }
1116 895
1117 DeleteShortcuts(installer_state, product, chrome_exe); 896 DeleteShortcuts(installer_state, product, chrome_exe);
1118 }
1119 897
1120 // Delete the registry keys (Uninstall key and Version key). 898 // Delete the registry keys (Uninstall key and Version key).
1121 HKEY reg_root = installer_state.root_key(); 899 HKEY reg_root = installer_state.root_key();
1122 900
1123 // Note that we must retrieve the distribution-specific data before deleting 901 // Note that we must retrieve the distribution-specific data before deleting
1124 // product.GetVersionKey(). 902 // product.GetVersionKey().
1125 base::string16 distribution_data(browser_dist->GetDistributionData(reg_root)); 903 base::string16 distribution_data(browser_dist->GetDistributionData(reg_root));
1126 904
1127 // Remove Control Panel uninstall link. 905 // Remove Control Panel uninstall link.
1128 if (product.ShouldCreateUninstallEntry()) { 906 if (product.ShouldCreateUninstallEntry()) {
1129 InstallUtil::DeleteRegistryKey( 907 InstallUtil::DeleteRegistryKey(
1130 reg_root, browser_dist->GetUninstallRegPath(), KEY_WOW64_32KEY); 908 reg_root, browser_dist->GetUninstallRegPath(), KEY_WOW64_32KEY);
1131 } 909 }
1132 910
1133 // Remove Omaha product key. 911 // Remove Omaha product key.
1134 InstallUtil::DeleteRegistryKey( 912 InstallUtil::DeleteRegistryKey(
1135 reg_root, browser_dist->GetVersionKey(), KEY_WOW64_32KEY); 913 reg_root, browser_dist->GetVersionKey(), KEY_WOW64_32KEY);
1136 914
1137 // Also try to delete the MSI value in the ClientState key (it might not be 915 // 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 916 // 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 917 // rapid reinstall might result in stale values from the old ClientState key
1140 // being picked up on reinstall. 918 // being picked up on reinstall.
1141 product.SetMsiMarker(installer_state.system_install(), false); 919 product.SetMsiMarker(installer_state.system_install(), false);
1142 920
1143 InstallStatus ret = installer::UNKNOWN_STATUS; 921 InstallStatus ret = installer::UNKNOWN_STATUS;
1144 922
1145 if (is_chrome) { 923 const base::string16 suffix(
1146 const base::string16 suffix( 924 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe));
1147 ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe));
1148 925
1149 // Remove all Chrome registration keys. 926 // Remove all Chrome registration keys.
1150 // Registration data is put in HKCU for both system level and user level 927 // Registration data is put in HKCU for both system level and user level
1151 // installs. 928 // installs.
929 DeleteChromeRegistrationKeys(installer_state, browser_dist, HKEY_CURRENT_USER,
930 suffix, &ret);
931
932 // If the user's Chrome is registered with a suffix: it is possible that old
933 // unsuffixed registrations were left in HKCU (e.g. if this install was
934 // previously installed with no suffix in HKCU (old suffix rules if the user
935 // is not an admin (or declined UAC at first run)) and later had to be
936 // suffixed when fully registered in HKLM (e.g. when later making Chrome
937 // default through the UI)).
938 // Remove remaining HKCU entries with no suffix if any.
939 if (!suffix.empty()) {
1152 DeleteChromeRegistrationKeys(installer_state, browser_dist, 940 DeleteChromeRegistrationKeys(installer_state, browser_dist,
1153 HKEY_CURRENT_USER, suffix, &ret); 941 HKEY_CURRENT_USER, base::string16(), &ret);
1154 942
1155 // If the user's Chrome is registered with a suffix: it is possible that old 943 // For similar reasons it is possible in very few installs (from
1156 // unsuffixed registrations were left in HKCU (e.g. if this install was 944 // 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 945 // 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 946 base::string16 old_style_suffix;
1159 // suffixed when fully registered in HKLM (e.g. when later making Chrome 947 if (ShellUtil::GetOldUserSpecificRegistrySuffix(&old_style_suffix) &&
1160 // default through the UI)). 948 suffix != old_style_suffix) {
1161 // Remove remaining HKCU entries with no suffix if any.
1162 if (!suffix.empty()) {
1163 DeleteChromeRegistrationKeys(installer_state, browser_dist, 949 DeleteChromeRegistrationKeys(installer_state, browser_dist,
1164 HKEY_CURRENT_USER, base::string16(), &ret); 950 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 } 951 }
1176 952
1177 // Chrome is registered in HKLM for all system-level installs and for 953 // 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. 954 // user-level installs for which Chrome has been made the default browser.
1179 // Always remove the HKLM registration for system-level installs. For 955 // 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 956 // 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 957 // self destruct following the installation of a system-level Chrome
1182 // (because the system-level Chrome owns the HKLM registration now), and 2) 958 // (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 959 // this user has made Chrome their default browser (i.e. has shell
1184 // integration entries registered with |suffix| (note: |suffix| will be the 960 // integration entries registered with |suffix| (note: |suffix| will be the
(...skipping 18 matching lines...) Expand all
1203 979
1204 UninstallFirewallRules(browser_dist, chrome_exe); 980 UninstallFirewallRules(browser_dist, chrome_exe);
1205 981
1206 RemoveBlacklistState(); 982 RemoveBlacklistState();
1207 983
1208 // Notify the shell that associations have changed since Chrome was likely 984 // Notify the shell that associations have changed since Chrome was likely
1209 // unregistered. 985 // unregistered.
1210 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); 986 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
1211 } 987 }
1212 988
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) 989 // Get the state of the installed product (if any)
1217 const ProductState* product_state = 990 const ProductState* product_state =
1218 original_state.GetProductState(installer_state.system_install(), 991 original_state.GetProductState(installer_state.system_install(),
1219 browser_dist->GetType()); 992 browser_dist->GetType());
1220 993
1221 // Delete shared registry keys as well (these require admin rights) if 994 // Delete shared registry keys as well (these require admin rights) if
1222 // remove_all option is specified. 995 // remove_all option is specified.
1223 if (remove_all) { 996 if (remove_all) {
1224 if (!InstallUtil::IsChromeSxSProcess() && is_chrome) { 997 if (!InstallUtil::IsChromeSxSProcess()) {
1225 // Delete media player registry key that exists only in HKLM. 998 // 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 999 // 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); 1000 base::string16 reg_path(installer::kMediaPlayerRegPath);
1229 reg_path.push_back(base::FilePath::kSeparators[0]); 1001 reg_path.push_back(base::FilePath::kSeparators[0]);
1230 reg_path.append(installer::kChromeExe); 1002 reg_path.append(installer::kChromeExe);
1231 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, reg_path, 1003 InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, reg_path,
1232 WorkItem::kWow64Default); 1004 WorkItem::kWow64Default);
1233 1005
1234 // Remove the event log provider registration as we are going to delete 1006 // Remove the event log provider registration as we are going to delete
1235 // the file which serves the resources anyways. 1007 // the file which serves the resources anyways.
1236 DeRegisterEventLogProvider(); 1008 DeRegisterEventLogProvider();
1237 } 1009 }
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 } 1010 }
1268 1011
1269 // Finally delete all the files from Chrome folder after moving setup.exe 1012 // Finally delete all the files from Chrome folder after moving setup.exe
1270 // and the user's Local State to a temp location. 1013 // and the user's Local State to a temp location.
1271 bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status, 1014 bool delete_profile = ShouldDeleteProfile(cmd_line, status);
1272 product);
1273 ret = installer::UNINSTALL_SUCCESSFUL; 1015 ret = installer::UNINSTALL_SUCCESSFUL;
1274 1016
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)); 1017 base::FilePath user_data_dir(GetUserDataDir(product));
1279 base::FilePath backup_state_file; 1018 base::FilePath backup_state_file;
1280 if (!user_data_dir.empty()) { 1019 if (!user_data_dir.empty()) {
1281 backup_state_file = BackupLocalStateFile(user_data_dir); 1020 backup_state_file = BackupLocalStateFile(user_data_dir);
1282 } else { 1021 } else {
1283 LOG(ERROR) << "Could not retrieve the user's profile directory."; 1022 LOG(ERROR) << "Could not retrieve the user's profile directory.";
1284 ret = installer::UNINSTALL_FAILED; 1023 ret = installer::UNINSTALL_FAILED;
1285 delete_profile = false; 1024 delete_profile = false;
1286 } 1025 }
1287 1026
1288 if (!installer_state.is_multi_install() || product.is_chrome_binaries()) { 1027 DeleteResult delete_result = DeleteChromeFilesAndFolders(
1289 DeleteResult delete_result = DeleteChromeFilesAndFolders( 1028 installer_state, base::MakeAbsoluteFilePath(setup_exe));
1290 installer_state, base::MakeAbsoluteFilePath(setup_exe)); 1029 if (delete_result == DELETE_FAILED)
1291 if (delete_result == DELETE_FAILED) { 1030 ret = installer::UNINSTALL_FAILED;
1292 ret = installer::UNINSTALL_FAILED; 1031 else if (delete_result == DELETE_REQUIRES_REBOOT)
1293 } else if (delete_result == DELETE_REQUIRES_REBOOT) { 1032 ret = installer::UNINSTALL_REQUIRES_REBOOT;
1294 ret = installer::UNINSTALL_REQUIRES_REBOOT;
1295 }
1296 }
1297 1033
1298 if (delete_profile) { 1034 if (delete_profile) {
1299 DeleteUserDataDir(user_data_dir, product.is_chrome_frame()); 1035 DeleteUserDataDir(user_data_dir);
1300 RemoveDistributionRegistryState(browser_dist); 1036 RemoveDistributionRegistryState(browser_dist);
1301 } 1037 }
1302 1038
1303 if (!force_uninstall && product_state) { 1039 if (!force_uninstall && product_state) {
1304 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; 1040 VLOG(1) << "Uninstallation complete. Launching post-uninstall operations.";
1305 browser_dist->DoPostUninstallOperations(product_state->version(), 1041 browser_dist->DoPostUninstallOperations(product_state->version(),
1306 backup_state_file, distribution_data); 1042 backup_state_file, distribution_data);
1307 } 1043 }
1308 1044
1309 // Try and delete the preserved local state once the post-install 1045 // Try and delete the preserved local state once the post-install
(...skipping 18 matching lines...) Expand all
1328 LOG(ERROR) << "No installation destination path."; 1064 LOG(ERROR) << "No installation destination path.";
1329 *uninstall_status = UNINSTALL_FAILED; 1065 *uninstall_status = UNINSTALL_FAILED;
1330 return; 1066 return;
1331 } 1067 }
1332 if (!target_path.IsParent(base::MakeAbsoluteFilePath(setup_exe))) { 1068 if (!target_path.IsParent(base::MakeAbsoluteFilePath(setup_exe))) {
1333 VLOG(1) << "setup.exe is not in target path. Skipping installer cleanup."; 1069 VLOG(1) << "setup.exe is not in target path. Skipping installer cleanup.";
1334 return; 1070 return;
1335 } 1071 }
1336 base::FilePath install_directory(setup_exe.DirName()); 1072 base::FilePath install_directory(setup_exe.DirName());
1337 1073
1338 bool remove_setup = CheckShouldRemoveSetup(original_state, installer_state); 1074 VLOG(1) << "Removing all installer files.";
1339 1075
1340 if (remove_setup) { 1076 // 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 1077 // move setup.exe out of the install folder.
1342 // need to move setup.exe out of the install folder. 1078 // 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? 1079 MoveSetupOutOfInstallFolder(installer_state, setup_exe);
1344 MoveSetupOutOfInstallFolder(installer_state, setup_exe);
1345 }
1346 1080
1347 // Remove files from "...\<product>\Application\<version>\Installer" 1081 // Remove files from "...\<product>\Application\<version>\Installer"
1348 if (!RemoveInstallerFiles(install_directory, remove_setup)) { 1082 if (!RemoveInstallerFiles(install_directory)) {
1349 *uninstall_status = UNINSTALL_FAILED; 1083 *uninstall_status = UNINSTALL_FAILED;
1350 return; 1084 return;
1351 } 1085 }
1352 1086
1353 if (!remove_setup)
1354 return;
1355
1356 // Try to remove the empty directory hierarchy. 1087 // Try to remove the empty directory hierarchy.
1357 1088
1358 // Delete "...\<product>\Application\<version>\Installer" 1089 // Delete "...\<product>\Application\<version>\Installer"
1359 if (DeleteEmptyDir(install_directory) != DELETE_SUCCEEDED) { 1090 if (DeleteEmptyDir(install_directory) != DELETE_SUCCEEDED) {
1360 *uninstall_status = UNINSTALL_FAILED; 1091 *uninstall_status = UNINSTALL_FAILED;
1361 return; 1092 return;
1362 } 1093 }
1363 1094
1364 // Delete "...\<product>\Application\<version>" 1095 // Delete "...\<product>\Application\<version>"
1365 DeleteResult delete_result = DeleteEmptyDir(install_directory.DirName()); 1096 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 1108 // If we need a reboot to continue, schedule the parent directories for
1378 // deletion unconditionally. If they are not empty, the session manager 1109 // deletion unconditionally. If they are not empty, the session manager
1379 // will not delete them on reboot. 1110 // will not delete them on reboot.
1380 ScheduleParentAndGrandparentForDeletion(target_path); 1111 ScheduleParentAndGrandparentForDeletion(target_path);
1381 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) { 1112 } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) {
1382 *uninstall_status = UNINSTALL_FAILED; 1113 *uninstall_status = UNINSTALL_FAILED;
1383 } 1114 }
1384 } 1115 }
1385 1116
1386 } // namespace installer 1117 } // namespace installer
OLDNEW
« no previous file with comments | « chrome/installer/setup/setup_util_unittest.cc ('k') | chrome/installer/util/install_util.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698