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

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

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

Powered by Google App Engine
This is Rietveld 408576698