Commit e034a2eb authored by grt@chromium.org's avatar grt@chromium.org

Remove stale code to delete the metro user data dir. It never shipped.

This more or less reverts r149968.

BUG=none
TBR=sky@chromium.org

Review URL: https://codereview.chromium.org/218683013

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@261457 0039d316-1c4b-4281-b951-d872f2087c98
parent f7deb750
...@@ -244,8 +244,6 @@ const int kHighestRendererOomScore = 1000; ...@@ -244,8 +244,6 @@ const int kHighestRendererOomScore = 1000;
#endif #endif
#if defined(OS_WIN) #if defined(OS_WIN)
// This is used by chrome in Windows 8 metro mode.
const wchar_t kMetroChromeUserDataSubDir[] = L"Metro";
const wchar_t kMetroNavigationAndSearchMessage[] = const wchar_t kMetroNavigationAndSearchMessage[] =
L"CHROME_METRO_NAV_SEARCH_REQUEST"; L"CHROME_METRO_NAV_SEARCH_REQUEST";
const wchar_t kMetroGetCurrentTabInfoMessage[] = const wchar_t kMetroGetCurrentTabInfoMessage[] =
......
...@@ -126,8 +126,6 @@ extern const int kHighestRendererOomScore; ...@@ -126,8 +126,6 @@ extern const int kHighestRendererOomScore;
#endif #endif
#if defined(OS_WIN) #if defined(OS_WIN)
// Used by Metro Chrome to create the profile under a custom subdirectory.
extern const wchar_t kMetroChromeUserDataSubDir[];
// Used by Metro Chrome to initiate navigation and search requests. // Used by Metro Chrome to initiate navigation and search requests.
extern const wchar_t kMetroNavigationAndSearchMessage[]; extern const wchar_t kMetroNavigationAndSearchMessage[];
// Used by Metro Chrome to get information about the current tab. // Used by Metro Chrome to get information about the current tab.
......
...@@ -50,8 +50,8 @@ ...@@ -50,8 +50,8 @@
#include "rlz/lib/rlz_lib.h" #include "rlz/lib/rlz_lib.h"
using base::win::RegKey; using base::win::RegKey;
using installer::InstallStatus;
using installer::MasterPreferences; namespace installer {
namespace { namespace {
...@@ -64,7 +64,7 @@ void DeleteInstallTempDir(const base::FilePath& target_path) { ...@@ -64,7 +64,7 @@ void DeleteInstallTempDir(const base::FilePath& target_path) {
base::FilePath temp_path(target_path.DirName().Append( base::FilePath temp_path(target_path.DirName().Append(
installer::kInstallTempDir)); installer::kInstallTempDir));
if (base::DirectoryExists(temp_path)) { if (base::DirectoryExists(temp_path)) {
installer::SelfCleaningTempDir temp_dir; SelfCleaningTempDir temp_dir;
if (!temp_dir.Initialize(target_path.DirName(), if (!temp_dir.Initialize(target_path.DirName(),
installer::kInstallTempDir) || installer::kInstallTempDir) ||
!temp_dir.Delete()) { !temp_dir.Delete()) {
...@@ -77,16 +77,16 @@ void DeleteInstallTempDir(const base::FilePath& target_path) { ...@@ -77,16 +77,16 @@ void DeleteInstallTempDir(const base::FilePath& target_path) {
// adds to |update_list| the work item to update the corresponding "ap" // adds to |update_list| the work item to update the corresponding "ap"
// registry value specified in |channel_info|. // registry value specified in |channel_info|.
void AddChannelValueUpdateWorkItems( void AddChannelValueUpdateWorkItems(
const installer::InstallationState& original_state, const InstallationState& original_state,
const installer::InstallerState& installer_state, const InstallerState& installer_state,
const installer::ChannelInfo& channel_info, const ChannelInfo& channel_info,
const std::vector<BrowserDistribution::Type>& dist_types, const std::vector<BrowserDistribution::Type>& dist_types,
WorkItemList* update_list) { WorkItemList* update_list) {
const bool system_level = installer_state.system_install(); const bool system_level = installer_state.system_install();
const HKEY reg_root = installer_state.root_key(); const HKEY reg_root = installer_state.root_key();
for (size_t i = 0; i < dist_types.size(); ++i) { for (size_t i = 0; i < dist_types.size(); ++i) {
BrowserDistribution::Type dist_type = dist_types[i]; BrowserDistribution::Type dist_type = dist_types[i];
const installer::ProductState* product_state = const ProductState* product_state =
original_state.GetProductState(system_level, dist_type); original_state.GetProductState(system_level, dist_type);
// Only modify other products if they're installed and multi. // Only modify other products if they're installed and multi.
if (product_state != NULL && if (product_state != NULL &&
...@@ -112,17 +112,16 @@ void AddChannelValueUpdateWorkItems( ...@@ -112,17 +112,16 @@ void AddChannelValueUpdateWorkItems(
// Specifically, removes the flags associated with this product ("-chrome" or // Specifically, removes the flags associated with this product ("-chrome" or
// "-chromeframe") from the "ap" values for all other installed products and for // "-chromeframe") from the "ap" values for all other installed products and for
// the multi-installer package. // the multi-installer package.
void ProcessGoogleUpdateItems( void ProcessGoogleUpdateItems(const InstallationState& original_state,
const installer::InstallationState& original_state, const InstallerState& installer_state,
const installer::InstallerState& installer_state, const Product& product) {
const installer::Product& product) {
DCHECK(installer_state.is_multi_install()); DCHECK(installer_state.is_multi_install());
const bool system_level = installer_state.system_install(); const bool system_level = installer_state.system_install();
BrowserDistribution* distribution = product.distribution(); BrowserDistribution* distribution = product.distribution();
const installer::ProductState* product_state = const ProductState* product_state =
original_state.GetProductState(system_level, distribution->GetType()); original_state.GetProductState(system_level, distribution->GetType());
DCHECK(product_state != NULL); DCHECK(product_state != NULL);
installer::ChannelInfo channel_info; ChannelInfo channel_info;
// Remove product's flags from the channel value. // Remove product's flags from the channel value.
channel_info.set_value(product_state->channel().value()); channel_info.set_value(product_state->channel().value());
...@@ -147,9 +146,8 @@ void ProcessGoogleUpdateItems( ...@@ -147,9 +146,8 @@ void ProcessGoogleUpdateItems(
} }
} }
void ProcessOnOsUpgradeWorkItems( void ProcessOnOsUpgradeWorkItems(const InstallerState& installer_state,
const installer::InstallerState& installer_state, const Product& product) {
const installer::Product& product) {
scoped_ptr<WorkItemList> work_item_list( scoped_ptr<WorkItemList> work_item_list(
WorkItem::CreateNoRollbackWorkItemList()); WorkItem::CreateNoRollbackWorkItemList());
AddOsUpgradeWorkItems(installer_state, base::FilePath(), Version(), product, AddOsUpgradeWorkItems(installer_state, base::FilePath(), Version(), product,
...@@ -158,12 +156,11 @@ void ProcessOnOsUpgradeWorkItems( ...@@ -158,12 +156,11 @@ void ProcessOnOsUpgradeWorkItems(
LOG(ERROR) << "Failed to remove on-os-upgrade command."; LOG(ERROR) << "Failed to remove on-os-upgrade command.";
} }
void ProcessIELowRightsPolicyWorkItems( void ProcessIELowRightsPolicyWorkItems(const InstallerState& installer_state) {
const installer::InstallerState& installer_state) {
scoped_ptr<WorkItemList> work_items(WorkItem::CreateNoRollbackWorkItemList()); scoped_ptr<WorkItemList> work_items(WorkItem::CreateNoRollbackWorkItemList());
AddDeleteOldIELowRightsPolicyWorkItems(installer_state, work_items.get()); AddDeleteOldIELowRightsPolicyWorkItems(installer_state, work_items.get());
work_items->Do(); work_items->Do();
installer::RefreshElevationPolicy(); RefreshElevationPolicy();
} }
void ClearRlzProductState() { void ClearRlzProductState() {
...@@ -187,9 +184,8 @@ void ClearRlzProductState() { ...@@ -187,9 +184,8 @@ void ClearRlzProductState() {
// * non-multi product being uninstalled: remove both // * non-multi product being uninstalled: remove both
// * any multi product left besides App Host: keep both // * any multi product left besides App Host: keep both
// * only App Host left: keep setup.exe // * only App Host left: keep setup.exe
void CheckShouldRemoveSetupAndArchive( void CheckShouldRemoveSetupAndArchive(const InstallationState& original_state,
const installer::InstallationState& original_state, const InstallerState& installer_state,
const installer::InstallerState& installer_state,
bool* remove_setup, bool* remove_setup,
bool* remove_archive) { bool* remove_archive) {
*remove_setup = true; *remove_setup = true;
...@@ -204,8 +200,7 @@ void CheckShouldRemoveSetupAndArchive( ...@@ -204,8 +200,7 @@ void CheckShouldRemoveSetupAndArchive(
for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) {
BrowserDistribution::Type dist_type = BrowserDistribution::Type dist_type =
static_cast<BrowserDistribution::Type>(i); static_cast<BrowserDistribution::Type>(i);
const installer::ProductState* product_state = const ProductState* product_state = original_state.GetProductState(
original_state.GetProductState(
installer_state.system_install(), dist_type); installer_state.system_install(), dist_type);
// If the product is installed, in multi mode, and is not part of the // If the product is installed, in multi mode, and is not part of the
// active uninstallation... // active uninstallation...
...@@ -260,10 +255,6 @@ bool RemoveInstallerFiles(const base::FilePath& installer_directory, ...@@ -260,10 +255,6 @@ bool RemoveInstallerFiles(const base::FilePath& installer_directory,
return success; return success;
} }
} // namespace
namespace installer {
// Kills all Chrome processes, immediately. // Kills all Chrome processes, immediately.
void CloseAllChromeProcesses() { void CloseAllChromeProcesses() {
base::CleanupProcesses(installer::kChromeExe, base::TimeDelta(), base::CleanupProcesses(installer::kChromeExe, base::TimeDelta(),
...@@ -395,62 +386,51 @@ DeleteResult DeleteEmptyDir(const base::FilePath& path) { ...@@ -395,62 +386,51 @@ DeleteResult DeleteEmptyDir(const base::FilePath& path) {
return DELETE_FAILED; return DELETE_FAILED;
} }
void GetLocalStateFolders(const Product& product, base::FilePath GetUserDataDir(const Product& product) {
std::vector<base::FilePath>* paths) {
// Obtain the location of the user profile data. // Obtain the location of the user profile data.
product.GetUserDataPaths(paths); base::FilePath user_data_dir = product.GetUserDataPath();
LOG_IF(ERROR, paths->empty()) LOG_IF(ERROR, user_data_dir.empty())
<< "Could not retrieve user's profile directory."; << "Could not retrieve user's profile directory.";
return user_data_dir;
} }
// Creates a copy of the local state file and returns a path to the copy. // Creates a copy of the local state file and returns a path to the copy.
base::FilePath BackupLocalStateFile( base::FilePath BackupLocalStateFile(const base::FilePath& user_data_dir) {
const std::vector<base::FilePath>& local_state_folders) {
base::FilePath backup; base::FilePath backup;
// Copy the first local state file that is found.
for (size_t i = 0; i < local_state_folders.size(); ++i) {
const base::FilePath& local_state_folder = local_state_folders[i];
base::FilePath state_file( base::FilePath state_file(
local_state_folder.Append(chrome::kLocalStateFilename)); user_data_dir.Append(chrome::kLocalStateFilename));
if (!base::PathExists(state_file))
continue;
if (!base::CreateTemporaryFile(&backup)) if (!base::CreateTemporaryFile(&backup))
LOG(ERROR) << "Failed to create temporary file for Local State."; LOG(ERROR) << "Failed to create temporary file for Local State.";
else else
base::CopyFile(state_file, backup); base::CopyFile(state_file, backup);
break;
}
return backup; return backup;
} }
// Deletes all user data directories for a product. // Deletes a given user data directory as well as the containing product
DeleteResult DeleteLocalState( // directories if they are empty (e.g., "Google\Chrome").
const std::vector<base::FilePath>& local_state_folders, DeleteResult DeleteUserDataDir(const base::FilePath& user_data_dir,
bool schedule_on_failure) { bool schedule_on_failure) {
if (local_state_folders.empty()) if (user_data_dir.empty())
return DELETE_SUCCEEDED; return DELETE_SUCCEEDED;
DeleteResult result = DELETE_SUCCEEDED; DeleteResult result = DELETE_SUCCEEDED;
for (size_t i = 0; i < local_state_folders.size(); ++i) { VLOG(1) << "Deleting user profile " << user_data_dir.value();
const base::FilePath& user_local_state = local_state_folders[i]; if (!base::DeleteFile(user_data_dir, true)) {
VLOG(1) << "Deleting user profile " << user_local_state.value();
if (!base::DeleteFile(user_local_state, true)) {
LOG(ERROR) << "Failed to delete user profile dir: " LOG(ERROR) << "Failed to delete user profile dir: "
<< user_local_state.value(); << user_data_dir.value();
if (schedule_on_failure) { if (schedule_on_failure) {
ScheduleDirectoryForDeletion(user_local_state); ScheduleDirectoryForDeletion(user_data_dir);
result = DELETE_REQUIRES_REBOOT; result = DELETE_REQUIRES_REBOOT;
} else { } else {
result = DELETE_FAILED; result = DELETE_FAILED;
} }
} }
}
if (result == DELETE_REQUIRES_REBOOT) { if (result == DELETE_REQUIRES_REBOOT) {
ScheduleParentAndGrandparentForDeletion(local_state_folders[0]); ScheduleParentAndGrandparentForDeletion(user_data_dir);
} else { } else {
const base::FilePath user_data_dir(local_state_folders[0].DirName()); const base::FilePath user_data_dir(user_data_dir.DirName());
if (!user_data_dir.empty() && if (!user_data_dir.empty() &&
DeleteEmptyDir(user_data_dir) == DELETE_SUCCEEDED) { DeleteEmptyDir(user_data_dir) == DELETE_SUCCEEDED) {
const base::FilePath product_dir(user_data_dir.DirName()); const base::FilePath product_dir(user_data_dir.DirName());
...@@ -522,27 +502,6 @@ bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state, ...@@ -522,27 +502,6 @@ bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state,
return true; return true;
} }
DeleteResult DeleteChromeDirectoriesIfEmpty(
const base::FilePath& application_directory) {
DeleteResult result(DeleteEmptyDir(application_directory));
if (result == DELETE_SUCCEEDED) {
// Now check and delete if the parent directories are empty
// For example Google\Chrome or Chromium
const base::FilePath product_directory(application_directory.DirName());
if (!product_directory.empty()) {
result = DeleteEmptyDir(product_directory);
if (result == DELETE_SUCCEEDED) {
const base::FilePath vendor_directory(product_directory.DirName());
if (!vendor_directory.empty())
result = DeleteEmptyDir(vendor_directory);
}
}
}
if (result == DELETE_NOT_EMPTY)
result = DELETE_SUCCEEDED;
return result;
}
DeleteResult DeleteAppHostFilesAndFolders(const InstallerState& installer_state, DeleteResult DeleteAppHostFilesAndFolders(const InstallerState& installer_state,
const Version& installed_version) { const Version& installed_version) {
const base::FilePath& target_path = installer_state.target_path(); const base::FilePath& target_path = installer_state.target_path();
...@@ -758,6 +717,164 @@ void RemoveFiletypeRegistration(const InstallerState& installer_state, ...@@ -758,6 +717,164 @@ void RemoveFiletypeRegistration(const InstallerState& installer_state,
} }
} }
// Builds and executes a work item list to remove DelegateExecute verb handler
// work items for |product|. This will be a noop for products whose
// corresponding BrowserDistribution implementations do not publish a CLSID via
// GetCommandExecuteImplClsid.
bool ProcessDelegateExecuteWorkItems(const InstallerState& installer_state,
const Product& product) {
scoped_ptr<WorkItemList> item_list(WorkItem::CreateNoRollbackWorkItemList());
AddDelegateExecuteWorkItems(installer_state, base::FilePath(), Version(),
product, item_list.get());
return item_list->Do();
}
// Removes Active Setup entries from the registry. This cannot be done through
// a work items list as usual because of different paths based on conditionals,
// but otherwise respects the no rollback/best effort uninstall mentality.
// This will only apply for system-level installs of Chrome/Chromium and will be
// a no-op for all other types of installs.
void UninstallActiveSetupEntries(const InstallerState& installer_state,
const Product& product) {
VLOG(1) << "Uninstalling registry entries for ActiveSetup.";
BrowserDistribution* distribution = product.distribution();
if (!product.is_chrome() || !installer_state.system_install()) {
const char* install_level =
installer_state.system_install() ? "system" : "user";
VLOG(1) << "No Active Setup processing to do for " << install_level
<< "-level " << distribution->GetDisplayName();
return;
}
const base::string16 active_setup_path(
InstallUtil::GetActiveSetupPath(distribution));
InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path);
// Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\
// Active Setup\\Installed Components\\{guid}
// for every user that logged in since system-level Chrome was installed.
// This is a problem because Windows compares the value of the Version subkey
// in there with the value of the Version subkey in the matching HKLM entries
// before running Chrome's Active Setup so if Chrome was to be reinstalled
// with a lesser version (e.g. switching back to a more stable channel), the
// affected users would not have Chrome's Active Setup called until Chrome
// eventually updated passed that user's registered Version.
//
// It is however very hard to delete those values as the registry hives for
// other users are not loaded by default under HKEY_USERS (unless a user is
// logged on or has a process impersonating him).
//
// Following our best effort uninstall practices, try to delete the value in
// all users hives. If a given user's hive is not loaded, try to load it to
// proceed with the deletion (failure to do so is ignored).
static const wchar_t kProfileList[] =
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\";
// Windows automatically adds Wow6432Node when creating/deleting the HKLM key,
// but doesn't seem to do so when manually deleting the user-level keys it
// created.
base::string16 alternate_active_setup_path(active_setup_path);
alternate_active_setup_path.insert(arraysize("Software\\") - 1,
L"Wow6432Node\\");
// These two privileges are required by RegLoadKey() and RegUnloadKey() below.
ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME);
ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME);
if (!se_restore_name_privilege.is_enabled() ||
!se_backup_name_privilege.is_enabled()) {
// This is not a critical failure as those privileges aren't required to
// clean hives that are already loaded, but attempts to LoadRegKey() below
// will fail.
LOG(WARNING) << "Failed to enable privileges required to load registry "
"hives.";
}
for (base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE, kProfileList);
it.Valid(); ++it) {
const wchar_t* profile_sid = it.Name();
// First check if this user's registry hive needs to be loaded in
// HKEY_USERS.
base::win::RegKey user_reg_root_probe(
HKEY_USERS, profile_sid, KEY_READ);
bool loaded_hive = false;
if (!user_reg_root_probe.Valid()) {
VLOG(1) << "Attempting to load registry hive for " << profile_sid;
base::string16 reg_profile_info_path(kProfileList);
reg_profile_info_path.append(profile_sid);
base::win::RegKey reg_profile_info_key(
HKEY_LOCAL_MACHINE, reg_profile_info_path.c_str(), KEY_READ);
base::string16 profile_path;
LONG result = reg_profile_info_key.ReadValue(L"ProfileImagePath",
&profile_path);
if (result != ERROR_SUCCESS) {
LOG(ERROR) << "Error reading ProfileImagePath: " << result;
continue;
}
base::FilePath registry_hive_file(profile_path);
registry_hive_file = registry_hive_file.AppendASCII("NTUSER.DAT");
result = RegLoadKey(HKEY_USERS, profile_sid,
registry_hive_file.value().c_str());
if (result != ERROR_SUCCESS) {
LOG(ERROR) << "Error loading registry hive: " << result;
continue;
}
VLOG(1) << "Loaded registry hive for " << profile_sid;
loaded_hive = true;
}
base::win::RegKey user_reg_root(
HKEY_USERS, profile_sid, KEY_ALL_ACCESS);
LONG result = user_reg_root.DeleteKey(active_setup_path.c_str());
if (result != ERROR_SUCCESS) {
result = user_reg_root.DeleteKey(alternate_active_setup_path.c_str());
if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
LOG(ERROR) << "Failed to delete key at " << active_setup_path
<< " and at " << alternate_active_setup_path
<< ", result: " << result;
}
}
if (loaded_hive) {
user_reg_root.Close();
if (RegUnLoadKey(HKEY_USERS, profile_sid) == ERROR_SUCCESS)
VLOG(1) << "Unloaded registry hive for " << profile_sid;
else
LOG(ERROR) << "Error unloading registry hive for " << profile_sid;
}
}
}
} // namespace
DeleteResult DeleteChromeDirectoriesIfEmpty(
const base::FilePath& application_directory) {
DeleteResult result(DeleteEmptyDir(application_directory));
if (result == DELETE_SUCCEEDED) {
// Now check and delete if the parent directories are empty
// For example Google\Chrome or Chromium
const base::FilePath product_directory(application_directory.DirName());
if (!product_directory.empty()) {
result = DeleteEmptyDir(product_directory);
if (result == DELETE_SUCCEEDED) {
const base::FilePath vendor_directory(product_directory.DirName());
if (!vendor_directory.empty())
result = DeleteEmptyDir(vendor_directory);
}
}
}
if (result == DELETE_NOT_EMPTY)
result = DELETE_SUCCEEDED;
return result;
}
bool DeleteChromeRegistrationKeys(const InstallerState& installer_state, bool DeleteChromeRegistrationKeys(const InstallerState& installer_state,
BrowserDistribution* dist, BrowserDistribution* dist,
HKEY root, HKEY root,
...@@ -929,141 +1046,6 @@ const wchar_t kChromeExtProgId[] = L"ChromiumExt"; ...@@ -929,141 +1046,6 @@ const wchar_t kChromeExtProgId[] = L"ChromiumExt";
} }
} }
// Builds and executes a work item list to remove DelegateExecute verb handler
// work items for |product|. This will be a noop for products whose
// corresponding BrowserDistribution implementations do not publish a CLSID via
// GetCommandExecuteImplClsid.
bool ProcessDelegateExecuteWorkItems(const InstallerState& installer_state,
const Product& product) {
scoped_ptr<WorkItemList> item_list(WorkItem::CreateNoRollbackWorkItemList());
AddDelegateExecuteWorkItems(installer_state, base::FilePath(), Version(),
product, item_list.get());
return item_list->Do();
}
// Removes Active Setup entries from the registry. This cannot be done through
// a work items list as usual because of different paths based on conditionals,
// but otherwise respects the no rollback/best effort uninstall mentality.
// This will only apply for system-level installs of Chrome/Chromium and will be
// a no-op for all other types of installs.
void UninstallActiveSetupEntries(const InstallerState& installer_state,
const Product& product) {
VLOG(1) << "Uninstalling registry entries for ActiveSetup.";
BrowserDistribution* distribution = product.distribution();
if (!product.is_chrome() || !installer_state.system_install()) {
const char* install_level =
installer_state.system_install() ? "system" : "user";
VLOG(1) << "No Active Setup processing to do for " << install_level
<< "-level " << distribution->GetDisplayName();
return;
}
const base::string16 active_setup_path(
InstallUtil::GetActiveSetupPath(distribution));
InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path);
// Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\
// Active Setup\\Installed Components\\{guid}
// for every user that logged in since system-level Chrome was installed.
// This is a problem because Windows compares the value of the Version subkey
// in there with the value of the Version subkey in the matching HKLM entries
// before running Chrome's Active Setup so if Chrome was to be reinstalled
// with a lesser version (e.g. switching back to a more stable channel), the
// affected users would not have Chrome's Active Setup called until Chrome
// eventually updated passed that user's registered Version.
//
// It is however very hard to delete those values as the registry hives for
// other users are not loaded by default under HKEY_USERS (unless a user is
// logged on or has a process impersonating him).
//
// Following our best effort uninstall practices, try to delete the value in
// all users hives. If a given user's hive is not loaded, try to load it to
// proceed with the deletion (failure to do so is ignored).
static const wchar_t kProfileList[] =
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\";
// Windows automatically adds Wow6432Node when creating/deleting the HKLM key,
// but doesn't seem to do so when manually deleting the user-level keys it
// created.
base::string16 alternate_active_setup_path(active_setup_path);
alternate_active_setup_path.insert(arraysize("Software\\") - 1,
L"Wow6432Node\\");
// These two privileges are required by RegLoadKey() and RegUnloadKey() below.
ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME);
ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME);
if (!se_restore_name_privilege.is_enabled() ||
!se_backup_name_privilege.is_enabled()) {
// This is not a critical failure as those privileges aren't required to
// clean hives that are already loaded, but attempts to LoadRegKey() below
// will fail.
LOG(WARNING) << "Failed to enable privileges required to load registry "
"hives.";
}
for (base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE, kProfileList);
it.Valid(); ++it) {
const wchar_t* profile_sid = it.Name();
// First check if this user's registry hive needs to be loaded in
// HKEY_USERS.
base::win::RegKey user_reg_root_probe(
HKEY_USERS, profile_sid, KEY_READ);
bool loaded_hive = false;
if (!user_reg_root_probe.Valid()) {
VLOG(1) << "Attempting to load registry hive for " << profile_sid;
base::string16 reg_profile_info_path(kProfileList);
reg_profile_info_path.append(profile_sid);
base::win::RegKey reg_profile_info_key(
HKEY_LOCAL_MACHINE, reg_profile_info_path.c_str(), KEY_READ);
base::string16 profile_path;
LONG result = reg_profile_info_key.ReadValue(L"ProfileImagePath",
&profile_path);
if (result != ERROR_SUCCESS) {
LOG(ERROR) << "Error reading ProfileImagePath: " << result;
continue;
}
base::FilePath registry_hive_file(profile_path);
registry_hive_file = registry_hive_file.AppendASCII("NTUSER.DAT");
result = RegLoadKey(HKEY_USERS, profile_sid,
registry_hive_file.value().c_str());
if (result != ERROR_SUCCESS) {
LOG(ERROR) << "Error loading registry hive: " << result;
continue;
}
VLOG(1) << "Loaded registry hive for " << profile_sid;
loaded_hive = true;
}
base::win::RegKey user_reg_root(
HKEY_USERS, profile_sid, KEY_ALL_ACCESS);
LONG result = user_reg_root.DeleteKey(active_setup_path.c_str());
if (result != ERROR_SUCCESS) {
result = user_reg_root.DeleteKey(alternate_active_setup_path.c_str());
if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
LOG(ERROR) << "Failed to delete key at " << active_setup_path
<< " and at " << alternate_active_setup_path
<< ", result: " << result;
}
}
if (loaded_hive) {
user_reg_root.Close();
if (RegUnLoadKey(HKEY_USERS, profile_sid) == ERROR_SUCCESS)
VLOG(1) << "Unloaded registry hive for " << profile_sid;
else
LOG(ERROR) << "Error unloading registry hive for " << profile_sid;
}
}
}
InstallStatus UninstallProduct(const InstallationState& original_state, InstallStatus UninstallProduct(const InstallationState& original_state,
const InstallerState& installer_state, const InstallerState& installer_state,
const base::FilePath& setup_exe, const base::FilePath& setup_exe,
...@@ -1332,9 +1314,8 @@ InstallStatus UninstallProduct(const InstallationState& original_state, ...@@ -1332,9 +1314,8 @@ InstallStatus UninstallProduct(const InstallationState& original_state,
// When deleting files, we must make sure that we're either a "single" // When deleting files, we must make sure that we're either a "single"
// (aka non-multi) installation or we are the Chrome Binaries. // (aka non-multi) installation or we are the Chrome Binaries.
std::vector<base::FilePath> local_state_folders; base::FilePath user_data_dir(GetUserDataDir(product));
GetLocalStateFolders(product, &local_state_folders); base::FilePath backup_state_file(BackupLocalStateFile(user_data_dir));
base::FilePath backup_state_file(BackupLocalStateFile(local_state_folders));
if (product.is_chrome_app_host()) { if (product.is_chrome_app_host()) {
DeleteAppHostFilesAndFolders(installer_state, product_state->version()); DeleteAppHostFilesAndFolders(installer_state, product_state->version());
...@@ -1350,7 +1331,7 @@ InstallStatus UninstallProduct(const InstallationState& original_state, ...@@ -1350,7 +1331,7 @@ InstallStatus UninstallProduct(const InstallationState& original_state,
} }
if (delete_profile) if (delete_profile)
DeleteLocalState(local_state_folders, product.is_chrome_frame()); DeleteUserDataDir(user_data_dir, product.is_chrome_frame());
if (!force_uninstall) { if (!force_uninstall) {
VLOG(1) << "Uninstallation complete. Launching post-uninstall operations."; VLOG(1) << "Uninstallation complete. Launching post-uninstall operations.";
......
...@@ -53,10 +53,7 @@ base::string16 ProfileToKeyName(const base::string16& profile_directory) { ...@@ -53,10 +53,7 @@ base::string16 ProfileToKeyName(const base::string16& profile_directory) {
BrowserDistribution::GetSpecificDistribution( BrowserDistribution::GetSpecificDistribution(
BrowserDistribution::CHROME_BROWSER); BrowserDistribution::CHROME_BROWSER);
installer::Product product(distribution); installer::Product product(distribution);
std::vector<base::FilePath> data_dir_paths; path = product.GetUserDataPath();
product.GetUserDataPaths(&data_dir_paths);
if (!data_dir_paths.empty())
path = data_dir_paths[0];
} }
path = path.Append(profile_directory); path = path.Append(profile_directory);
......
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/win/windows_version.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/install_util.h" #include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/installation_state.h" #include "chrome/installer/util/installation_state.h"
...@@ -43,27 +41,8 @@ base::FilePath GetChromeInstallPath(bool system_install, ...@@ -43,27 +41,8 @@ base::FilePath GetChromeInstallPath(bool system_install,
return GetChromeInstallBasePath(system_install, dist, kInstallBinaryDir); return GetChromeInstallBasePath(system_install, dist, kInstallBinaryDir);
} }
// TODO(gab): Cleanup this method (kMetroChromeUserDataSubDir is deprecated). base::FilePath GetChromeUserDataPath(BrowserDistribution* dist) {
void GetChromeUserDataPaths(BrowserDistribution* dist, return GetChromeInstallBasePath(false, dist, kInstallUserDataDir);
std::vector<base::FilePath>* paths) {
const bool has_metro_data =
base::win::GetVersion() >= base::win::VERSION_WIN8 &&
dist->GetDefaultBrowserControlPolicy() !=
BrowserDistribution::DEFAULT_BROWSER_UNSUPPORTED;
base::FilePath data_dir(GetChromeInstallBasePath(false, dist,
kInstallUserDataDir));
if (data_dir.empty()) {
paths->clear();
} else {
paths->resize(has_metro_data ? 2 : 1);
(*paths)[0] = data_dir;
if (has_metro_data) {
(*paths)[1] = data_dir.DirName().Append(
chrome::kMetroChromeUserDataSubDir);
}
}
DCHECK(!paths->empty());
} }
BrowserDistribution* GetBinariesDistribution(bool system_install) { BrowserDistribution* GetBinariesDistribution(bool system_install) {
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#define CHROME_INSTALLER_UTIL_HELPER_H_ #define CHROME_INSTALLER_UTIL_HELPER_H_
#include <string> #include <string>
#include <vector>
class BrowserDistribution; class BrowserDistribution;
...@@ -25,16 +24,12 @@ namespace installer { ...@@ -25,16 +24,12 @@ namespace installer {
// location (Document And Settings\<user>\Local Settings...) // location (Document And Settings\<user>\Local Settings...)
base::FilePath GetChromeInstallPath(bool system_install, BrowserDistribution* dist); base::FilePath GetChromeInstallPath(bool system_install, BrowserDistribution* dist);
// Returns the path(s) to the directory that holds the user data (primary and, // Returns the path to the directory that holds the user data. This is always
// if applicable to |dist|, alternate). This is always inside a user's local // inside a user's local application data folder (e.g., "AppData\Local" or
// application data folder (e.g., "AppData\Local or "Local Settings\Application // "Local Settings\Application Data" in %USERPROFILE%). Note that this is the
// Data" in %USERPROFILE%). Note that these are the defaults and do not take // default user data directory and does not take into account that it can be
// into account that they can be overriden with a command line parameter. // overriden with a command line parameter.
// |paths| may be empty on return, but is guaranteed not to contain empty paths base::FilePath GetChromeUserDataPath(BrowserDistribution* dist);
// otherwise. If more than one path is returned, they are guaranteed to be
// siblings.
void GetChromeUserDataPaths(BrowserDistribution* dist,
std::vector<base::FilePath>* paths);
// Returns the distribution corresponding to the current process's binaries. // Returns the distribution corresponding to the current process's binaries.
// In the case of a multi-install product, this will be the CHROME_BINARIES // In the case of a multi-install product, this will be the CHROME_BINARIES
......
...@@ -414,12 +414,11 @@ bool InstallUtil::GetSentinelFilePath(const base::FilePath::CharType* file, ...@@ -414,12 +414,11 @@ bool InstallUtil::GetSentinelFilePath(const base::FilePath::CharType* file,
BrowserDistribution* dist, BrowserDistribution* dist,
base::FilePath* path) { base::FilePath* path) {
// TODO(msw): Use PathService to obtain the correct DIR_USER_DATA. // TODO(msw): Use PathService to obtain the correct DIR_USER_DATA.
std::vector<base::FilePath> user_data_dir_paths; base::FilePath user_data_dir(installer::GetChromeUserDataPath(dist));
installer::GetChromeUserDataPaths(dist, &user_data_dir_paths);
if (user_data_dir_paths.empty()) if (user_data_dir.empty())
return false; return false;
*path = user_data_dir_paths[0].Append(file); *path = user_data_dir.Append(file);
return true; return true;
} }
......
...@@ -62,8 +62,8 @@ void Product::InitializeFromUninstallCommand( ...@@ -62,8 +62,8 @@ void Product::InitializeFromUninstallCommand(
operations_->ReadOptions(uninstall_command, &options_); operations_->ReadOptions(uninstall_command, &options_);
} }
void Product::GetUserDataPaths(std::vector<base::FilePath>* paths) const { base::FilePath Product::GetUserDataPath() const {
GetChromeUserDataPaths(distribution_, paths); return GetChromeUserDataPath(distribution_);
} }
bool Product::LaunchChrome(const base::FilePath& application_path) const { bool Product::LaunchChrome(const base::FilePath& application_path) const {
......
...@@ -81,15 +81,12 @@ class Product { ...@@ -81,15 +81,12 @@ class Product {
return options_.erase(option) != 0; return options_.erase(option) != 0;
} }
// Returns the path(s) to the directory that holds the user data (primary // Returns the path to the directory that holds the user data. This is always
// and, if applicable to |dist|, alternate). This is always inside a user's // inside a user's local application data folder (e.g., "AppData\Local" or
// local application data folder (e.g., "AppData\Local or "Local // "Local Settings\Application Data" in %USERPROFILE%). Note that this is the
// Settings\Application Data" in %USERPROFILE%). Note that these are the // default user data directory and does not take into account that it can be
// defaults and do not take into account that they can be overriden with a // overriden with a command line parameter.
// command line parameter. |paths| may be empty on return, but is guaranteed base::FilePath GetUserDataPath() const;
// not to contain empty paths otherwise. If more than one path is returned,
// they are guaranteed to be siblings.
void GetUserDataPaths(std::vector<base::FilePath>* paths) const;
// Launches Chrome without waiting for it to exit. // Launches Chrome without waiting for it to exit.
bool LaunchChrome(const base::FilePath& application_path) const; bool LaunchChrome(const base::FilePath& application_path) const;
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/test_reg_util_win.h" #include "base/test/test_reg_util_win.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/installer/util/chrome_frame_distribution.h" #include "chrome/installer/util/chrome_frame_distribution.h"
#include "chrome/installer/util/google_update_constants.h" #include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/installation_state.h" #include "chrome/installer/util/installation_state.h"
...@@ -71,19 +70,10 @@ TEST_F(ProductTest, MAYBE_ProductInstallBasic) { ...@@ -71,19 +70,10 @@ TEST_F(ProductTest, MAYBE_ProductInstallBasic) {
BrowserDistribution* distribution = product->distribution(); BrowserDistribution* distribution = product->distribution();
EXPECT_EQ(BrowserDistribution::CHROME_BROWSER, distribution->GetType()); EXPECT_EQ(BrowserDistribution::CHROME_BROWSER, distribution->GetType());
std::vector<base::FilePath> user_data_paths; base::FilePath user_data(product->GetUserDataPath());
product->GetUserDataPaths(&user_data_paths); EXPECT_FALSE(user_data.empty());
EXPECT_GE(user_data_paths.size(), static_cast<size_t>(1));
const base::FilePath& user_data = user_data_paths[0];
EXPECT_FALSE(user_data_paths[0].empty());
EXPECT_NE(std::wstring::npos, EXPECT_NE(std::wstring::npos,
user_data_paths[0].value().find(installer::kInstallUserDataDir)); user_data.value().find(installer::kInstallUserDataDir));
if (user_data_paths.size() > 1) {
EXPECT_FALSE(user_data_paths[1].empty());
EXPECT_NE(
std::wstring::npos,
user_data_paths[1].value().find(chrome::kMetroChromeUserDataSubDir));
}
base::FilePath program_files; base::FilePath program_files;
PathService::Get(base::DIR_PROGRAM_FILES, &program_files); PathService::Get(base::DIR_PROGRAM_FILES, &program_files);
......
...@@ -427,21 +427,15 @@ void LaunchBrowserUserExperiment(const CommandLine& base_cmd_line, ...@@ -427,21 +427,15 @@ void LaunchBrowserUserExperiment(const CommandLine& base_cmd_line,
} }
// Check browser usage inactivity by the age of the last-write time of the // Check browser usage inactivity by the age of the last-write time of the
// most recently-used chrome user data directory. // most recently-used chrome user data directory.
std::vector<base::FilePath> user_data_dirs;
BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution( BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
BrowserDistribution::CHROME_BROWSER); BrowserDistribution::CHROME_BROWSER);
GetChromeUserDataPaths(dist, &user_data_dirs); base::FilePath user_data_dir(GetChromeUserDataPath(dist));
int dir_age_hours = -1;
for (size_t i = 0; i < user_data_dirs.size(); ++i) {
int this_age = GetDirectoryWriteAgeInHours(
user_data_dirs[i].value().c_str());
if (this_age >= 0 && (dir_age_hours < 0 || this_age < dir_age_hours))
dir_age_hours = this_age;
}
const bool experiment_enabled = false; const bool experiment_enabled = false;
const int kThirtyDays = 30 * 24; const int kThirtyDays = 30 * 24;
int dir_age_hours = GetDirectoryWriteAgeInHours(
user_data_dir.value().c_str());
if (!experiment_enabled) { if (!experiment_enabled) {
VLOG(1) << "Toast experiment is disabled."; VLOG(1) << "Toast experiment is disabled.";
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment