summaryrefslogtreecommitdiff
path: root/chrome/installer
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-09-26 13:24:57 +0100
committerTorne (Richard Coles) <torne@google.com>2013-09-26 13:24:57 +0100
commit68043e1e95eeb07d5cae7aca370b26518b0867d6 (patch)
treecc6a216bce6aa9319a216327b73a07f49200dab5 /chrome/installer
parentcede44592cfb9ec370925d10c2df733349a94a82 (diff)
downloadchromium_org-68043e1e95eeb07d5cae7aca370b26518b0867d6.tar.gz
Merge from Chromium at DEPS revision 225410
This commit was generated by merge_to_master.py. Change-Id: Ifa1539ca216abb163295ee7a77f81bb67f52e178
Diffstat (limited to 'chrome/installer')
-rw-r--r--chrome/installer/gcapi_mac/gcapi.mm7
-rwxr-xr-xchrome/installer/linux/debian/build.sh10
-rw-r--r--chrome/installer/setup/cf_migration.cc131
-rw-r--r--chrome/installer/setup/cf_migration.h45
-rw-r--r--chrome/installer/setup/install.cc10
-rw-r--r--chrome/installer/setup/setup_main.cc189
-rw-r--r--chrome/installer/setup/setup_main.h23
-rw-r--r--chrome/installer/setup/uninstall.cc12
-rw-r--r--chrome/installer/util/channel_info.cc13
-rw-r--r--chrome/installer/util/channel_info.h7
-rw-r--r--chrome/installer/util/channel_info_unittest.cc34
-rw-r--r--chrome/installer/util/delete_after_reboot_helper.cc91
-rw-r--r--chrome/installer/util/delete_after_reboot_helper.h22
-rw-r--r--chrome/installer/util/delete_after_reboot_helper_unittest.cc41
-rw-r--r--chrome/installer/util/self_cleaning_temp_dir.cc4
-rw-r--r--chrome/installer/util/shell_util.cc7
16 files changed, 439 insertions, 207 deletions
diff --git a/chrome/installer/gcapi_mac/gcapi.mm b/chrome/installer/gcapi_mac/gcapi.mm
index 57f0d02d58..1ca5839300 100644
--- a/chrome/installer/gcapi_mac/gcapi.mm
+++ b/chrome/installer/gcapi_mac/gcapi.mm
@@ -34,9 +34,6 @@ NSString* const kUserMasterPrefsPath =
@"~~/Library/Application Support/Google/Chrome/"
"Google Chrome Master Preferences";
-NSString* const kChannelKey = @"KSChannelID";
-NSString* const kVersionKey = @"KSVersion";
-
// Condensed from chromium's base/mac/mac_util.mm.
bool IsOSXVersionSupported() {
// On 10.6, Gestalt() was observed to be able to spawn threads (see
@@ -60,8 +57,8 @@ bool IsOSXVersionSupported() {
// 10.2.
int mac_os_x_minor_version = darwin_major_version - 4;
- // Chrome is known to work on 10.6 - 10.8.
- return mac_os_x_minor_version >= 6 && mac_os_x_minor_version <= 8;
+ // Chrome is known to work on 10.6 - 10.9.
+ return mac_os_x_minor_version >= 6 && mac_os_x_minor_version <= 9;
}
// Returns the pid/gid of the logged-in user, even if getuid() claims that the
diff --git a/chrome/installer/linux/debian/build.sh b/chrome/installer/linux/debian/build.sh
index 290aaef053..dad1f03ab8 100755
--- a/chrome/installer/linux/debian/build.sh
+++ b/chrome/installer/linux/debian/build.sh
@@ -94,9 +94,13 @@ do_package() {
echo "Packaging ${ARCHITECTURE}..."
PREDEPENDS="$COMMON_PREDEPS"
DEPENDS="${COMMON_DEPS}"
- REPLACES=""
- CONFLICTS=""
- PROVIDES="www-browser"
+ # Trunk is a special package, mostly for development testing, so don't make
+ # it replace any installed release packages.
+ if [ "$CHANNEL" != "trunk" ] && [ "$CHANNEL" != "asan" ]; then
+ REPLACES="${PACKAGE}"
+ CONFLICTS="${PACKAGE}"
+ PROVIDES="${PACKAGE}, www-browser"
+ fi
gen_changelog
process_template "${SCRIPTDIR}/control.template" "${DEB_CONTROL}"
export DEB_HOST_ARCH="${ARCHITECTURE}"
diff --git a/chrome/installer/setup/cf_migration.cc b/chrome/installer/setup/cf_migration.cc
new file mode 100644
index 0000000000..313f2ce317
--- /dev/null
+++ b/chrome/installer/setup/cf_migration.cc
@@ -0,0 +1,131 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/installer/setup/cf_migration.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/process/launch.h"
+#include "base/win/registry.h"
+#include "chrome/installer/setup/setup_constants.h"
+#include "chrome/installer/setup/setup_main.h"
+#include "chrome/installer/setup/setup_util.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/installation_state.h"
+#include "chrome/installer/util/installer_state.h"
+#include "chrome/installer/util/master_preferences.h"
+#include "chrome/installer/util/util_constants.h"
+
+namespace installer {
+
+bool LaunchChromeFrameMigrationProcess(
+ const ProductState& chrome_frame_product,
+ const CommandLine& command_line,
+ const base::FilePath& installer_directory,
+ bool system_level) {
+ // Before running the migration, mutate the CF ap value to include a
+ // "-migrate" beacon. This beacon value will be cleaned up by the "ap"
+ // cleanup in MigrateGoogleUpdateStateMultiToSingle that calls
+ // ChannelInfo::RemoveAllModifiersAndSuffixes().
+ if (chrome_frame_product.is_multi_install()) {
+ const HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
+ base::win::RegKey state_key;
+ installer::ChannelInfo channel_info;
+ BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_FRAME);
+
+ LONG result = state_key.Open(root, dist->GetStateKey().c_str(),
+ KEY_QUERY_VALUE | KEY_SET_VALUE);
+ if (result != ERROR_SUCCESS || !channel_info.Initialize(state_key)) {
+ LOG(ERROR) << "Failed to read CF channel to store beacon.";
+ } else if (!channel_info.SetMigratingSuffix(true)) {
+ LOG(WARNING) << "CF already has migration beacon in channel.";
+ } else {
+ VLOG(1) << "Writing CF migration beacon to channel: "
+ << channel_info.value();
+ channel_info.Write(&state_key);
+ }
+ }
+
+ // Call the installed setup.exe using the current installer command line and
+ // adding the migration flags. This seems like it could be unsafe, here's why
+ // it's safe today:
+ // 1) MigrateChromeFrameInChildProcess is called only during a multi update.
+ // 2) Multi update processing occurs after HandleNonInstallCmdLineOptions is
+ // called.
+ // 3) Setup exits if there were any non-install command line options handled.
+ // 4) Thus, the command line being copied will have no non-install command
+ // line options at time of copying.
+ // 5) kMigrateChromeFrame is a non-install command line option.
+ // 6) Thus, it will be handled (and the child setup process will exit) before
+ // the child setup process acts on any other flags on the command line.
+ // 7) Furthermore, --uncompressed-archive takes precedence over
+ // --install-archive, so it is safe to add the former to the command line
+ // without removing the latter.
+ CommandLine setup_cmd(command_line);
+ setup_cmd.SetProgram(installer_directory.Append(installer::kSetupExe));
+ setup_cmd.AppendSwitchPath(
+ switches::kUncompressedArchive,
+ installer_directory.Append(installer::kChromeArchive));
+ setup_cmd.AppendSwitch(switches::kMigrateChromeFrame);
+
+ VLOG(1) << "Running Chrome Frame migration process with command line: "
+ << setup_cmd.GetCommandLineString();
+
+ base::LaunchOptions options;
+ options.force_breakaway_from_job_ = true;
+ if (!base::LaunchProcess(setup_cmd, options, NULL)) {
+ PLOG(ERROR) << "Launching Chrome Frame migration process failed. "
+ << "(Command line: " << setup_cmd.GetCommandLineString() << ")";
+ return false;
+ }
+
+ return true;
+}
+
+InstallStatus MigrateChromeFrame(const InstallationState& original_state,
+ InstallerState* installer_state) {
+ const bool system_level = installer_state->system_install();
+
+ // Nothing to do if multi-install Chrome Frame is not installed.
+ const ProductState* multi_chrome_frame = original_state.GetProductState(
+ system_level, BrowserDistribution::CHROME_FRAME);
+ if (!multi_chrome_frame || !multi_chrome_frame->is_multi_install())
+ return INVALID_STATE_FOR_OPTION;
+
+ // Install SxS Chrome Frame.
+ InstallerState install_gcf(installer_state->level());
+ {
+ scoped_ptr<Product> chrome_frame(
+ new Product(BrowserDistribution::GetSpecificDistribution(
+ BrowserDistribution::CHROME_FRAME)));
+ install_gcf.AddProduct(&chrome_frame);
+ }
+ DCHECK(!install_gcf.is_multi_install());
+
+ ArchiveType archive_type = UNKNOWN_ARCHIVE_TYPE;
+ bool delegated_to_existing = false;
+ InstallStatus install_status = InstallProductsHelper(
+ original_state, *CommandLine::ForCurrentProcess(),
+ MasterPreferences::ForCurrentProcess(), install_gcf,
+ NULL, &archive_type, &delegated_to_existing);
+
+ if (!InstallUtil::GetInstallReturnCode(install_status)) {
+ // Migration was successful. There's no turning back now. The multi-install
+ // npchrome_frame.dll and/or chrome.exe may still be in use at this point,
+ // although the user-level helper will not be. It is not safe to delete the
+ // multi-install binaries until npchrome_frame.dll and chrome.exe are no
+ // longer in use. The remaining tasks here are best-effort. Failure does not
+ // do any harm.
+ MigrateGoogleUpdateStateMultiToSingle(system_level,
+ BrowserDistribution::CHROME_FRAME,
+ original_state);
+ }
+
+ return install_status;
+}
+
+} // namespace installer
diff --git a/chrome/installer/setup/cf_migration.h b/chrome/installer/setup/cf_migration.h
new file mode 100644
index 0000000000..976e54464a
--- /dev/null
+++ b/chrome/installer/setup/cf_migration.h
@@ -0,0 +1,45 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_INSTALLER_SETUP_CF_MIGRATION_H_
+#define CHROME_INSTALLER_SETUP_CF_MIGRATION_H_
+
+#include "chrome/installer/util/util_constants.h"
+
+class CommandLine;
+
+namespace base {
+class FilePath;
+}
+
+namespace installer {
+
+class InstallationState;
+class InstallerState;
+class ProductState;
+
+// Invokes a child helper instance of the setup.exe in |installer_directory| to
+// run MigrateChromeFrame (see comments below) using the archive in
+// |installer_directory| for the given installation level. Returns true if the
+// process is launched.
+bool LaunchChromeFrameMigrationProcess(
+ const ProductState& chrome_frame_product,
+ const CommandLine& command_line,
+ const base::FilePath& installer_directory,
+ bool system_level);
+
+// Migrates multi-install Chrome Frame to single-install at the current
+// level. Does not remove the multi-install binaries if no other products are
+// using them. --uncompressed-archive=chrome.7z is expected to be given on the
+// command line to point this setup.exe at the (possibly patched) archive from
+// the calling instance.
+// Note about process model: this is called in a child setup.exe that is
+// invoked from the setup.exe instance run as part of an update to a
+// multi-install Chrome Frame.
+InstallStatus MigrateChromeFrame(const InstallationState& original_state,
+ InstallerState* installer_state);
+
+} // namespace installer
+
+#endif // CHROME_INSTALLER_SETUP_CF_MIGRATION_H_
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index 688df1c786..5049fdca81 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -17,6 +17,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/process/launch.h"
+#include "base/safe_numerics.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -340,9 +341,10 @@ bool CreateVisualElementsManifest(const base::FilePath& src_path,
// Write the manifest to |src_path|.
const std::string manifest(UTF16ToUTF8(manifest16));
+ int size = base::checked_numeric_cast<int>(manifest.size());
if (file_util::WriteFile(
- src_path.Append(installer::kVisualElementsManifest),
- manifest.c_str(), manifest.size())) {
+ src_path.Append(installer::kVisualElementsManifest),
+ manifest.c_str(), size) == size) {
VLOG(1) << "Successfully wrote " << installer::kVisualElementsManifest
<< " to " << src_path.value();
return true;
@@ -504,10 +506,8 @@ InstallStatus InstallOrUpdateProduct(
DCHECK(products.size());
if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
// Make sure that we don't end up deleting installed files on next reboot.
- if (!RemoveFromMovesPendingReboot(
- installer_state.target_path().value().c_str())) {
+ if (!RemoveFromMovesPendingReboot(installer_state.target_path()))
LOG(ERROR) << "Error accessing pending moves value.";
- }
}
// Create VisualElementManifest.xml in |src_path| (if required) so that it
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 171ac7c7c4..9f38cfff19 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -36,6 +36,7 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/installer/setup/archive_patch_helper.h"
+#include "chrome/installer/setup/cf_migration.h"
#include "chrome/installer/setup/chrome_frame_quick_enable.h"
#include "chrome/installer/setup/chrome_frame_ready_mode.h"
#include "chrome/installer/setup/install.h"
@@ -71,10 +72,10 @@
using installer::InstallerState;
using installer::InstallationState;
using installer::InstallationValidator;
+using installer::MasterPreferences;
using installer::Product;
using installer::ProductState;
using installer::Products;
-using installer::MasterPreferences;
const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices";
const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\";
@@ -691,7 +692,8 @@ installer::InstallStatus InstallProducts(
const InstallationState& original_state,
const CommandLine& cmd_line,
const MasterPreferences& prefs,
- InstallerState* installer_state) {
+ InstallerState* installer_state,
+ base::FilePath* installer_directory) {
DCHECK(installer_state);
const bool system_install = installer_state->system_install();
installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
@@ -706,8 +708,8 @@ installer::InstallStatus InstallProducts(
&install_status)) {
VLOG(1) << "Installing to " << installer_state->target_path().value();
install_status = InstallProductsHelper(
- original_state, cmd_line, prefs, *installer_state, &archive_type,
- &delegated_to_existing);
+ original_state, cmd_line, prefs, *installer_state,
+ installer_directory, &archive_type, &delegated_to_existing);
} else {
// CheckPreInstallConditions must set the status on failure.
DCHECK_NE(install_status, installer::UNKNOWN_STATUS);
@@ -723,7 +725,7 @@ installer::InstallStatus InstallProducts(
LOG(ERROR) << "Failed deleting master preferences file "
<< prefs_path.value()
<< ", scheduling for deletion after reboot.";
- ScheduleFileSystemEntityForDeletion(prefs_path.value().c_str());
+ ScheduleFileSystemEntityForDeletion(prefs_path);
}
}
@@ -981,55 +983,6 @@ installer::InstallStatus RegisterDevChrome(
return status;
}
-// Migrates multi-install Chrome Frame to single-install at the current
-// level. Does not remove the multi-install binaries if no other products are
-// using them. --uncompressed-archive=chrome.7z is expected to be given on the
-// command line to point this setup.exe at the (possibly patched) archive from
-// the calling instance.
-installer::InstallStatus MigrateChromeFrame(
- const InstallationState& original_state,
- InstallerState* installer_state) {
- const bool system_level = installer_state->system_install();
-
- // Nothing to do if multi-install Chrome Frame is not installed.
- const ProductState* multi_chrome_frame = original_state.GetProductState(
- system_level, BrowserDistribution::CHROME_FRAME);
- if (!multi_chrome_frame || !multi_chrome_frame->is_multi_install())
- return installer::INVALID_STATE_FOR_OPTION;
-
- // Install SxS Chrome Frame.
- InstallerState install_gcf(installer_state->level());
- {
- scoped_ptr<Product> chrome_frame(
- new Product(BrowserDistribution::GetSpecificDistribution(
- BrowserDistribution::CHROME_FRAME)));
- install_gcf.AddProduct(&chrome_frame);
- }
- DCHECK(!install_gcf.is_multi_install());
-
- installer::ArchiveType archive_type = installer::UNKNOWN_ARCHIVE_TYPE;
- bool delegated_to_existing = false;
- installer::InstallStatus install_status = InstallProductsHelper(
- original_state, *CommandLine::ForCurrentProcess(),
- MasterPreferences::ForCurrentProcess(), install_gcf,
- &archive_type, &delegated_to_existing);
-
- if (!InstallUtil::GetInstallReturnCode(install_status)) {
- // Migration was successful. There's no turning back now. The multi-install
- // npchrome_frame.dll and/or chrome.exe may still be in use at this point,
- // although the user-level helper will not be. It is not safe to delete the
- // multi-install binaries until npchrome_frame.dll and chrome.exe are no
- // longer in use. The remaining tasks here are best-effort. Failure does not
- // do any harm.
- installer::MigrateGoogleUpdateStateMultiToSingle(
- system_level,
- BrowserDistribution::CHROME_FRAME,
- original_state);
- }
-
- return install_status;
-}
-
// This method processes any command line options that make setup.exe do
// various tasks other than installation (renaming chrome.exe, showing eula
// among others). This function returns true if any such command line option
@@ -1070,7 +1023,7 @@ bool HandleNonInstallCmdLineOptions(const InstallationState& original_state,
// the Windows last-error code.
LOG(WARNING) << "Scheduling temporary path " << temp_path.path().value()
<< " for deletion at reboot.";
- ScheduleDirectoryForDeletion(temp_path.path().value().c_str());
+ ScheduleDirectoryForDeletion(temp_path.path());
}
}
@@ -1401,42 +1354,43 @@ google_breakpad::ExceptionHandler* InitializeCrashReporting(
namespace installer {
-installer::InstallStatus InstallProductsHelper(
+InstallStatus InstallProductsHelper(
const InstallationState& original_state,
const CommandLine& cmd_line,
const MasterPreferences& prefs,
const InstallerState& installer_state,
- installer::ArchiveType* archive_type,
+ base::FilePath* installer_directory,
+ ArchiveType* archive_type,
bool* delegated_to_existing) {
DCHECK(archive_type);
DCHECK(delegated_to_existing);
const bool system_install = installer_state.system_install();
- installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
+ InstallStatus install_status = UNKNOWN_STATUS;
// Drop to background processing mode if the process was started below the
// normal process priority class.
- bool entered_background_mode = installer::AdjustProcessPriority();
+ bool entered_background_mode = AdjustProcessPriority();
VLOG_IF(1, entered_background_mode) << "Entered background processing mode.";
// 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.
- installer::SelfCleaningTempDir temp_path;
+ SelfCleaningTempDir temp_path;
base::FilePath unpack_path;
if (!CreateTemporaryAndUnpackDirectories(installer_state, &temp_path,
&unpack_path)) {
- installer_state.WriteInstallerResult(installer::TEMP_DIR_FAILED,
+ installer_state.WriteInstallerResult(TEMP_DIR_FAILED,
IDS_INSTALL_TEMP_DIR_FAILED_BASE,
NULL);
- return installer::TEMP_DIR_FAILED;
+ return TEMP_DIR_FAILED;
}
// Uncompress and optionally patch the archive if an uncompressed archive was
// not specified on the command line and a compressed archive is found.
- *archive_type = installer::UNKNOWN_ARCHIVE_TYPE;
+ *archive_type = UNKNOWN_ARCHIVE_TYPE;
base::FilePath uncompressed_archive(cmd_line.GetSwitchValuePath(
- installer::switches::kUncompressedArchive));
+ switches::kUncompressedArchive));
if (uncompressed_archive.empty()) {
- scoped_ptr<installer::ArchivePatchHelper> archive_helper(
+ scoped_ptr<ArchivePatchHelper> archive_helper(
CreateChromeArchiveHelper(cmd_line, installer_state, unpack_path));
if (archive_helper) {
VLOG(1) << "Installing Chrome from compressed archive "
@@ -1446,7 +1400,7 @@ installer::InstallStatus InstallProductsHelper(
archive_helper.get(),
archive_type,
&install_status)) {
- DCHECK_NE(install_status, installer::UNKNOWN_STATUS);
+ DCHECK_NE(install_status, UNKNOWN_STATUS);
return install_status;
}
uncompressed_archive = archive_helper->target();
@@ -1458,19 +1412,19 @@ installer::InstallStatus InstallProductsHelper(
// was not given or generated.
if (uncompressed_archive.empty()) {
uncompressed_archive =
- cmd_line.GetProgram().DirName().Append(installer::kChromeArchive);
+ cmd_line.GetProgram().DirName().Append(kChromeArchive);
}
- if (*archive_type == installer::UNKNOWN_ARCHIVE_TYPE) {
+ if (*archive_type == UNKNOWN_ARCHIVE_TYPE) {
// An archive was not uncompressed or patched above.
if (uncompressed_archive.empty() ||
!base::PathExists(uncompressed_archive)) {
LOG(ERROR) << "Cannot install Chrome without an uncompressed archive.";
installer_state.WriteInstallerResult(
- installer::INVALID_ARCHIVE, IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
- return installer::INVALID_ARCHIVE;
+ INVALID_ARCHIVE, IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
+ return INVALID_ARCHIVE;
}
- *archive_type = installer::FULL_ARCHIVE_TYPE;
+ *archive_type = FULL_ARCHIVE_TYPE;
}
// Unpack the uncompressed archive.
@@ -1478,20 +1432,20 @@ installer::InstallStatus InstallProductsHelper(
unpack_path.value(),
NULL)) {
installer_state.WriteInstallerResult(
- installer::UNCOMPRESSION_FAILED,
+ UNCOMPRESSION_FAILED,
IDS_INSTALL_UNCOMPRESSION_FAILED_BASE,
NULL);
- return installer::UNCOMPRESSION_FAILED;
+ return UNCOMPRESSION_FAILED;
}
VLOG(1) << "unpacked to " << unpack_path.value();
base::FilePath src_path(
- unpack_path.Append(installer::kInstallSourceChromeDir));
+ unpack_path.Append(kInstallSourceChromeDir));
scoped_ptr<Version>
- installer_version(installer::GetMaxVersionFromArchiveDir(src_path));
+ installer_version(GetMaxVersionFromArchiveDir(src_path));
if (!installer_version.get()) {
LOG(ERROR) << "Did not find any valid version in installer.";
- install_status = installer::INVALID_ARCHIVE;
+ install_status = INVALID_ARCHIVE;
installer_state.WriteInstallerResult(install_status,
IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
} else {
@@ -1508,7 +1462,7 @@ installer::InstallStatus InstallProductsHelper(
if (GetExistingHigherInstaller(original_state, system_install,
*installer_version, &setup_exe)) {
VLOG(1) << "Deferring to existing installer.";
- installer_state.UpdateStage(installer::DEFERRING_TO_HIGHER_VERSION);
+ installer_state.UpdateStage(DEFERRING_TO_HIGHER_VERSION);
if (DeferToExistingInstall(setup_exe, cmd_line, installer_state,
temp_path.path(), &install_status)) {
*delegated_to_existing = true;
@@ -1546,7 +1500,7 @@ installer::InstallStatus InstallProductsHelper(
int message_id = 0;
proceed_with_installation = false;
- install_status = installer::HIGHER_VERSION_EXISTS;
+ install_status = HIGHER_VERSION_EXISTS;
switch (higher_products) {
case kBrowserBit:
message_id = IDS_INSTALL_HIGHER_VERSION_BASE;
@@ -1579,16 +1533,17 @@ installer::InstallStatus InstallProductsHelper(
if (!google_update::EnsureUserLevelGoogleUpdatePresent()) {
LOG(ERROR) << "Failed to install Google Update";
proceed_with_installation = false;
- install_status = installer::INSTALL_OF_GOOGLE_UPDATE_FAILED;
+ install_status = INSTALL_OF_GOOGLE_UPDATE_FAILED;
installer_state.WriteInstallerResult(install_status, 0, NULL);
}
}
+
}
if (proceed_with_installation) {
base::FilePath prefs_source_path(cmd_line.GetSwitchValueNative(
- installer::switches::kInstallerData));
- install_status = installer::InstallOrUpdateProduct(
+ switches::kInstallerData));
+ install_status = InstallOrUpdateProduct(
original_state, installer_state, cmd_line.GetProgram(),
uncompressed_archive, temp_path.path(), src_path, prefs_source_path,
prefs, *installer_version);
@@ -1596,27 +1551,26 @@ installer::InstallStatus InstallProductsHelper(
int install_msg_base = IDS_INSTALL_FAILED_BASE;
string16 chrome_exe;
string16 quoted_chrome_exe;
- if (install_status == installer::SAME_VERSION_REPAIR_FAILED) {
+ if (install_status == SAME_VERSION_REPAIR_FAILED) {
if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE;
} else {
install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE;
}
- } else if (install_status != installer::INSTALL_FAILED) {
+ } else if (install_status != INSTALL_FAILED) {
if (installer_state.target_path().empty()) {
// If we failed to construct install path, it means the OS call to
// get %ProgramFiles% or %AppData% failed. Report this as failure.
install_msg_base = IDS_INSTALL_OS_ERROR_BASE;
- install_status = installer::OS_ERROR;
+ install_status = OS_ERROR;
} else {
- chrome_exe = installer_state.target_path()
- .Append(installer::kChromeExe).value();
+ chrome_exe = installer_state.target_path().Append(kChromeExe).value();
quoted_chrome_exe = L"\"" + chrome_exe + L"\"";
install_msg_base = 0;
}
}
- installer_state.UpdateStage(installer::FINISHING);
+ installer_state.UpdateStage(FINISHING);
// Only do Chrome-specific stuff (like launching the browser) if
// Chrome was specifically requested (rather than being upgraded as
@@ -1627,48 +1581,45 @@ installer::InstallStatus InstallProductsHelper(
bool do_not_register_for_update_launch = false;
if (chrome_install) {
- prefs.GetBool(
- installer::master_preferences::kDoNotRegisterForUpdateLaunch,
- &do_not_register_for_update_launch);
+ prefs.GetBool(master_preferences::kDoNotRegisterForUpdateLaunch,
+ &do_not_register_for_update_launch);
} else {
do_not_register_for_update_launch = true; // Never register.
}
bool write_chrome_launch_string =
(!do_not_register_for_update_launch &&
- install_status != installer::IN_USE_UPDATED);
+ install_status != IN_USE_UPDATED);
installer_state.WriteInstallerResult(install_status, install_msg_base,
write_chrome_launch_string ? &quoted_chrome_exe : NULL);
- if (install_status == installer::FIRST_INSTALL_SUCCESS) {
+ if (install_status == FIRST_INSTALL_SUCCESS) {
VLOG(1) << "First install successful.";
if (chrome_install) {
// We never want to launch Chrome in system level install mode.
bool do_not_launch_chrome = false;
- prefs.GetBool(
- installer::master_preferences::kDoNotLaunchChrome,
- &do_not_launch_chrome);
+ prefs.GetBool(master_preferences::kDoNotLaunchChrome,
+ &do_not_launch_chrome);
if (!system_install && !do_not_launch_chrome)
chrome_install->LaunchChrome(installer_state.target_path());
}
- } else if ((install_status == installer::NEW_VERSION_UPDATED) ||
- (install_status == installer::IN_USE_UPDATED)) {
+ } else if ((install_status == NEW_VERSION_UPDATED) ||
+ (install_status == IN_USE_UPDATED)) {
const Product* chrome = installer_state.FindProduct(
BrowserDistribution::CHROME_BROWSER);
if (chrome != NULL) {
DCHECK_NE(chrome_exe, string16());
- installer::RemoveChromeLegacyRegistryKeys(chrome->distribution(),
- chrome_exe);
+ RemoveChromeLegacyRegistryKeys(chrome->distribution(), chrome_exe);
}
}
if (prefs.install_chrome_app_launcher() &&
InstallUtil::GetInstallReturnCode(install_status) == 0) {
std::string webstore_item(google_update::GetUntrustedDataValue(
- installer::kInstallFromWebstore));
+ kInstallFromWebstore));
if (!webstore_item.empty()) {
- bool success = installer::InstallFromWebstore(webstore_item);
+ bool success = InstallFromWebstore(webstore_item);
VLOG_IF(1, !success) << "Failed to launch app installation.";
}
}
@@ -1699,6 +1650,15 @@ installer::InstallStatus InstallProductsHelper(
}
}
+ // If installation completed successfully, return the path to the directory
+ // containing the newly installed setup.exe and uncompressed archive if the
+ // caller requested it.
+ if (installer_directory &&
+ InstallUtil::GetInstallReturnCode(install_status) == 0) {
+ *installer_directory =
+ installer_state.GetInstallerDirectory(*installer_version);
+ }
+
// temp_path's dtor will take care of deleting or scheduling itself for
// deletion at reboot when this scope closes.
VLOG(1) << "Deleting temporary directory " << temp_path.path().value();
@@ -1798,6 +1758,7 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
}
}
+ base::FilePath installer_directory;
installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
// If --uninstall option is given, uninstall the identified product(s)
if (is_uninstall) {
@@ -1806,7 +1767,8 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
} else {
// If --uninstall option is not specified, we assume it is install case.
install_status =
- InstallProducts(original_state, cmd_line, prefs, &installer_state);
+ InstallProducts(original_state, cmd_line, prefs, &installer_state,
+ &installer_directory);
}
// Validate that the machine is now in a good state following the operation.
@@ -1820,7 +1782,6 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
const Product* cf_install =
installer_state.FindProduct(BrowserDistribution::CHROME_FRAME);
-
if (cf_install &&
!cmd_line.HasSwitch(installer::switches::kForceUninstall)) {
if (install_status == installer::UNINSTALL_REQUIRES_REBOOT) {
@@ -1849,11 +1810,31 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
// MSI demands that custom actions always return 0 (ERROR_SUCCESS) or it will
// rollback the action. If we're uninstalling we want to avoid this, so always
// report success, squashing any more informative return codes.
- if (!(installer_state.is_msi() && is_uninstall))
+ if (!(installer_state.is_msi() && is_uninstall)) {
// Note that we allow the status installer::UNINSTALL_REQUIRES_REBOOT
// to pass through, since this is only returned on uninstall which is
// never invoked directly by Google Update.
return_code = InstallUtil::GetInstallReturnCode(install_status);
+ }
+
+ // Reinitialize original_state to make sure it reflects the now-current
+ // state of the system.
+ original_state.Initialize();
+
+ // If multi Chrome Frame was just updated, migrate the installation to a SxS
+ // install. Do this right before quitting.
+ const ProductState* chrome_frame_state =
+ original_state.GetProductState(system_install,
+ BrowserDistribution::CHROME_FRAME);
+ if ((install_status == installer::NEW_VERSION_UPDATED ||
+ install_status == installer::IN_USE_UPDATED) &&
+ chrome_frame_state &&
+ installer_state.operation() == InstallerState::MULTI_UPDATE) {
+ // Call the newly updated setup.exe with kUncompressedArchive and
+ // kMigrateChromeFrame to perform the migration.
+ LaunchChromeFrameMigrationProcess(*chrome_frame_state, cmd_line,
+ installer_directory, system_install);
+ }
VLOG(1) << "Installation complete, returning: " << return_code;
diff --git a/chrome/installer/setup/setup_main.h b/chrome/installer/setup/setup_main.h
index f39e742de0..f87509cf68 100644
--- a/chrome/installer/setup/setup_main.h
+++ b/chrome/installer/setup/setup_main.h
@@ -12,20 +12,27 @@
class CommandLine;
-namespace installer {
+namespace base {
+class FilePath;
+} // namespace base
+namespace installer {
class InstallationState;
class InstallerState;
class MasterPreferences;
// Helper function that performs the installation of a set of products.
-installer::InstallStatus InstallProductsHelper(
- const installer::InstallationState& original_state,
- const CommandLine& cmd_line,
- const installer::MasterPreferences& prefs,
- const installer::InstallerState& installer_state,
- installer::ArchiveType* archive_type,
- bool* delegated_to_existing);
+// |installer_directory|, if non-NULL, is populated with the path to the
+// directory containing the newly installed setup.exe. |archive_type| is
+// populated with the type of archive found. |delegated_to_existing| is set to
+// |true| if installation was delegated to a pre-existing higher version.
+InstallStatus InstallProductsHelper(const InstallationState& original_state,
+ const CommandLine& cmd_line,
+ const MasterPreferences& prefs,
+ const InstallerState& installer_state,
+ base::FilePath* installer_directory,
+ ArchiveType* archive_type,
+ bool* delegated_to_existing);
} // namespace installer
diff --git a/chrome/installer/setup/uninstall.cc b/chrome/installer/setup/uninstall.cc
index 2387ab319b..ad0b0d25e3 100644
--- a/chrome/installer/setup/uninstall.cc
+++ b/chrome/installer/setup/uninstall.cc
@@ -428,13 +428,13 @@ void DeleteShortcuts(const InstallerState& installer_state,
bool ScheduleParentAndGrandparentForDeletion(const base::FilePath& path) {
base::FilePath parent_dir = path.DirName();
- bool ret = ScheduleFileSystemEntityForDeletion(parent_dir.value().c_str());
+ bool ret = ScheduleFileSystemEntityForDeletion(parent_dir);
if (!ret) {
LOG(ERROR) << "Failed to schedule parent dir for deletion: "
<< parent_dir.value();
} else {
base::FilePath grandparent_dir(parent_dir.DirName());
- ret = ScheduleFileSystemEntityForDeletion(grandparent_dir.value().c_str());
+ ret = ScheduleFileSystemEntityForDeletion(grandparent_dir);
if (!ret) {
LOG(ERROR) << "Failed to schedule grandparent dir for deletion: "
<< grandparent_dir.value();
@@ -508,7 +508,7 @@ DeleteResult DeleteLocalState(
LOG(ERROR) << "Failed to delete user profile dir: "
<< user_local_state.value();
if (schedule_on_failure) {
- ScheduleDirectoryForDeletion(user_local_state.value().c_str());
+ ScheduleDirectoryForDeletion(user_local_state);
result = DELETE_REQUIRES_REBOOT;
} else {
result = DELETE_FAILED;
@@ -652,9 +652,9 @@ DeleteResult DeleteChromeFilesAndFolders(const InstallerState& installer_state,
// return a value that will trigger a reboot prompt.
base::FileEnumerator::FileInfo find_info = file_enumerator.GetInfo();
if (find_info.IsDirectory())
- ScheduleDirectoryForDeletion(to_delete.value().c_str());
+ ScheduleDirectoryForDeletion(to_delete);
else
- ScheduleFileSystemEntityForDeletion(to_delete.value().c_str());
+ ScheduleFileSystemEntityForDeletion(to_delete);
result = DELETE_REQUIRES_REBOOT;
} else {
// Try closing any running Chrome processes and deleting files once
@@ -1496,7 +1496,7 @@ void CleanUpInstallationDirectoryAfterUninstall(
if (*uninstall_status == installer::UNINSTALL_REQUIRES_REBOOT) {
// Delete the Application directory at reboot if empty.
- ScheduleFileSystemEntityForDeletion(target_path.value().c_str());
+ ScheduleFileSystemEntityForDeletion(target_path);
// If we need a reboot to continue, schedule the parent directories for
// deletion unconditionally. If they are not empty, the session manager
diff --git a/chrome/installer/util/channel_info.cc b/chrome/installer/util/channel_info.cc
index e52ae77afe..48a4e32127 100644
--- a/chrome/installer/util/channel_info.cc
+++ b/chrome/installer/util/channel_info.cc
@@ -22,6 +22,7 @@ const wchar_t kModMultiInstall[] = L"-multi";
const wchar_t kModReadyMode[] = L"-readymode";
const wchar_t kModStage[] = L"-stage:";
const wchar_t kSfxFull[] = L"-full";
+const wchar_t kSfxMigrating[] = L"-migrating";
const wchar_t kSfxMultiFail[] = L"-multifail";
const wchar_t* const kChannels[] = {
@@ -38,7 +39,8 @@ const wchar_t* const kModifiers[] = {
kModAppLauncher,
kModReadyMode,
kSfxMultiFail,
- kSfxFull
+ kSfxMigrating,
+ kSfxFull,
};
enum ModifierIndex {
@@ -50,6 +52,7 @@ enum ModifierIndex {
MOD_APP_LAUNCHER,
MOD_READY_MODE,
SFX_MULTI_FAIL,
+ SFX_MIGRATING,
SFX_FULL,
NUM_MODIFIERS
};
@@ -281,6 +284,14 @@ bool ChannelInfo::SetMultiFailSuffix(bool value) {
return SetModifier(SFX_MULTI_FAIL, value, &value_);
}
+bool ChannelInfo::SetMigratingSuffix(bool value) {
+ return SetModifier(SFX_MIGRATING, value, &value_);
+}
+
+bool ChannelInfo::HasMigratingSuffix() const {
+ return HasModifier(SFX_MIGRATING, value_);
+}
+
bool ChannelInfo::RemoveAllModifiersAndSuffixes() {
bool modified = false;
diff --git a/chrome/installer/util/channel_info.h b/chrome/installer/util/channel_info.h
index 438966f247..f14811390a 100644
--- a/chrome/installer/util/channel_info.h
+++ b/chrome/installer/util/channel_info.h
@@ -101,6 +101,13 @@ class ChannelInfo {
// modified.
bool SetMultiFailSuffix(bool value);
+ // Adds or removes the -migrating suffix, returning true if the value is
+ // modified.
+ bool SetMigratingSuffix(bool value);
+
+ // Returns true if the -migrating suffix is present in the value.
+ bool HasMigratingSuffix() const;
+
// Removes all modifiers and suffixes. For example, 2.0-dev-multi-chrome-full
// becomes 2.0-dev. Returns true if the value is modified.
bool RemoveAllModifiersAndSuffixes();
diff --git a/chrome/installer/util/channel_info_unittest.cc b/chrome/installer/util/channel_info_unittest.cc
index 1aacb24730..d08f2c3104 100644
--- a/chrome/installer/util/channel_info_unittest.cc
+++ b/chrome/installer/util/channel_info_unittest.cc
@@ -118,6 +118,38 @@ TEST(ChannelInfoTest, MultiInstall) {
EXPECT_EQ(L"2.0-beta", ci.value());
}
+TEST(ChannelInfoTest, Migration) {
+ ChannelInfo ci;
+
+ ci.set_value(L"");
+ EXPECT_TRUE(ci.SetMigratingSuffix(true));
+ EXPECT_TRUE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"-migrating", ci.value());
+ EXPECT_FALSE(ci.SetMigratingSuffix(true));
+ EXPECT_TRUE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"-migrating", ci.value());
+ EXPECT_TRUE(ci.SetMigratingSuffix(false));
+ EXPECT_FALSE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"", ci.value());
+ EXPECT_FALSE(ci.SetMigratingSuffix(false));
+ EXPECT_FALSE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"", ci.value());
+
+ ci.set_value(L"2.0-beta");
+ EXPECT_TRUE(ci.SetMigratingSuffix(true));
+ EXPECT_TRUE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"2.0-beta-migrating", ci.value());
+ EXPECT_FALSE(ci.SetMigratingSuffix(true));
+ EXPECT_TRUE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"2.0-beta-migrating", ci.value());
+ EXPECT_TRUE(ci.SetMigratingSuffix(false));
+ EXPECT_FALSE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"2.0-beta", ci.value());
+ EXPECT_FALSE(ci.SetMigratingSuffix(false));
+ EXPECT_FALSE(ci.HasMigratingSuffix());
+ EXPECT_EQ(L"2.0-beta", ci.value());
+}
+
TEST(ChannelInfoTest, Combinations) {
ChannelInfo ci;
@@ -212,7 +244,7 @@ TEST(ChannelInfoTest, RemoveAllModifiersAndSuffixes) {
EXPECT_FALSE(ci.RemoveAllModifiersAndSuffixes());
EXPECT_EQ(L"", ci.value());
- ci.set_value(L"2.0-dev-multi-chrome-chromeframe");
+ ci.set_value(L"2.0-dev-multi-chrome-chromeframe-migrating");
EXPECT_TRUE(ci.RemoveAllModifiersAndSuffixes());
EXPECT_EQ(L"2.0-dev", ci.value());
}
diff --git a/chrome/installer/util/delete_after_reboot_helper.cc b/chrome/installer/util/delete_after_reboot_helper.cc
index 5131b1d58b..fb7956ed26 100644
--- a/chrome/installer/util/delete_after_reboot_helper.cc
+++ b/chrome/installer/util/delete_after_reboot_helper.cc
@@ -30,20 +30,19 @@ namespace {
// Returns true if this directory name is 'safe' for deletion (doesn't contain
// "..", doesn't specify a drive root)
-bool IsSafeDirectoryNameForDeletion(const wchar_t* dir_name) {
- DCHECK(dir_name);
-
+bool IsSafeDirectoryNameForDeletion(const base::FilePath& dir_name) {
// empty name isn't allowed
- if (!(dir_name && *dir_name))
+ if (dir_name.empty())
return false;
// require a character other than \/:. after the last :
// disallow anything with ".."
bool ok = false;
- for (const wchar_t* s = dir_name; *s; ++s) {
+ const wchar_t* dir_name_str = dir_name.value().c_str();
+ for (const wchar_t* s = dir_name_str; *s; ++s) {
if (*s != L'\\' && *s != L'/' && *s != L':' && *s != L'.')
ok = true;
- if (*s == L'.' && s > dir_name && *(s - 1) == L'.')
+ if (*s == L'.' && s > dir_name_str && *(s - 1) == L'.')
return false;
if (*s == L':')
ok = false;
@@ -54,22 +53,23 @@ bool IsSafeDirectoryNameForDeletion(const wchar_t* dir_name) {
} // end namespace
// Must only be called for regular files or directories that will be empty.
-bool ScheduleFileSystemEntityForDeletion(const wchar_t* path) {
+bool ScheduleFileSystemEntityForDeletion(const base::FilePath& path) {
// Check if the file exists, return false if not.
WIN32_FILE_ATTRIBUTE_DATA attrs = {0};
- if (!::GetFileAttributesEx(path, ::GetFileExInfoStandard, &attrs)) {
- PLOG(WARNING) << path << " does not exist.";
+ if (!::GetFileAttributesEx(path.value().c_str(),
+ ::GetFileExInfoStandard, &attrs)) {
+ PLOG(WARNING) << path.value() << " does not exist.";
return false;
}
DWORD flags = MOVEFILE_DELAY_UNTIL_REBOOT;
- if (!base::DirectoryExists(base::FilePath::FromWStringHack(path))) {
+ if (!base::DirectoryExists(path)) {
// This flag valid only for files
flags |= MOVEFILE_REPLACE_EXISTING;
}
- if (!::MoveFileEx(path, NULL, flags)) {
- PLOG(ERROR) << "Could not schedule " << path << " for deletion.";
+ if (!::MoveFileEx(path.value().c_str(), NULL, flags)) {
+ PLOG(ERROR) << "Could not schedule " << path.value() << " for deletion.";
return false;
}
@@ -77,51 +77,53 @@ bool ScheduleFileSystemEntityForDeletion(const wchar_t* path) {
// Useful debugging code to track down what files are in use.
if (flags & MOVEFILE_REPLACE_EXISTING) {
// Attempt to open the file exclusively.
- HANDLE file = ::CreateFileW(path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
- OPEN_EXISTING, 0, NULL);
+ HANDLE file = ::CreateFileW(path.value().c_str(),
+ GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ OPEN_EXISTING, 0, NULL);
if (file != INVALID_HANDLE_VALUE) {
- LOG(INFO) << " file not in use: " << path;
+ LOG(INFO) << " file not in use: " << path.value();
::CloseHandle(file);
} else {
- PLOG(INFO) << " file in use (or not found?): " << path;
+ PLOG(INFO) << " file in use (or not found?): " << path.value();
}
}
#endif
- VLOG(1) << "Scheduled for deletion: " << path;
+ VLOG(1) << "Scheduled for deletion: " << path.value();
return true;
}
-bool ScheduleDirectoryForDeletion(const wchar_t* dir_name) {
+bool ScheduleDirectoryForDeletion(const base::FilePath& dir_name) {
if (!IsSafeDirectoryNameForDeletion(dir_name)) {
- LOG(ERROR) << "Unsafe directory name for deletion: " << dir_name;
+ LOG(ERROR) << "Unsafe directory name for deletion: " << dir_name.value();
return false;
}
// Make sure the directory exists (it is ok if it doesn't)
- DWORD dir_attributes = ::GetFileAttributes(dir_name);
+ DWORD dir_attributes = ::GetFileAttributes(dir_name.value().c_str());
if (dir_attributes == INVALID_FILE_ATTRIBUTES) {
if (::GetLastError() == ERROR_FILE_NOT_FOUND) {
return true; // Ok if directory is missing
} else {
- PLOG(ERROR) << "Could not GetFileAttributes for " << dir_name;
+ PLOG(ERROR) << "Could not GetFileAttributes for " << dir_name.value();
return false;
}
}
// Confirm it is a directory
if (!(dir_attributes & FILE_ATTRIBUTE_DIRECTORY)) {
- LOG(ERROR) << "Scheduled directory is not a directory: " << dir_name;
+ LOG(ERROR) << "Scheduled directory is not a directory: "
+ << dir_name.value();
return false;
}
// First schedule all the normal files for deletion.
{
bool success = true;
- base::FileEnumerator file_enum(base::FilePath(dir_name), false,
+ base::FileEnumerator file_enum(dir_name, false,
base::FileEnumerator::FILES);
for (base::FilePath file = file_enum.Next(); !file.empty();
file = file_enum.Next()) {
- success = ScheduleFileSystemEntityForDeletion(file.value().c_str());
+ success = ScheduleFileSystemEntityForDeletion(file);
if (!success) {
LOG(ERROR) << "Failed to schedule file for deletion: " << file.value();
return false;
@@ -132,11 +134,11 @@ bool ScheduleDirectoryForDeletion(const wchar_t* dir_name) {
// Then recurse to all the subdirectories.
{
bool success = true;
- base::FileEnumerator dir_enum(base::FilePath(dir_name), false,
+ base::FileEnumerator dir_enum(dir_name, false,
base::FileEnumerator::DIRECTORIES);
for (base::FilePath sub_dir = dir_enum.Next(); !sub_dir.empty();
sub_dir = dir_enum.Next()) {
- success = ScheduleDirectoryForDeletion(sub_dir.value().c_str());
+ success = ScheduleDirectoryForDeletion(sub_dir);
if (!success) {
LOG(ERROR) << "Failed to schedule subdirectory for deletion: "
<< sub_dir.value();
@@ -146,8 +148,10 @@ bool ScheduleDirectoryForDeletion(const wchar_t* dir_name) {
}
// Now schedule the empty directory itself
- if (!ScheduleFileSystemEntityForDeletion(dir_name))
- LOG(ERROR) << "Failed to schedule directory for deletion: " << dir_name;
+ if (!ScheduleFileSystemEntityForDeletion(dir_name)) {
+ LOG(ERROR) << "Failed to schedule directory for deletion: "
+ << dir_name.value();
+ }
return true;
}
@@ -240,9 +244,10 @@ void StringArrayToMultiSZBytes(const std::vector<PendingMove>& strings,
DCHECK(++write_pointer == end_pointer);
}
-std::wstring GetShortPathName(const wchar_t* path) {
+base::FilePath GetShortPathName(const base::FilePath& path) {
std::wstring short_path;
- DWORD length = GetShortPathName(path, WriteInto(&short_path, MAX_PATH),
+ DWORD length = GetShortPathName(path.value().c_str(),
+ WriteInto(&short_path, MAX_PATH),
MAX_PATH);
DWORD last_error = ::GetLastError();
DLOG_IF(WARNING, length == 0 && last_error != ERROR_PATH_NOT_FOUND)
@@ -255,11 +260,10 @@ std::wstring GetShortPathName(const wchar_t* path) {
}
short_path.resize(length);
- return short_path;
+ return base::FilePath(short_path);
}
-HRESULT GetPendingMovesValue(
- std::vector<PendingMove>* pending_moves) {
+HRESULT GetPendingMovesValue(std::vector<PendingMove>* pending_moves) {
DCHECK(pending_moves);
pending_moves->clear();
@@ -319,9 +323,10 @@ HRESULT GetPendingMovesValue(
return hr;
}
-bool MatchPendingDeletePath(const std::wstring& short_form_needle,
- const std::wstring& reg_path) {
- std::wstring match_path(reg_path); // Stores the path stored in each entry.
+bool MatchPendingDeletePath(const base::FilePath& short_form_needle,
+ const base::FilePath& reg_path) {
+ // Stores the path stored in each entry.
+ std::wstring match_path(reg_path.value());
// First chomp the prefix since that will mess up GetShortPathName.
std::wstring prefix(L"\\??\\");
@@ -329,17 +334,16 @@ bool MatchPendingDeletePath(const std::wstring& short_form_needle,
match_path = match_path.substr(4);
// Get the short path name of the entry.
- std::wstring short_match_path(GetShortPathName(match_path.c_str()));
+ base::FilePath short_match_path(GetShortPathName(base::FilePath(match_path)));
// Now compare the paths. If it isn't one we're looking for, add it
// to the list to keep.
- return StartsWith(short_match_path, short_form_needle, false);
+ return StartsWith(short_match_path.value(), short_form_needle.value(), false);
}
// Removes all pending moves for the given |directory| and any contained
// files or subdirectories. Returns true on success
-bool RemoveFromMovesPendingReboot(const wchar_t* directory) {
- DCHECK(directory);
+bool RemoveFromMovesPendingReboot(const base::FilePath& directory) {
std::vector<PendingMove> pending_moves;
HRESULT hr = GetPendingMovesValue(&pending_moves);
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
@@ -352,12 +356,13 @@ bool RemoveFromMovesPendingReboot(const wchar_t* directory) {
}
// Get the short form of |directory| and use that to match.
- std::wstring short_directory(GetShortPathName(directory));
+ base::FilePath short_directory(GetShortPathName(directory));
std::vector<PendingMove> strings_to_keep;
for (std::vector<PendingMove>::const_iterator iter(pending_moves.begin());
- iter != pending_moves.end(); iter++) {
- if (!MatchPendingDeletePath(short_directory, iter->first)) {
+ iter != pending_moves.end(); ++iter) {
+ base::FilePath move_path(iter->first);
+ if (!MatchPendingDeletePath(short_directory, move_path)) {
// This doesn't match the deletions we are looking for. Preserve
// this string pair, making sure that it is in fact a pair.
strings_to_keep.push_back(*iter);
diff --git a/chrome/installer/util/delete_after_reboot_helper.h b/chrome/installer/util/delete_after_reboot_helper.h
index 6d59b26fb6..55cc52205a 100644
--- a/chrome/installer/util/delete_after_reboot_helper.h
+++ b/chrome/installer/util/delete_after_reboot_helper.h
@@ -13,6 +13,10 @@
#include <windows.h>
+namespace base {
+class FilePath;
+}
+
// Used by the unit tests.
extern const wchar_t kSessionManagerKey[];
extern const wchar_t kPendingFileRenameOps[];
@@ -20,14 +24,14 @@ extern const wchar_t kPendingFileRenameOps[];
typedef std::pair<std::wstring, std::wstring> PendingMove;
// Attempts to schedule only the item at path for deletion.
-bool ScheduleFileSystemEntityForDeletion(const wchar_t* path);
+bool ScheduleFileSystemEntityForDeletion(const base::FilePath& path);
// Attempts to recursively schedule the directory for deletion.
-bool ScheduleDirectoryForDeletion(const wchar_t* dir_name);
+bool ScheduleDirectoryForDeletion(const base::FilePath& dir_name);
// Removes all pending moves that are registered for |directory| and all
// elements contained in |directory|.
-bool RemoveFromMovesPendingReboot(const wchar_t* directory);
+bool RemoveFromMovesPendingReboot(const base::FilePath& directory);
// Retrieves the list of pending renames from the registry and returns a vector
// containing pairs of strings that represent the operations. If the list
@@ -39,8 +43,8 @@ HRESULT GetPendingMovesValue(std::vector<PendingMove>* pending_moves);
// |short_form_needle| is a file system path that has been shortened by
// GetShortPathName and |reg_path| is a path stored in the
// PendingFileRenameOperations key.
-bool MatchPendingDeletePath(const std::wstring& short_form_needle,
- const std::wstring& reg_path);
+bool MatchPendingDeletePath(const base::FilePath& short_form_needle,
+ const base::FilePath& reg_path);
// Converts the strings found in |buffer| to a list of PendingMoves that is
// returned in |value|.
@@ -63,9 +67,9 @@ void StringArrayToMultiSZBytes(const std::vector<PendingMove>& strings,
std::vector<char>* buffer);
// A helper function for the win32 GetShortPathName that more conveniently
-// returns a correctly sized wstring. Note that if |path| is not present on the
-// file system then GetShortPathName will return |path| unchanged, unlike the
-// win32 GetShortPathName which will return an error.
-std::wstring GetShortPathName(const wchar_t* path);
+// returns a FilePath. Note that if |path| is not present on the file system
+// then GetShortPathName will return |path| unchanged, unlike the win32
+// GetShortPathName which will return an error.
+base::FilePath GetShortPathName(const base::FilePath& path);
#endif // CHROME_INSTALLER_UTIL_DELETE_AFTER_REBOOT_HELPER_H_
diff --git a/chrome/installer/util/delete_after_reboot_helper_unittest.cc b/chrome/installer/util/delete_after_reboot_helper_unittest.cc
index 7fb7360c2d..c97cecdfa4 100644
--- a/chrome/installer/util/delete_after_reboot_helper_unittest.cc
+++ b/chrome/installer/util/delete_after_reboot_helper_unittest.cc
@@ -96,7 +96,8 @@ class DeleteAfterRebootHelperTest : public testing::Test {
base::FilePath temp_subdir_;
base::FilePath temp_subdir_file_;
};
-}
+
+} // namespace
TEST_F(DeleteAfterRebootHelperTest, TestStringListToMultiSZConversions) {
struct StringTest {
@@ -143,22 +144,23 @@ TEST_F(DeleteAfterRebootHelperTest, TestFileDeleteScheduleAndUnschedule) {
return;
}
- EXPECT_TRUE(ScheduleDirectoryForDeletion(temp_dir_.value().c_str()));
+ EXPECT_TRUE(ScheduleDirectoryForDeletion(temp_dir_));
std::vector<PendingMove> pending_moves;
EXPECT_TRUE(SUCCEEDED(GetPendingMovesValue(&pending_moves)));
// We should see, somewhere in this key, deletion writs for
// temp_file_, temp_subdir_file_, temp_subdir_ and temp_dir_ in that order.
- EXPECT_TRUE(pending_moves.size() > 3);
+ EXPECT_GT(pending_moves.size(), 3U);
// Get the short form of temp_file_ and use that to match.
- std::wstring short_temp_file(GetShortPathName(temp_file_.value().c_str()));
+ base::FilePath short_temp_file(GetShortPathName(temp_file_));
// Scan for the first expected delete.
std::vector<PendingMove>::const_iterator iter(pending_moves.begin());
for (; iter != pending_moves.end(); iter++) {
- if (MatchPendingDeletePath(short_temp_file, iter->first))
+ base::FilePath move_path(iter->first);
+ if (MatchPendingDeletePath(short_temp_file, move_path))
break;
}
@@ -168,21 +170,22 @@ TEST_F(DeleteAfterRebootHelperTest, TestFileDeleteScheduleAndUnschedule) {
for (int i = 0; i < arraysize(expected_paths); ++i) {
EXPECT_FALSE(iter == pending_moves.end());
if (iter != pending_moves.end()) {
- std::wstring short_path_name(
- GetShortPathName(expected_paths[i].value().c_str()));
- EXPECT_TRUE(MatchPendingDeletePath(short_path_name, iter->first));
+ base::FilePath short_path_name(GetShortPathName(expected_paths[i]));
+ base::FilePath move_path(iter->first);
+ EXPECT_TRUE(MatchPendingDeletePath(short_path_name, move_path));
++iter;
}
}
// Test that we can remove the pending deletes.
- EXPECT_TRUE(RemoveFromMovesPendingReboot(temp_dir_.value().c_str()));
+ EXPECT_TRUE(RemoveFromMovesPendingReboot(temp_dir_));
HRESULT hr = GetPendingMovesValue(&pending_moves);
EXPECT_TRUE(hr == S_OK || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
std::vector<PendingMove>::const_iterator check_iter(pending_moves.begin());
for (; check_iter != pending_moves.end(); ++check_iter) {
- EXPECT_FALSE(MatchPendingDeletePath(short_temp_file, check_iter->first));
+ base::FilePath move_path(check_iter->first);
+ EXPECT_FALSE(MatchPendingDeletePath(short_temp_file, move_path));
}
}
@@ -195,7 +198,7 @@ TEST_F(DeleteAfterRebootHelperTest, TestFileDeleteSchedulingWithActualDeletes) {
GetPendingMovesValue(&initial_pending_moves);
size_t initial_pending_moves_size = initial_pending_moves.size();
- EXPECT_TRUE(ScheduleDirectoryForDeletion(temp_dir_.value().c_str()));
+ EXPECT_TRUE(ScheduleDirectoryForDeletion(temp_dir_));
std::vector<PendingMove> pending_moves;
EXPECT_TRUE(SUCCEEDED(GetPendingMovesValue(&pending_moves)));
@@ -205,12 +208,13 @@ TEST_F(DeleteAfterRebootHelperTest, TestFileDeleteSchedulingWithActualDeletes) {
EXPECT_TRUE(pending_moves.size() > 3);
// Get the short form of temp_file_ and use that to match.
- std::wstring short_temp_file(GetShortPathName(temp_file_.value().c_str()));
+ base::FilePath short_temp_file(GetShortPathName(temp_file_));
// Scan for the first expected delete.
std::vector<PendingMove>::const_iterator iter(pending_moves.begin());
for (; iter != pending_moves.end(); iter++) {
- if (MatchPendingDeletePath(short_temp_file, iter->first))
+ base::FilePath move_path(iter->first);
+ if (MatchPendingDeletePath(short_temp_file, move_path))
break;
}
@@ -220,9 +224,9 @@ TEST_F(DeleteAfterRebootHelperTest, TestFileDeleteSchedulingWithActualDeletes) {
for (int i = 0; i < arraysize(expected_paths); ++i) {
EXPECT_FALSE(iter == pending_moves.end());
if (iter != pending_moves.end()) {
- std::wstring short_path_name(
- GetShortPathName(expected_paths[i].value().c_str()));
- EXPECT_TRUE(MatchPendingDeletePath(short_path_name, iter->first));
+ base::FilePath short_path_name(GetShortPathName(expected_paths[i]));
+ base::FilePath move_path(iter->first);
+ EXPECT_TRUE(MatchPendingDeletePath(short_path_name, move_path));
++iter;
}
}
@@ -231,7 +235,7 @@ TEST_F(DeleteAfterRebootHelperTest, TestFileDeleteSchedulingWithActualDeletes) {
base::DeleteFile(temp_dir_, true);
// Test that we can remove the pending deletes.
- EXPECT_TRUE(RemoveFromMovesPendingReboot(temp_dir_.value().c_str()));
+ EXPECT_TRUE(RemoveFromMovesPendingReboot(temp_dir_));
HRESULT hr = GetPendingMovesValue(&pending_moves);
EXPECT_TRUE(hr == S_OK || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
@@ -239,7 +243,8 @@ TEST_F(DeleteAfterRebootHelperTest, TestFileDeleteSchedulingWithActualDeletes) {
std::vector<PendingMove>::const_iterator check_iter(pending_moves.begin());
for (; check_iter != pending_moves.end(); ++check_iter) {
- EXPECT_FALSE(MatchPendingDeletePath(short_temp_file, check_iter->first));
+ base::FilePath move_path(check_iter->first);
+ EXPECT_FALSE(MatchPendingDeletePath(short_temp_file, move_path));
}
}
diff --git a/chrome/installer/util/self_cleaning_temp_dir.cc b/chrome/installer/util/self_cleaning_temp_dir.cc
index 6426dd9f98..23d3091802 100644
--- a/chrome/installer/util/self_cleaning_temp_dir.cc
+++ b/chrome/installer/util/self_cleaning_temp_dir.cc
@@ -84,7 +84,7 @@ bool SelfCleaningTempDir::Delete() {
LOG(WARNING) << "Failed to delete temporary directory " << path().value()
<< ". Scheduling for deletion at reboot.";
schedule_deletes = true;
- if (!ScheduleDirectoryForDeletion(path().value().c_str()))
+ if (!ScheduleDirectoryForDeletion(path()))
return false; // Entirely unexpected failure (Schedule logs the reason).
}
@@ -101,7 +101,7 @@ bool SelfCleaningTempDir::Delete() {
if (schedule_deletes) {
// Ignore the return code. If we fail to schedule, go ahead and add the
// other parent directories anyway.
- ScheduleFileSystemEntityForDeletion(next_dir.value().c_str());
+ ScheduleFileSystemEntityForDeletion(next_dir);
}
if (next_dir == base_dir_)
break; // We just processed the topmost directory we created.
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index c74754770c..19a5feb5a9 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -697,8 +697,7 @@ bool ElevateAndRegisterChrome(BrowserDistribution* dist,
DCHECK(InstallUtil::IsPerUserInstall(chrome_exe.c_str()));
DCHECK_LT(base::win::GetVersion(), base::win::VERSION_WIN8);
base::FilePath exe_path =
- base::FilePath::FromWStringHack(chrome_exe).DirName()
- .Append(installer::kSetupExe);
+ base::FilePath(chrome_exe).DirName().Append(installer::kSetupExe);
if (!base::PathExists(exe_path)) {
HKEY reg_root = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ?
HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
@@ -1696,6 +1695,8 @@ string16 ShellUtil::BuildAppModelId(
}
ShellUtil::DefaultState ShellUtil::GetChromeDefaultState() {
+ if (!BrowserDistribution::GetDistribution()->CanSetAsDefault())
+ return NOT_DEFAULT;
// When we check for default browser we don't necessarily want to count file
// type handlers and icons as having changed the default browser status,
// since the user may have changed their shell settings to cause HTML files
@@ -1711,6 +1712,8 @@ ShellUtil::DefaultState ShellUtil::GetChromeDefaultState() {
ShellUtil::DefaultState ShellUtil::GetChromeDefaultProtocolClientState(
const string16& protocol) {
+ if (!BrowserDistribution::GetDistribution()->CanSetAsDefault())
+ return NOT_DEFAULT;
if (protocol.empty())
return UNKNOWN_DEFAULT;