summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorgrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-18 14:54:50 +0000
committergrt@chromium.org <grt@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-18 14:54:50 +0000
commitbdddb676d97056742f83d280843ff099768b07f3 (patch)
tree42b9dc58c818226653c2388d7716ec729e3836cf /chrome
parent7e91c5937f1f9587acda5a0a732d07bed8cafe46 (diff)
downloadchromium_src-bdddb676d97056742f83d280843ff099768b07f3.zip
chromium_src-bdddb676d97056742f83d280843ff099768b07f3.tar.gz
chromium_src-bdddb676d97056742f83d280843ff099768b07f3.tar.bz2
Temp dir cleanup:
- use ScopedTempDir in work items that need backup space for rollback - all work items that need backup space take a parent dir in which they create temp dirs - use ScopedTempDir in a few other places - renamed some parameters in certain functions so that the same name is used everywhere While I was at it, I couldn't help but replace Append(UTF8ToWide(version.GetString())) with the more pleasing AppendASCII(version.GetString()) BUG=70368 TEST=existing tests in installer_util_unittests cover the changes Review URL: http://codereview.chromium.org/6538025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75392 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/installer/setup/chrome_frame_quick_enable.cc8
-rw-r--r--chrome/installer/setup/install.cc34
-rw-r--r--chrome/installer/setup/install_worker.cc42
-rw-r--r--chrome/installer/setup/install_worker.h7
-rw-r--r--chrome/installer/setup/setup_main.cc58
-rw-r--r--chrome/installer/setup/uninstall.cc4
-rw-r--r--chrome/installer/util/copy_tree_work_item.cc43
-rw-r--r--chrome/installer/util/copy_tree_work_item.h21
-rw-r--r--chrome/installer/util/copy_tree_work_item_unittest.cc49
-rw-r--r--chrome/installer/util/delete_tree_work_item.cc137
-rw-r--r--chrome/installer/util/delete_tree_work_item.h42
-rw-r--r--chrome/installer/util/delete_tree_work_item_unittest.cc19
-rw-r--r--chrome/installer/util/installer_state.cc6
-rw-r--r--chrome/installer/util/installer_state.h3
-rw-r--r--chrome/installer/util/installer_state_unittest.cc25
-rw-r--r--chrome/installer/util/move_tree_work_item.cc27
-rw-r--r--chrome/installer/util/move_tree_work_item.h10
-rw-r--r--chrome/installer/util/work_item.cc6
-rw-r--r--chrome/installer/util/work_item.h4
-rw-r--r--chrome/installer/util/work_item_list.cc9
-rw-r--r--chrome/installer/util/work_item_list.h4
21 files changed, 296 insertions, 262 deletions
diff --git a/chrome/installer/setup/chrome_frame_quick_enable.cc b/chrome/installer/setup/chrome_frame_quick_enable.cc
index 22b4615..d100392 100644
--- a/chrome/installer/setup/chrome_frame_quick_enable.cc
+++ b/chrome/installer/setup/chrome_frame_quick_enable.cc
@@ -7,6 +7,7 @@
#include <windows.h>
#include "base/logging.h"
+#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
#include "base/win/registry.h"
#include "chrome/installer/setup/install_worker.h"
@@ -79,6 +80,11 @@ InstallStatus ChromeFrameQuickEnable(const InstallationState& machine_state,
LOG(ERROR) << "AddProduct failed";
status = INSTALL_FAILED;
} else {
+ ScopedTempDir temp_path;
+ if (!temp_path.CreateUniqueTempDir()) {
+ PLOG(ERROR) << "Failed to create Temp directory";
+ return INSTALL_FAILED;
+ }
scoped_ptr<WorkItemList> item_list(WorkItem::CreateWorkItemList());
const ProductState* chrome_state =
machine_state.GetProductState(installer_state->system_install(),
@@ -106,7 +112,7 @@ InstallStatus ChromeFrameQuickEnable(const InstallationState& machine_state,
const Version* opv = chrome_state->old_version();
AppendPostInstallTasks(*installer_state, setup_path, new_chrome_exe, opv,
- new_version, item_list.get());
+ new_version, temp_path.path(), item_list.get());
// Before updating the channel values, add Chrome back to the mix so that
// all multi-installed products' channel values get updated.
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index d9b55fe..e9b394b 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -57,30 +57,6 @@ void AddChromeToMediaPlayerList() {
LOG(ERROR) << "Could not add Chrome to media player inclusion list.";
}
-void AddInstallerCopyTasks(const InstallerState& installer_state,
- const FilePath& setup_path,
- const FilePath& archive_path,
- const FilePath& temp_path,
- const Version& new_version,
- WorkItemList* install_list) {
- DCHECK(install_list);
- FilePath installer_dir(installer_state.GetInstallerDirectory(new_version));
- install_list->AddCreateDirWorkItem(installer_dir);
-
- FilePath exe_dst(installer_dir.Append(setup_path.BaseName()));
- FilePath archive_dst(installer_dir.Append(archive_path.BaseName()));
-
- install_list->AddCopyTreeWorkItem(setup_path.value(), exe_dst.value(),
- temp_path.value(), WorkItem::ALWAYS);
- if (installer_state.system_install()) {
- install_list->AddCopyTreeWorkItem(archive_path.value(), archive_dst.value(),
- temp_path.value(), WorkItem::ALWAYS);
- } else {
- install_list->AddMoveTreeWorkItem(archive_path.value(), archive_dst.value(),
- temp_path.value());
- }
-}
-
// Copy master preferences file provided to installer, in the same folder
// as chrome.exe so Chrome first run can find it. This function will be called
// only on the first install of Chrome.
@@ -263,8 +239,8 @@ void RegisterChromeOnMachine(const InstallerState& installer_state,
// to Chrome install folder after install is complete
// src_path: the path that contains a complete and unpacked Chrome package
// to be installed.
-// temp_dir: the path of working directory used during installation. This path
-// does not need to exist.
+// temp_path: the path of working directory used during installation. This path
+// does not need to exist.
// new_version: new Chrome version that needs to be installed
// current_version: returns the current active version (if any)
//
@@ -281,7 +257,7 @@ installer::InstallStatus InstallNewVersion(
const FilePath& setup_path,
const FilePath& archive_path,
const FilePath& src_path,
- const FilePath& temp_dir,
+ const FilePath& temp_path,
const Version& new_version,
scoped_ptr<Version>* current_version) {
DCHECK(current_version);
@@ -294,7 +270,7 @@ installer::InstallStatus InstallNewVersion(
setup_path,
archive_path,
src_path,
- temp_dir,
+ temp_path,
new_version,
current_version,
install_list.get());
@@ -425,7 +401,7 @@ InstallStatus InstallOrUpdateProduct(
}
installer_state.RemoveOldVersionDirectories(existing_version.get() ?
- *existing_version.get() : new_version);
+ *existing_version.get() : new_version, install_temp_path);
}
return result;
diff --git a/chrome/installer/setup/install_worker.cc b/chrome/installer/setup/install_worker.cc
index 46eb559..0717a34 100644
--- a/chrome/installer/setup/install_worker.cc
+++ b/chrome/installer/setup/install_worker.cc
@@ -79,8 +79,8 @@ void AddRegisterComDllWorkItemsForPackage(const InstallerState& installer_state,
// saved state instead of assuming it is the same as the registration list.
if (!com_dll_list.empty()) {
if (old_version) {
- FilePath old_dll_path(installer_state.target_path().Append(
- UTF8ToWide(old_version->GetString())));
+ FilePath old_dll_path(installer_state.target_path().AppendASCII(
+ old_version->GetString()));
installer::AddRegisterComDllWorkItems(old_dll_path,
com_dll_list,
@@ -90,8 +90,8 @@ void AddRegisterComDllWorkItemsForPackage(const InstallerState& installer_state,
work_item_list);
}
- FilePath dll_path(installer_state.target_path().Append(
- UTF8ToWide(new_version.GetString())));
+ FilePath dll_path(installer_state.target_path().AppendASCII(
+ new_version.GetString()));
installer::AddRegisterComDllWorkItems(dll_path,
com_dll_list,
installer_state.system_install(),
@@ -358,6 +358,7 @@ void AddGoogleUpdateWorkItems(const InstallerState& installer_state,
void AddDeleteUninstallShortcutsForMSIWorkItems(
const InstallerState& installer_state,
const Product& product,
+ const FilePath& temp_path,
WorkItemList* work_item_list) {
DCHECK(installer_state.is_msi())
<< "This must only be called for MSI installations!";
@@ -388,7 +389,7 @@ void AddDeleteUninstallShortcutsForMSIWorkItems(
VLOG(1) << "Deleting old uninstall shortcut (if present): "
<< uninstall_link.value();
WorkItem* delete_link = work_item_list->AddDeleteTreeWorkItem(
- uninstall_link);
+ uninstall_link, temp_path);
delete_link->set_ignore_failure(true);
delete_link->set_log_message(
"Failed to delete old uninstall shortcut.");
@@ -409,6 +410,7 @@ bool AppendPostInstallTasks(const InstallerState& installer_state,
const FilePath& new_chrome_exe,
const Version* current_version,
const Version& new_version,
+ const FilePath& temp_path,
WorkItemList* post_install_task_list) {
DCHECK(post_install_task_list);
@@ -514,6 +516,7 @@ bool AppendPostInstallTasks(const InstallerState& installer_state,
// previous non-MSI installations for the same type of install (system or
// per user).
AddDeleteUninstallShortcutsForMSIWorkItems(installer_state, *product,
+ temp_path,
post_install_task_list);
}
if (installer_state.is_multi_install()) {
@@ -531,7 +534,7 @@ void AddInstallWorkItems(const InstallationState& original_state,
const FilePath& setup_path,
const FilePath& archive_path,
const FilePath& src_path,
- const FilePath& temp_dir,
+ const FilePath& temp_path,
const Version& new_version,
scoped_ptr<Version>* current_version,
WorkItemList* install_list) {
@@ -540,7 +543,7 @@ void AddInstallWorkItems(const InstallationState& original_state,
const FilePath& target_path = installer_state.target_path();
// A temp directory that work items need and the actual install directory.
- install_list->AddCreateDirWorkItem(temp_dir);
+ install_list->AddCreateDirWorkItem(temp_path);
install_list->AddCreateDirWorkItem(target_path);
// Delete any new_chrome.exe if present (we will end up creating a new one
@@ -548,47 +551,47 @@ void AddInstallWorkItems(const InstallationState& original_state,
FilePath new_chrome_exe(
target_path.Append(installer::kChromeNewExe));
- install_list->AddDeleteTreeWorkItem(new_chrome_exe);
+ install_list->AddDeleteTreeWorkItem(new_chrome_exe, temp_path);
install_list->AddCopyTreeWorkItem(
src_path.Append(installer::kChromeExe).value(),
target_path.Append(installer::kChromeExe).value(),
- temp_dir.value(), WorkItem::NEW_NAME_IF_IN_USE, new_chrome_exe.value());
+ temp_path.value(), WorkItem::NEW_NAME_IF_IN_USE, new_chrome_exe.value());
// Extra executable for 64 bit systems.
if (Is64bit()) {
install_list->AddCopyTreeWorkItem(
src_path.Append(installer::kWowHelperExe).value(),
target_path.Append(installer::kWowHelperExe).value(),
- temp_dir.value(), WorkItem::ALWAYS);
+ temp_path.value(), WorkItem::ALWAYS);
}
// If it is system level install copy the version folder (since we want to
// take the permissions of %ProgramFiles% folder) otherwise just move it.
if (installer_state.system_install()) {
install_list->AddCopyTreeWorkItem(
- src_path.Append(UTF8ToWide(new_version.GetString())).value(),
- target_path.Append(UTF8ToWide(new_version.GetString())).value(),
- temp_dir.value(), WorkItem::ALWAYS);
+ src_path.AppendASCII(new_version.GetString()).value(),
+ target_path.AppendASCII(new_version.GetString()).value(),
+ temp_path.value(), WorkItem::ALWAYS);
} else {
install_list->AddMoveTreeWorkItem(
- src_path.Append(UTF8ToWide(new_version.GetString())).value(),
- target_path.Append(UTF8ToWide(new_version.GetString())).value(),
- temp_dir.value());
+ src_path.AppendASCII(new_version.GetString()).value(),
+ target_path.AppendASCII(new_version.GetString()).value(),
+ temp_path.value());
}
// Copy the default Dictionaries only if the folder doesn't exist already.
install_list->AddCopyTreeWorkItem(
src_path.Append(installer::kDictionaries).value(),
target_path.Append(installer::kDictionaries).value(),
- temp_dir.value(), WorkItem::IF_NOT_PRESENT);
+ temp_path.value(), WorkItem::IF_NOT_PRESENT);
// Delete any old_chrome.exe if present.
install_list->AddDeleteTreeWorkItem(
- target_path.Append(installer::kChromeOldExe));
+ target_path.Append(installer::kChromeOldExe), temp_path);
// Copy installer in install directory and
// add shortcut in Control Panel->Add/Remove Programs.
- AddInstallerCopyTasks(installer_state, setup_path, archive_path, temp_dir,
+ AddInstallerCopyTasks(installer_state, setup_path, archive_path, temp_path,
new_version, install_list);
const HKEY root = installer_state.root_key();
@@ -623,6 +626,7 @@ void AddInstallWorkItems(const InstallationState& original_state,
new_chrome_exe,
current_version->get(),
new_version,
+ temp_path,
install_list);
}
diff --git a/chrome/installer/setup/install_worker.h b/chrome/installer/setup/install_worker.h
index 596b367..fd78922 100644
--- a/chrome/installer/setup/install_worker.h
+++ b/chrome/installer/setup/install_worker.h
@@ -51,6 +51,7 @@ bool AppendPostInstallTasks(const InstallerState& installer_state,
const FilePath& new_chrome_exe,
const Version* current_version,
const Version& new_version,
+ const FilePath& temp_path,
WorkItemList* post_install_task_list);
// Builds the complete WorkItemList used to build the set of installation steps
@@ -62,14 +63,14 @@ bool AppendPostInstallTasks(const InstallerState& installer_state,
// to Chrome install folder after install is complete
// src_path: the path that contains a complete and unpacked Chrome package
// to be installed.
-// temp_dir: the path of working directory used during installation. This path
-// does not need to exist.
+// temp_path: the path of working directory used during installation. This path
+// does not need to exist.
void AddInstallWorkItems(const InstallationState& original_state,
const InstallerState& installer_state,
const FilePath& setup_path,
const FilePath& archive_path,
const FilePath& src_path,
- const FilePath& temp_dir,
+ const FilePath& temp_path,
const Version& new_version,
scoped_ptr<Version>* current_version,
WorkItemList* install_list);
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 6377114..b34759e 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -16,6 +16,7 @@
#include "base/file_version_info.h"
#include "base/path_service.h"
#include "base/process_util.h"
+#include "base/scoped_temp_dir.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
@@ -114,8 +115,8 @@ DWORD UnPackArchive(const FilePath& archive,
return installer::CHROME_NOT_INSTALLED;
}
- FilePath existing_archive(installer_state.target_path().Append(
- UTF8ToWide(archive_version->GetString())));
+ FilePath existing_archive(installer_state.target_path().AppendASCII(
+ archive_version->GetString()));
existing_archive = existing_archive.Append(installer::kInstallerDir);
existing_archive = existing_archive.Append(installer::kChromeArchive);
if (int i = installer::ApplyDiffPatch(FilePath(existing_archive),
@@ -142,23 +143,23 @@ installer::InstallStatus RenameChromeExecutables(
const InstallerState& installer_state) {
const FilePath &target_path = installer_state.target_path();
FilePath chrome_exe(target_path.Append(installer::kChromeExe));
- FilePath chrome_old_exe(target_path.Append(installer::kChromeOldExe));
FilePath chrome_new_exe(target_path.Append(installer::kChromeNewExe));
- scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
- install_list->AddDeleteTreeWorkItem(chrome_old_exe);
- FilePath temp_path;
- if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) {
- LOG(ERROR) << "Failed to create Temp directory " << temp_path.value();
+ // TODO(grt): Create the temp dir in the target_path rather than %TMP% and
+ // friends since it/they may be on another volume, which prevents us from
+ // moving an in-use chrome.exe out of the way.
+ ScopedTempDir temp_path;
+ if (!temp_path.CreateUniqueTempDir()) {
+ PLOG(ERROR) << "Failed to create Temp directory";
return installer::RENAME_FAILED;
}
-
+ scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
install_list->AddCopyTreeWorkItem(chrome_new_exe.value(),
chrome_exe.value(),
- temp_path.value(),
+ temp_path.path().value(),
WorkItem::IF_DIFFERENT,
std::wstring());
- install_list->AddDeleteTreeWorkItem(chrome_new_exe);
+ install_list->AddDeleteTreeWorkItem(chrome_new_exe, temp_path.path());
HKEY reg_root = installer_state.root_key();
const Products& products = installer_state.products();
@@ -179,7 +180,6 @@ installer::InstallStatus RenameChromeExecutables(
install_list->Rollback();
ret = installer::RENAME_FAILED;
}
- file_util::Delete(temp_path, true);
return ret;
}
@@ -479,18 +479,18 @@ installer::InstallStatus InstallProductsHelper(
// Create a temp folder where we will unpack Chrome archive. If it fails,
// then we are doomed, so return immediately and no cleanup is required.
- FilePath temp_path;
- if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) {
- LOG(ERROR) << "Could not create temporary path.";
+ ScopedTempDir temp_path;
+ if (!temp_path.CreateUniqueTempDir()) {
+ PLOG(ERROR) << "Could not create temporary path.";
InstallUtil::WriteInstallerResult(system_install,
installer_state.state_key(), installer::TEMP_DIR_FAILED,
IDS_INSTALL_TEMP_DIR_FAILED_BASE, NULL);
return installer::TEMP_DIR_FAILED;
}
- VLOG(1) << "created path " << temp_path.value();
+ VLOG(1) << "created path " << temp_path.path().value();
- FilePath unpack_path(temp_path.Append(installer::kInstallSourceDir));
- if (UnPackArchive(archive, installer_state, temp_path, unpack_path,
+ FilePath unpack_path(temp_path.path().Append(installer::kInstallSourceDir));
+ if (UnPackArchive(archive, installer_state, temp_path.path(), unpack_path,
archive_type)) {
install_status = installer::UNCOMPRESSION_FAILED;
InstallUtil::WriteInstallerResult(system_install,
@@ -543,12 +543,13 @@ installer::InstallStatus InstallProductsHelper(
if (!higher_version_installed) {
// We want to keep uncompressed archive (chrome.7z) that we get after
// uncompressing and binary patching. Get the location for this file.
- FilePath archive_to_copy(temp_path.Append(installer::kChromeArchive));
+ FilePath archive_to_copy(
+ temp_path.path().Append(installer::kChromeArchive));
FilePath prefs_source_path(cmd_line.GetSwitchValueNative(
installer::switches::kInstallerData));
install_status = installer::InstallOrUpdateProduct(original_state,
- installer_state, cmd_line.GetProgram(), archive_to_copy, temp_path,
- prefs_source_path, prefs, *installer_version);
+ installer_state, cmd_line.GetProgram(), archive_to_copy,
+ temp_path.path(), prefs_source_path, prefs, *installer_version);
int install_msg_base = IDS_INSTALL_FAILED_BASE;
std::wstring chrome_exe;
@@ -633,8 +634,8 @@ installer::InstallStatus InstallProductsHelper(
// and master profile file if present. Note that we do not care about rollback
// here and we schedule for deletion on reboot below if the deletes fail. As
// such, we do not use DeleteTreeWorkItem.
- VLOG(1) << "Deleting temporary directory " << temp_path.value();
- bool cleanup_success = file_util::Delete(temp_path, true);
+ VLOG(1) << "Deleting temporary directory " << temp_path.path().value();
+ bool cleanup_success = temp_path.Delete();
if (cmd_line.HasSwitch(installer::switches::kInstallerData)) {
std::wstring prefs_path = cmd_line.GetSwitchValueNative(
installer::switches::kInstallerData);
@@ -648,7 +649,7 @@ installer::InstallStatus InstallProductsHelper(
// this, if we fail to delete the temp folders, then schedule them for
// deletion at next reboot.
if (!cleanup_success) {
- ScheduleDirectoryForDeletion(temp_path.value().c_str());
+ ScheduleDirectoryForDeletion(temp_path.path().value().c_str());
if (cmd_line.HasSwitch(installer::switches::kInstallerData)) {
std::wstring prefs_path = cmd_line.GetSwitchValueNative(
installer::switches::kInstallerData);
@@ -758,15 +759,15 @@ bool HandleNonInstallCmdLineOptions(const InstallationState& original_state,
// patch to current exe, and store the resulting binary in the path
// specified by --new-setup-exe. But we need to first unpack the file
// given in --update-setup-exe.
- FilePath temp_path;
- if (!file_util::CreateNewTempDirectory(L"chrome_", &temp_path)) {
- LOG(ERROR) << "Could not create temporary path.";
+ ScopedTempDir temp_path;
+ if (!temp_path.CreateUniqueTempDir()) {
+ PLOG(ERROR) << "Could not create temporary path.";
} else {
std::wstring setup_patch = cmd_line.GetSwitchValueNative(
installer::switches::kUpdateSetupExe);
VLOG(1) << "Opening archive " << setup_patch;
std::wstring uncompressed_patch;
- if (LzmaUtil::UnPackArchive(setup_patch, temp_path.value(),
+ if (LzmaUtil::UnPackArchive(setup_patch, temp_path.path().value(),
&uncompressed_patch) == NO_ERROR) {
FilePath old_setup_exe = cmd_line.GetProgram();
FilePath new_setup_exe = cmd_line.GetSwitchValuePath(
@@ -785,7 +786,6 @@ bool HandleNonInstallCmdLineOptions(const InstallationState& original_state,
installer_state->state_key(), status, IDS_SETUP_PATCH_FAILED_BASE,
NULL);
}
- file_util::Delete(temp_path, true);
} else if (cmd_line.HasSwitch(installer::switches::kShowEula)) {
// Check if we need to show the EULA. If it is passed as a command line
// then the dialog is shown and regardless of the outcome setup exits here.
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index 21a1dcb..46bb73d 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -690,8 +690,8 @@ InstallStatus UninstallProduct(const InstallationState& original_state,
if (product_state != NULL) {
std::vector<FilePath> com_dll_list;
product.AddComDllList(&com_dll_list);
- FilePath dll_folder = installer_state.target_path().Append(
- UTF8ToWide(product_state->version().GetString()));
+ FilePath dll_folder = installer_state.target_path().AppendASCII(
+ product_state->version().GetString());
scoped_ptr<WorkItemList> unreg_work_item_list(
WorkItem::CreateWorkItemList());
diff --git a/chrome/installer/util/copy_tree_work_item.cc b/chrome/installer/util/copy_tree_work_item.cc
index f60c822..6461cd6 100644
--- a/chrome/installer/util/copy_tree_work_item.cc
+++ b/chrome/installer/util/copy_tree_work_item.cc
@@ -11,9 +11,6 @@
#include "chrome/installer/util/logging_installer.h"
CopyTreeWorkItem::~CopyTreeWorkItem() {
- if (file_util::PathExists(backup_path_)) {
- file_util::Delete(backup_path_, true);
- }
}
CopyTreeWorkItem::CopyTreeWorkItem(const FilePath& source_path,
@@ -40,7 +37,7 @@ bool CopyTreeWorkItem::Do() {
bool dest_exist = file_util::PathExists(dest_path_);
// handle overwrite_option_ = IF_DIFFERENT case.
if ((dest_exist) &&
- (overwrite_option_ == WorkItem::IF_DIFFERENT) && // only for single file
+ (overwrite_option_ == WorkItem::IF_DIFFERENT) && // only for single file
(!file_util::DirectoryExists(source_path_)) &&
(!file_util::DirectoryExists(dest_path_)) &&
(file_util::ContentsEqual(source_path_, dest_path_))) {
@@ -74,16 +71,20 @@ bool CopyTreeWorkItem::Do() {
// In all cases that reach here, move dest to a backup path.
if (dest_exist) {
- if (!GetBackupPath())
+ if (!backup_path_.CreateUniqueTempDirUnderPath(temp_dir_)) {
+ PLOG(ERROR) << "Failed to get backup path in folder "
+ << temp_dir_.value();
return false;
+ }
- if (file_util::Move(dest_path_, backup_path_)) {
+ FilePath backup = backup_path_.path().Append(dest_path_.BaseName());
+ if (file_util::Move(dest_path_, backup)) {
moved_to_backup_ = true;
VLOG(1) << "Moved destination " << dest_path_.value() <<
- " to backup path " << backup_path_.value();
+ " to backup path " << backup.value();
} else {
LOG(ERROR) << "failed moving " << dest_path_.value()
- << " to " << backup_path_.value();
+ << " to " << backup.value();
return false;
}
}
@@ -104,16 +105,19 @@ bool CopyTreeWorkItem::Do() {
void CopyTreeWorkItem::Rollback() {
// Normally the delete operations below should not fail unless some
- // programs like anti-virus are inpecting the files we just copied.
+ // programs like anti-virus are inspecting the files we just copied.
// If this does happen sometimes, we may consider using Move instead of
// Delete here. For now we just log the error and continue with the
// rest of rollback operation.
if (copied_to_dest_path_ && !file_util::Delete(dest_path_, true)) {
LOG(ERROR) << "Can not delete " << dest_path_.value();
}
- if (moved_to_backup_ && !file_util::Move(backup_path_, dest_path_)) {
- LOG(ERROR) << "failed move " << backup_path_.value()
- << " to " << dest_path_.value();
+ if (moved_to_backup_) {
+ FilePath backup(backup_path_.path().Append(dest_path_.BaseName()));
+ if (!file_util::Move(backup, dest_path_)) {
+ LOG(ERROR) << "failed move " << backup.value()
+ << " to " << dest_path_.value();
+ }
}
if (copied_to_alternate_path_ &&
!file_util::Delete(alternative_path_, true)) {
@@ -133,18 +137,3 @@ bool CopyTreeWorkItem::IsFileInUse(const FilePath& path) {
CloseHandle(handle);
return false;
}
-
-bool CopyTreeWorkItem::GetBackupPath() {
- backup_path_ = temp_dir_.Append(dest_path_.BaseName());
-
- if (file_util::PathExists(backup_path_)) {
- // Ideally we should not fail immediately. Instead we could try some
- // random paths under temp_dir_ until we reach certain limit.
- // For now our caller always provides a good temporary directory so
- // we don't bother.
- LOG(ERROR) << "backup path " << backup_path_.value() << " already exists";
- return false;
- }
-
- return true;
-}
diff --git a/chrome/installer/util/copy_tree_work_item.h b/chrome/installer/util/copy_tree_work_item.h
index 830a0d4..1e248ce 100644
--- a/chrome/installer/util/copy_tree_work_item.h
+++ b/chrome/installer/util/copy_tree_work_item.h
@@ -6,11 +6,9 @@
#define CHROME_INSTALLER_UTIL_COPY_TREE_WORK_ITEM_H_
#pragma once
-#include <windows.h>
-
-#include <string>
-
#include "base/file_path.h"
+#include "base/gtest_prod_util.h"
+#include "base/scoped_temp_dir.h"
#include "chrome/installer/util/work_item.h"
// A WorkItem subclass that recursively copies a file system hierarchy from
@@ -46,10 +44,6 @@ class CopyTreeWorkItem : public WorkItem {
// Checks if the path specified is in use (and hence can not be deleted)
bool IsFileInUse(const FilePath& path);
- // Get a backup path that can keep the original files under dest_path_,
- // and set backup_path_ with the result.
- bool GetBackupPath();
-
// Source path to copy files from.
FilePath source_path_;
@@ -78,9 +72,14 @@ class CopyTreeWorkItem : public WorkItem {
// existed and was in use. Needed during rollback.
bool copied_to_alternate_path_;
- // The full path in temporary directory that the original dest_path_ has
- // been moved to.
- FilePath backup_path_;
+ // The temporary directory into which the original dest_path_ has been moved.
+ ScopedTempDir backup_path_;
+
+ FRIEND_TEST_ALL_PREFIXES(CopyTreeWorkItemTest, CopyFileSameContent);
+ FRIEND_TEST_ALL_PREFIXES(CopyTreeWorkItemTest, CopyFileInUse);
+ FRIEND_TEST_ALL_PREFIXES(CopyTreeWorkItemTest, CopyFileAndCleanup);
+ FRIEND_TEST_ALL_PREFIXES(CopyTreeWorkItemTest, NewNameAndCopyTest);
+ FRIEND_TEST_ALL_PREFIXES(CopyTreeWorkItemTest, CopyFileInUseAndCleanup);
};
#endif // CHROME_INSTALLER_UTIL_COPY_TREE_WORK_ITEM_H_
diff --git a/chrome/installer/util/copy_tree_work_item_unittest.cc b/chrome/installer/util/copy_tree_work_item_unittest.cc
index 931dff8..ee1eae7 100644
--- a/chrome/installer/util/copy_tree_work_item_unittest.cc
+++ b/chrome/installer/util/copy_tree_work_item_unittest.cc
@@ -217,10 +217,6 @@ TEST_F(CopyTreeWorkItemTest, CopyFileSameContent) {
CreateTextFile(file_name_to.value(), text_content_1);
ASSERT_TRUE(file_util::PathExists(file_name_to));
- // Get the path of backup file
- FilePath backup_file(temp_dir_);
- backup_file = backup_file.AppendASCII("File_To.txt");
-
// test Do() with always_overwrite being true.
scoped_ptr<CopyTreeWorkItem> work_item(
WorkItem::CreateCopyTreeWorkItem(file_name_from,
@@ -231,6 +227,11 @@ TEST_F(CopyTreeWorkItemTest, CopyFileSameContent) {
EXPECT_TRUE(work_item->Do());
+ // Get the path of backup file
+ FilePath backup_file(work_item->backup_path_.path());
+ EXPECT_FALSE(backup_file.empty());
+ backup_file = backup_file.AppendASCII("File_To.txt");
+
EXPECT_TRUE(file_util::PathExists(file_name_from));
EXPECT_TRUE(file_util::PathExists(file_name_to));
EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
@@ -297,9 +298,7 @@ TEST_F(CopyTreeWorkItemTest, CopyFileAndCleanup) {
CreateTextFile(file_name_to.value(), text_content_2);
ASSERT_TRUE(file_util::PathExists(file_name_to));
- // Get the path of backup file
- FilePath backup_file(temp_dir_);
- backup_file = backup_file.AppendASCII("File_To.txt");
+ FilePath backup_file;
{
// test Do().
@@ -312,6 +311,11 @@ TEST_F(CopyTreeWorkItemTest, CopyFileAndCleanup) {
EXPECT_TRUE(work_item->Do());
+ // Get the path of backup file
+ backup_file = work_item->backup_path_.path();
+ EXPECT_FALSE(backup_file.empty());
+ backup_file = backup_file.AppendASCII("File_To.txt");
+
EXPECT_TRUE(file_util::PathExists(file_name_from));
EXPECT_TRUE(file_util::PathExists(file_name_to));
EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
@@ -361,10 +365,6 @@ TEST_F(CopyTreeWorkItemTest, CopyFileInUse) {
NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED,
NULL, NULL, &si, &pi));
- // Get the path of backup file
- FilePath backup_file(temp_dir_);
- backup_file = backup_file.AppendASCII("File_To");
-
// test Do().
scoped_ptr<CopyTreeWorkItem> work_item(
WorkItem::CreateCopyTreeWorkItem(file_name_from,
@@ -375,6 +375,11 @@ TEST_F(CopyTreeWorkItemTest, CopyFileInUse) {
EXPECT_TRUE(work_item->Do());
+ // Get the path of backup file
+ FilePath backup_file(work_item->backup_path_.path());
+ EXPECT_FALSE(backup_file.empty());
+ backup_file = backup_file.AppendASCII("File_To");
+
EXPECT_TRUE(file_util::PathExists(file_name_from));
EXPECT_TRUE(file_util::PathExists(file_name_to));
EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
@@ -440,10 +445,6 @@ TEST_F(CopyTreeWorkItemTest, NewNameAndCopyTest) {
NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED,
NULL, NULL, &si, &pi));
- // Get the path of backup file
- FilePath backup_file(temp_dir_);
- backup_file = backup_file.AppendASCII("File_To");
-
// test Do().
scoped_ptr<CopyTreeWorkItem> work_item(
WorkItem::CreateCopyTreeWorkItem(file_name_from,
@@ -459,7 +460,7 @@ TEST_F(CopyTreeWorkItemTest, NewNameAndCopyTest) {
EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, file_name_to));
// verify that the backup path does not exist
- EXPECT_FALSE(file_util::PathExists(backup_file));
+ EXPECT_TRUE(work_item->backup_path_.path().empty());
EXPECT_TRUE(file_util::ContentsEqual(file_name_from, alternate_to));
// test rollback()
@@ -469,7 +470,7 @@ TEST_F(CopyTreeWorkItemTest, NewNameAndCopyTest) {
EXPECT_TRUE(file_util::PathExists(file_name_to));
EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, file_name_to));
- EXPECT_FALSE(file_util::PathExists(backup_file));
+ EXPECT_TRUE(work_item->backup_path_.path().empty());
// the alternate file should be gone after rollback
EXPECT_FALSE(file_util::PathExists(alternate_to));
@@ -490,6 +491,11 @@ TEST_F(CopyTreeWorkItemTest, NewNameAndCopyTest) {
ASSERT_FALSE(IsFileInUse(file_name_to));
EXPECT_TRUE(work_item->Do());
+ // Get the path of backup file
+ FilePath backup_file(work_item->backup_path_.path());
+ EXPECT_FALSE(backup_file.empty());
+ backup_file = backup_file.AppendASCII("File_To");
+
EXPECT_TRUE(file_util::PathExists(file_name_from));
EXPECT_TRUE(file_util::PathExists(file_name_to));
EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
@@ -631,9 +637,7 @@ TEST_F(CopyTreeWorkItemTest, FLAKY_CopyFileInUseAndCleanup) {
NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED,
NULL, NULL, &si, &pi));
- // Get the path of backup file
- FilePath backup_file(temp_dir_);
- backup_file = backup_file.AppendASCII("File_To");
+ FilePath backup_file;
// test Do().
{
@@ -646,6 +650,11 @@ TEST_F(CopyTreeWorkItemTest, FLAKY_CopyFileInUseAndCleanup) {
EXPECT_TRUE(work_item->Do());
+ // Get the path of backup file
+ backup_file = work_item->backup_path_.path();
+ EXPECT_FALSE(backup_file.empty());
+ backup_file = backup_file.AppendASCII("File_To");
+
EXPECT_TRUE(file_util::PathExists(file_name_from));
EXPECT_TRUE(file_util::PathExists(file_name_to));
EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
diff --git a/chrome/installer/util/delete_tree_work_item.cc b/chrome/installer/util/delete_tree_work_item.cc
index 76d5a8c..e288ee4 100644
--- a/chrome/installer/util/delete_tree_work_item.cc
+++ b/chrome/installer/util/delete_tree_work_item.cc
@@ -2,38 +2,47 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "chrome/installer/util/delete_tree_work_item.h"
+
+#include <algorithm>
+#include <limits>
+
#include "base/file_util.h"
#include "base/logging.h"
-#include "chrome/installer/util/delete_tree_work_item.h"
+
+namespace {
+
+// Casts a value of an unsigned type to a signed type of the same size provided
+// that there is no overflow.
+template<typename L, typename R>
+bool SafeCast(L left, R* right) {
+ DCHECK(right);
+ COMPILE_ASSERT(sizeof(left) == sizeof(right),
+ must_add_support_for_crazy_data_types);
+ if (left > static_cast<L>(std::numeric_limits<R>::max()))
+ return false;
+ *right = static_cast<L>(left);
+ return true;
+}
+
+} // namespace
DeleteTreeWorkItem::DeleteTreeWorkItem(
const FilePath& root_path,
+ const FilePath& temp_path,
const std::vector<FilePath>& key_paths)
- : root_path_(root_path) {
- // Populate our key_paths_ list with empty backup path values.
- std::vector<FilePath>::const_iterator it(key_paths.begin());
- for (; it != key_paths.end(); ++it) {
- key_paths_.push_back(KeyFileList::value_type(*it, FilePath()));
+ : root_path_(root_path),
+ temp_path_(temp_path) {
+ if (!SafeCast(key_paths.size(), &num_key_files_)) {
+ NOTREACHED() << "Impossibly large key_paths collection";
+ } else if (num_key_files_ != 0) {
+ key_paths_.reset(new FilePath[num_key_files_]);
+ key_backup_paths_.reset(new ScopedTempDir[num_key_files_]);
+ std::copy(key_paths.begin(), key_paths.end(), &key_paths_[0]);
}
}
DeleteTreeWorkItem::~DeleteTreeWorkItem() {
- if (!backup_path_.empty()) {
- FilePath tmp_dir = backup_path_.DirName();
- if (file_util::PathExists(tmp_dir)) {
- file_util::Delete(tmp_dir, true);
- }
- }
-
- KeyFileList::const_iterator it(key_paths_.begin());
- for (; it != key_paths_.end(); ++it) {
- if (!it->second.empty()) {
- FilePath tmp_dir = it->second.DirName();
- if (file_util::PathExists(tmp_dir)) {
- file_util::Delete(tmp_dir, true);
- }
- }
- }
}
// We first try to move key_path_ to backup_path. If it succeeds, we go ahead
@@ -42,26 +51,31 @@ bool DeleteTreeWorkItem::Do() {
// Go through all the key files and see if we can open them exclusively
// with only the FILE_SHARE_DELETE flag. Once we know we have all of them,
// we can delete them.
- KeyFileList::iterator it(key_paths_.begin());
std::vector<HANDLE> opened_key_files;
+ opened_key_files.reserve(num_key_files_);
bool abort = false;
- for (; !abort && it != key_paths_.end(); ++it) {
- if (!GetBackupPath(it->first, &it->second) ||
- !file_util::CopyFile(it->first, it->second)) {
- PLOG(ERROR) << "Could not back up: " << it->first.value();
+ for (ptrdiff_t i = 0; !abort && i != num_key_files_; ++i) {
+ FilePath& key_file = key_paths_[i];
+ ScopedTempDir& backup = key_backup_paths_[i];
+ if (!backup.CreateUniqueTempDirUnderPath(temp_path_)) {
+ PLOG(ERROR) << "Could not create temp dir in " << temp_path_.value();
+ abort = true;
+ } else if (!file_util::CopyFile(key_file,
+ backup.path().Append(key_file.BaseName()))) {
+ PLOG(ERROR) << "Could not back up " << key_file.value()
+ << " to directory " << backup.path().value();
abort = true;
} else {
- HANDLE file = ::CreateFile(it->first.value().c_str(), FILE_ALL_ACCESS,
+ HANDLE file = ::CreateFile(key_file.value().c_str(), FILE_ALL_ACCESS,
FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0,
NULL);
if (file != INVALID_HANDLE_VALUE) {
- VLOG(1) << "Acquired exclusive lock for key file: "
- << it->first.value();
+ VLOG(1) << "Acquired exclusive lock for key file: " << key_file.value();
opened_key_files.push_back(file);
} else {
if (::GetLastError() != ERROR_FILE_NOT_FOUND)
abort = true;
- PLOG(INFO) << "Failed to open " << it->first.value();
+ PLOG(INFO) << "Failed to open " << key_file.value();
}
}
}
@@ -70,21 +84,17 @@ bool DeleteTreeWorkItem::Do() {
// We now hold exclusive locks with "share delete" permissions for each
// of the key files and also have created backups of those files.
// We can safely delete the key files now.
- it = key_paths_.begin();
- for (; !abort && it != key_paths_.end(); ++it) {
- if (!file_util::Delete(it->first, true)) {
+ for (ptrdiff_t i = 0; !abort && i != num_key_files_; ++i) {
+ FilePath& key_file = key_paths_[i];
+ if (!file_util::Delete(key_file, true)) {
// This should not really be possible because of the above.
- NOTREACHED();
- PLOG(ERROR) << "Unexpectedly could not delete " << it->first.value();
+ PLOG(DFATAL) << "Unexpectedly could not delete " << key_file.value();
abort = true;
}
}
}
- std::vector<HANDLE>::const_iterator file_it(opened_key_files.begin());
- for (; file_it != opened_key_files.end(); ++file_it)
- ::CloseHandle(*file_it);
-
+ std::for_each(opened_key_files.begin(), opened_key_files.end(), CloseHandle);
opened_key_files.clear();
if (abort) {
@@ -94,12 +104,18 @@ bool DeleteTreeWorkItem::Do() {
// Now that we've taken care of the key files, take care of the rest.
if (!root_path_.empty() && file_util::PathExists(root_path_)) {
- if (!GetBackupPath(root_path_, &backup_path_) ||
- !file_util::CopyDirectory(root_path_, backup_path_, true) ||
- !file_util::Delete(root_path_, true)) {
- LOG(ERROR) << "can not delete " << root_path_.value()
- << " OR copy it to backup path " << backup_path_.value();
+ if (!backup_path_.CreateUniqueTempDirUnderPath(temp_path_)) {
+ PLOG(ERROR) << "Failed to get backup path in folder "
+ << temp_path_.value();
return false;
+ } else {
+ FilePath backup = backup_path_.path().Append(root_path_.BaseName());
+ if (!file_util::CopyDirectory(root_path_, backup, true) ||
+ !file_util::Delete(root_path_, true)) {
+ LOG(ERROR) << "can not delete " << root_path_.value()
+ << " OR copy it to backup path " << backup.value();
+ return false;
+ }
}
}
@@ -108,30 +124,23 @@ bool DeleteTreeWorkItem::Do() {
// If there are files in backup paths move them back.
void DeleteTreeWorkItem::Rollback() {
- if (!backup_path_.empty() && file_util::PathExists(backup_path_)) {
- file_util::Move(backup_path_, root_path_);
+ if (!backup_path_.path().empty()) {
+ FilePath backup = backup_path_.path().Append(root_path_.BaseName());
+ if (file_util::PathExists(backup))
+ file_util::Move(backup, root_path_);
}
- KeyFileList::const_iterator it(key_paths_.begin());
- for (; it != key_paths_.end(); ++it) {
- if (!it->second.empty() && file_util::PathExists(it->second)) {
- if (!file_util::Move(it->second, it->first)) {
+ for (ptrdiff_t i = 0; i != num_key_files_; ++i) {
+ ScopedTempDir& backup_dir = key_backup_paths_[i];
+ if (!backup_dir.path().empty()) {
+ FilePath& key_file = key_paths_[i];
+ FilePath backup_file = backup_dir.path().Append(key_file.BaseName());
+ if (file_util::PathExists(backup_file) &&
+ !file_util::Move(backup_file, key_file)) {
// This could happen if we could not delete the key file to begin with.
PLOG(WARNING) << "Rollback: Failed to move backup file back in place: "
- << it->second.value() << " to " << it->first.value();
+ << backup_file.value() << " to " << key_file.value();
}
}
}
}
-
-bool DeleteTreeWorkItem::GetBackupPath(const FilePath& for_path,
- FilePath* backup_path) {
- if (!file_util::CreateNewTempDirectory(L"", backup_path)) {
- // We assume that CreateNewTempDirectory() is doing its job well.
- LOG(ERROR) << "Couldn't get backup path for delete.";
- return false;
- }
-
- *backup_path = backup_path->Append(for_path.BaseName());
- return true;
-}
diff --git a/chrome/installer/util/delete_tree_work_item.h b/chrome/installer/util/delete_tree_work_item.h
index f57a722..508b885 100644
--- a/chrome/installer/util/delete_tree_work_item.h
+++ b/chrome/installer/util/delete_tree_work_item.h
@@ -6,20 +6,18 @@
#define CHROME_INSTALLER_UTIL_DELETE_TREE_WORK_ITEM_H_
#pragma once
-#include <windows.h>
-
-#include <string>
-#include <utility>
#include <vector>
#include "base/file_path.h"
+#include "base/scoped_ptr.h"
+#include "base/scoped_temp_dir.h"
#include "chrome/installer/util/work_item.h"
// A WorkItem subclass that recursively deletes a file system hierarchy at the
// given root path. The file system hierarchy could be a single file, or a
// directory.
-// The file system hierarchy to be deleted can have a key file. If the key file
-// is specified, deletion will be performed only if the key file is not in use.
+// The file system hierarchy to be deleted can have one or more key files. If
+// specified, deletion will be performed only if all key files are not in use.
class DeleteTreeWorkItem : public WorkItem {
public:
virtual ~DeleteTreeWorkItem();
@@ -31,28 +29,30 @@ class DeleteTreeWorkItem : public WorkItem {
private:
friend class WorkItem;
- // A list of key file paths and paths to a backup of a key file.
- // the 'first' member of the pair has the key file path, the 'second' has
- // the path to the backup.
- typedef std::vector<std::pair<FilePath, FilePath> > KeyFileList;
-
- // Get a backup path that can keep root_path_ or key_paths_
- bool GetBackupPath(const FilePath& for_path, FilePath* backup_path);
-
DeleteTreeWorkItem(const FilePath& root_path,
+ const FilePath& temp_path,
const std::vector<FilePath>& key_paths);
// Root path to delete.
FilePath root_path_;
- // Contains the path to key files and their backups once Do() has been called.
- // If key files are specified, deletion will be performed only if none of the
- // key files are in use.
- KeyFileList key_paths_;
+ // Temporary directory that can be used.
+ FilePath temp_path_;
+
+ // The number of key files.
+ ptrdiff_t num_key_files_;
+
+ // Contains the paths to the key files. If specified, deletion will be
+ // performed only if none of the key files are in use.
+ scoped_array<FilePath> key_paths_;
+
+ // Contains the temp directories for the backed-up key files. The directories
+ // are created and populated in Do() as-needed. We don't use a standard
+ // container for this since ScopedTempDir isn't CopyConstructible.
+ scoped_array<ScopedTempDir> key_backup_paths_;
- // The full path in temporary directory that the original root_path_ has
- // been moved to.
- FilePath backup_path_;
+ // The temporary directory into which the original root_path_ has been moved.
+ ScopedTempDir backup_path_;
};
#endif // CHROME_INSTALLER_UTIL_DELETE_TREE_WORK_ITEM_H_
diff --git a/chrome/installer/util/delete_tree_work_item_unittest.cc b/chrome/installer/util/delete_tree_work_item_unittest.cc
index f87fe93..e2b0074 100644
--- a/chrome/installer/util/delete_tree_work_item_unittest.cc
+++ b/chrome/installer/util/delete_tree_work_item_unittest.cc
@@ -12,6 +12,7 @@
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/scoped_ptr.h"
+#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
#include "chrome/installer/util/delete_tree_work_item.h"
#include "chrome/installer/util/work_item.h"
@@ -85,9 +86,13 @@ TEST_F(DeleteTreeWorkItemTest, DeleteTreeNoKeyPath) {
ASSERT_TRUE(file_util::PathExists(file_name_delete_2));
// test Do()
+ ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
std::vector<FilePath> key_files;
scoped_ptr<DeleteTreeWorkItem> work_item(
- WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, key_files));
+ WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(),
+ key_files));
EXPECT_TRUE(work_item->Do());
// everything should be gone
@@ -133,9 +138,13 @@ TEST_F(DeleteTreeWorkItemTest, DeleteTree) {
ASSERT_TRUE(file_util::PathExists(file_name_delete_2));
// test Do()
+ ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
std::vector<FilePath> key_files(1, file_name_delete_1);
scoped_ptr<DeleteTreeWorkItem> work_item(
- WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, key_files));
+ WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(),
+ key_files));
EXPECT_TRUE(work_item->Do());
// everything should be gone
@@ -202,9 +211,13 @@ TEST_F(DeleteTreeWorkItemTest, DeleteTreeInUse) {
// test Do().
{
+ ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
std::vector<FilePath> key_paths(1, key_path);
scoped_ptr<DeleteTreeWorkItem> work_item(
- WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, key_paths));
+ WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(),
+ key_paths));
// delete should fail as file in use.
EXPECT_FALSE(work_item->Do());
diff --git a/chrome/installer/util/installer_state.cc b/chrome/installer/util/installer_state.cc
index 9137b29..65bc51e 100644
--- a/chrome/installer/util/installer_state.cc
+++ b/chrome/installer/util/installer_state.cc
@@ -388,7 +388,8 @@ FilePath InstallerState::GetInstallerDirectory(const Version& version) const {
}
void InstallerState::RemoveOldVersionDirectories(
- const Version& latest_version) const {
+ const Version& latest_version,
+ const FilePath& temp_path) const {
file_util::FileEnumerator version_enum(target_path(), false,
file_util::FileEnumerator::DIRECTORIES);
scoped_ptr<Version> version;
@@ -417,7 +418,8 @@ void InstallerState::RemoveOldVersionDirectories(
VLOG(1) << "Deleting directory: " << next_version.value();
scoped_ptr<WorkItem> item(
- WorkItem::CreateDeleteTreeWorkItem(next_version, key_files));
+ WorkItem::CreateDeleteTreeWorkItem(next_version, temp_path,
+ key_files));
if (!item->Do())
item->Rollback();
}
diff --git a/chrome/installer/util/installer_state.h b/chrome/installer/util/installer_state.h
index 0b4ea0b..05b8626 100644
--- a/chrome/installer/util/installer_state.h
+++ b/chrome/installer/util/installer_state.h
@@ -145,7 +145,8 @@ class InstallerState {
// Try to delete all directories whose versions are lower than
// |latest_version|.
- void RemoveOldVersionDirectories(const Version& latest_version) const;
+ void RemoveOldVersionDirectories(const Version& latest_version,
+ const FilePath& temp_path) const;
// Adds to |com_dll_list| the list of COM DLLs that are to be registered
// and/or unregistered. The list may be empty.
diff --git a/chrome/installer/util/installer_state_unittest.cc b/chrome/installer/util/installer_state_unittest.cc
index 25efc07..700bffb 100644
--- a/chrome/installer/util/installer_state_unittest.cc
+++ b/chrome/installer/util/installer_state_unittest.cc
@@ -11,6 +11,7 @@
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/process_util.h"
+#include "base/scoped_temp_dir.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/version.h"
@@ -118,7 +119,12 @@ TEST_F(InstallerStateTest, Delete) {
MockInstallerState installer_state;
BuildSingleChromeState(chrome_dir, &installer_state);
scoped_ptr<Version> latest_version(Version::GetVersionFromString("1.0.4.0"));
- installer_state.RemoveOldVersionDirectories(*latest_version.get());
+ {
+ ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ installer_state.RemoveOldVersionDirectories(*latest_version.get(),
+ temp_dir.path());
+ }
// old versions should be gone
EXPECT_FALSE(file_util::PathExists(chrome_dir_1));
@@ -193,7 +199,12 @@ TEST_F(InstallerStateTest, DeleteInUsed) {
MockInstallerState installer_state;
BuildSingleChromeState(chrome_dir, &installer_state);
scoped_ptr<Version> latest_version(Version::GetVersionFromString("1.0.4.0"));
- installer_state.RemoveOldVersionDirectories(*latest_version.get());
+ {
+ ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ installer_state.RemoveOldVersionDirectories(*latest_version.get(),
+ temp_dir.path());
+ }
// old versions not in used should be gone
EXPECT_FALSE(file_util::PathExists(chrome_dir_1));
@@ -265,7 +276,12 @@ TEST_F(InstallerStateTest, Basic) {
EXPECT_TRUE(file.IsValid());
EXPECT_TRUE(file_util::PathExists(old_chrome_dll));
- installer_state.RemoveOldVersionDirectories(*new_version.get());
+ ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+ installer_state.RemoveOldVersionDirectories(*new_version.get(),
+ temp_dir.path());
+
// The old directory should still exist.
EXPECT_TRUE(file_util::PathExists(old_version_dir));
EXPECT_TRUE(file_util::PathExists(new_version_dir));
@@ -273,7 +289,8 @@ TEST_F(InstallerStateTest, Basic) {
// Now close the file handle to make it possible to delete our key file.
file.Close();
- installer_state.RemoveOldVersionDirectories(*new_version.get());
+ installer_state.RemoveOldVersionDirectories(*new_version.get(),
+ temp_dir.path());
// The new directory should still exist.
EXPECT_TRUE(file_util::PathExists(new_version_dir));
diff --git a/chrome/installer/util/move_tree_work_item.cc b/chrome/installer/util/move_tree_work_item.cc
index 027de2f..b4a7cc6 100644
--- a/chrome/installer/util/move_tree_work_item.cc
+++ b/chrome/installer/util/move_tree_work_item.cc
@@ -11,9 +11,6 @@
#include "chrome/installer/util/logging_installer.h"
MoveTreeWorkItem::~MoveTreeWorkItem() {
- if (file_util::PathExists(backup_path_)) {
- file_util::Delete(backup_path_, true);
- }
}
MoveTreeWorkItem::MoveTreeWorkItem(const FilePath& source_path,
@@ -35,19 +32,21 @@ bool MoveTreeWorkItem::Do() {
// If dest_path_ exists, move destination to a backup path.
if (file_util::PathExists(dest_path_)) {
// Generate a backup path that can keep the original files under dest_path_.
- if (!file_util::CreateTemporaryFileInDir(FilePath(temp_dir_),
- &backup_path_)) {
- LOG(ERROR) << "Failed to get backup path in folder " << temp_dir_.value();
+ if (!backup_path_.CreateUniqueTempDirUnderPath(temp_dir_)) {
+ PLOG(ERROR) << "Failed to get backup path in folder "
+ << temp_dir_.value();
return false;
}
- if (file_util::Move(dest_path_, backup_path_)) {
+ FilePath backup = backup_path_.path().Append(dest_path_.BaseName());
+
+ if (file_util::Move(dest_path_, backup)) {
moved_to_backup_ = true;
VLOG(1) << "Moved destination " << dest_path_.value()
- << " to backup path " << backup_path_.value();
+ << " to backup path " << backup.value();
} else {
LOG(ERROR) << "failed moving " << dest_path_.value()
- << " to " << backup_path_.value();
+ << " to " << backup.value();
return false;
}
}
@@ -71,7 +70,11 @@ void MoveTreeWorkItem::Rollback() {
LOG(ERROR) << "Can not move " << dest_path_.value()
<< " to " << source_path_.value();
- if (moved_to_backup_ && !file_util::Move(backup_path_, dest_path_))
- LOG(ERROR) << "failed move " << backup_path_.value()
- << " to " << dest_path_.value();
+ if (moved_to_backup_) {
+ FilePath backup = backup_path_.path().Append(dest_path_.BaseName());
+ if (!file_util::Move(backup, dest_path_)) {
+ LOG(ERROR) << "failed move " << backup.value()
+ << " to " << dest_path_.value();
+ }
+ }
}
diff --git a/chrome/installer/util/move_tree_work_item.h b/chrome/installer/util/move_tree_work_item.h
index f1941cd8..b4d97cf 100644
--- a/chrome/installer/util/move_tree_work_item.h
+++ b/chrome/installer/util/move_tree_work_item.h
@@ -6,11 +6,8 @@
#define CHROME_INSTALLER_UTIL_MOVE_TREE_WORK_ITEM_H_
#pragma once
-#include <windows.h>
-
-#include <string>
-
#include "base/file_path.h"
+#include "base/scoped_temp_dir.h"
#include "chrome/installer/util/work_item.h"
// A WorkItem subclass that recursively move a file system hierarchy from
@@ -49,9 +46,8 @@ class MoveTreeWorkItem : public WorkItem {
// Temporary directory to backup dest_path_ (if it already exists).
FilePath temp_dir_;
- // The full path in temp_dir_ where the original dest_path_ has
- // been moved to.
- FilePath backup_path_;
+ // The temporary directory into which the original dest_path_ has been moved.
+ ScopedTempDir backup_path_;
// Whether the source was moved to dest_path_
bool moved_to_dest_path_;
diff --git a/chrome/installer/util/work_item.cc b/chrome/installer/util/work_item.cc
index 2d40d36..59583f9 100644
--- a/chrome/installer/util/work_item.cc
+++ b/chrome/installer/util/work_item.cc
@@ -54,8 +54,10 @@ DeleteRegValueWorkItem* WorkItem::CreateDeleteRegValueWorkItem(
}
DeleteTreeWorkItem* WorkItem::CreateDeleteTreeWorkItem(
- const FilePath& root_path, const std::vector<FilePath>& key_paths) {
- return new DeleteTreeWorkItem(root_path, key_paths);
+ const FilePath& root_path,
+ const FilePath& temp_path,
+ const std::vector<FilePath>& key_paths) {
+ return new DeleteTreeWorkItem(root_path, temp_path, key_paths);
}
MoveTreeWorkItem* WorkItem::CreateMoveTreeWorkItem(
diff --git a/chrome/installer/util/work_item.h b/chrome/installer/util/work_item.h
index 9b98cc6..66925ed 100644
--- a/chrome/installer/util/work_item.h
+++ b/chrome/installer/util/work_item.h
@@ -88,7 +88,9 @@ class WorkItem {
// hierarchy at the given root path. A key file can be optionally specified
// by key_path.
static DeleteTreeWorkItem* CreateDeleteTreeWorkItem(
- const FilePath& root_path, const std::vector<FilePath>& key_paths);
+ const FilePath& root_path,
+ const FilePath& temp_path,
+ const std::vector<FilePath>& key_paths);
// Create a MoveTreeWorkItem that recursively moves a file system hierarchy
// from source path to destination path.
diff --git a/chrome/installer/util/work_item_list.cc b/chrome/installer/util/work_item_list.cc
index 39249c4..3156f7d 100644
--- a/chrome/installer/util/work_item_list.cc
+++ b/chrome/installer/util/work_item_list.cc
@@ -119,15 +119,18 @@ WorkItem* WorkItemList::AddDeleteRegValueWorkItem(
WorkItem* WorkItemList::AddDeleteTreeWorkItem(
const FilePath& root_path,
+ const FilePath& temp_path,
const std::vector<FilePath>& key_paths) {
- WorkItem* item = WorkItem::CreateDeleteTreeWorkItem(root_path, key_paths);
+ WorkItem* item = WorkItem::CreateDeleteTreeWorkItem(root_path, temp_path,
+ key_paths);
AddWorkItem(item);
return item;
}
-WorkItem* WorkItemList::AddDeleteTreeWorkItem(const FilePath& root_path) {
+WorkItem* WorkItemList::AddDeleteTreeWorkItem(const FilePath& root_path,
+ const FilePath& temp_path) {
std::vector<FilePath> no_key_files;
- return AddDeleteTreeWorkItem(root_path, no_key_files);
+ return AddDeleteTreeWorkItem(root_path, temp_path, no_key_files);
}
WorkItem* WorkItemList::AddMoveTreeWorkItem(const std::wstring& source_path,
diff --git a/chrome/installer/util/work_item_list.h b/chrome/installer/util/work_item_list.h
index 23af15b..fc826ed 100644
--- a/chrome/installer/util/work_item_list.h
+++ b/chrome/installer/util/work_item_list.h
@@ -69,10 +69,12 @@ class WorkItemList : public WorkItem {
// by key_path.
virtual WorkItem* AddDeleteTreeWorkItem(
const FilePath& root_path,
+ const FilePath& temp_path,
const std::vector<FilePath>& key_paths);
// Same as above but without support for key files.
- virtual WorkItem* AddDeleteTreeWorkItem(const FilePath& root_path);
+ virtual WorkItem* AddDeleteTreeWorkItem(const FilePath& root_path,
+ const FilePath& temp_path);
// Add a MoveTreeWorkItem to the list of work items.
virtual WorkItem* AddMoveTreeWorkItem(const std::wstring& source_path,