summaryrefslogtreecommitdiffstats
path: root/chrome/installer
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/installer')
-rw-r--r--chrome/installer/setup/setup_main.cc24
-rw-r--r--chrome/installer/setup/setup_util.cc70
-rw-r--r--chrome/installer/setup/setup_util.h27
-rw-r--r--chrome/installer/util/util_constants.cc12
-rw-r--r--chrome/installer/util/util_constants.h20
5 files changed, 140 insertions, 13 deletions
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 735be3f..2c60a20 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -14,6 +14,7 @@
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/file_version_info.h"
+#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/path_service.h"
#include "base/process_util.h"
@@ -491,7 +492,6 @@ bool CheckAppHostPreconditions(const InstallationState& original_state,
InstallerState* installer_state,
installer::InstallStatus* status) {
if (installer_state->FindProduct(BrowserDistribution::CHROME_APP_HOST)) {
-
if (!installer_state->is_multi_install()) {
LOG(DFATAL) << "App Launcher requires multi install";
*status = installer::APP_HOST_REQUIRES_MULTI_INSTALL;
@@ -507,7 +507,6 @@ bool CheckAppHostPreconditions(const InstallationState& original_state,
installer_state->WriteInstallerResult(*status, 0, NULL);
return false;
}
-
}
return true;
@@ -1477,6 +1476,27 @@ bool HandleNonInstallCmdLineOptions(const InstallationState& original_state,
} else if (cmd_line.HasSwitch(installer::switches::kChromeFrameQuickEnable)) {
*exit_code = installer::ChromeFrameQuickEnable(original_state,
installer_state);
+ } else if (cmd_line.HasSwitch(installer::switches::kPatch)) {
+ const std::string patch_type_str(
+ cmd_line.GetSwitchValueASCII(installer::switches::kPatch));
+ const base::FilePath input_file(
+ cmd_line.GetSwitchValuePath(installer::switches::kInputFile));
+ const base::FilePath patch_file(
+ cmd_line.GetSwitchValuePath(installer::switches::kPatchFile));
+ const base::FilePath output_file(
+ cmd_line.GetSwitchValuePath(installer::switches::kOutputFile));
+
+ if (patch_type_str == installer::kCourgette) {
+ *exit_code = installer::CourgettePatchFiles(input_file,
+ patch_file,
+ output_file);
+ } else if (patch_type_str == installer::kBsdiff) {
+ *exit_code = installer::BsdiffPatchFiles(input_file,
+ patch_file,
+ output_file);
+ } else {
+ *exit_code = installer::PATCH_INVALID_ARGUMENTS;
+ }
} else {
handled = false;
}
diff --git a/chrome/installer/setup/setup_util.cc b/chrome/installer/setup/setup_util.cc
index ef0f8360..d679274 100644
--- a/chrome/installer/setup/setup_util.cc
+++ b/chrome/installer/setup/setup_util.cc
@@ -24,6 +24,7 @@
#include "chrome/installer/util/util_constants.h"
#include "chrome/installer/util/work_item.h"
#include "courgette/courgette.h"
+#include "courgette/third_party/bsdiff.h"
#include "third_party/bspatch/mbspatch.h"
namespace installer {
@@ -86,12 +87,59 @@ bool SupportsSingleInstall(BrowserDistribution::Type type) {
} // namespace
+int CourgettePatchFiles(const base::FilePath& src,
+ const base::FilePath& patch,
+ const base::FilePath& dest) {
+ VLOG(1) << "Applying Courgette patch " << patch.value()
+ << " to file " << src.value()
+ << " and generating file " << dest.value();
+
+ if (src.empty() || patch.empty() || dest.empty())
+ return installer::PATCH_INVALID_ARGUMENTS;
+
+ const courgette::Status patch_status =
+ courgette::ApplyEnsemblePatch(src.value().c_str(),
+ patch.value().c_str(),
+ dest.value().c_str());
+ const int exit_code = (patch_status != courgette::C_OK) ?
+ static_cast<int>(patch_status) + kCourgetteErrorOffset : 0;
+
+ LOG_IF(ERROR, exit_code)
+ << "Failed to apply Courgette patch " << patch.value()
+ << " to file " << src.value() << " and generating file " << dest.value()
+ << ". err=" << exit_code;
+
+ return exit_code;
+}
+
+int BsdiffPatchFiles(const base::FilePath& src,
+ const base::FilePath& patch,
+ const base::FilePath& dest) {
+ VLOG(1) << "Applying bsdiff patch " << patch.value()
+ << " to file " << src.value()
+ << " and generating file " << dest.value();
+
+ if (src.empty() || patch.empty() || dest.empty())
+ return installer::PATCH_INVALID_ARGUMENTS;
+
+ const int patch_status = courgette::ApplyBinaryPatch(src, patch, dest);
+ const int exit_code = patch_status != OK ?
+ patch_status + kBsdiffErrorOffset : 0;
+
+ LOG_IF(ERROR, exit_code)
+ << "Failed to apply bsdiff patch " << patch.value()
+ << " to file " << src.value() << " and generating file " << dest.value()
+ << ". err=" << exit_code;
+
+ return exit_code;
+}
+
int ApplyDiffPatch(const base::FilePath& src,
const base::FilePath& patch,
const base::FilePath& dest,
const InstallerState* installer_state) {
- VLOG(1) << "Applying patch " << patch.value() << " to file " << src.value()
- << " and generating file " << dest.value();
+ VLOG(1) << "Applying patch " << patch.value() << " to file "
+ << src.value() << " and generating file " << dest.value();
if (installer_state != NULL)
installer_state->UpdateStage(installer::ENSEMBLE_PATCHING);
@@ -105,8 +153,10 @@ int ApplyDiffPatch(const base::FilePath& src,
if (patch_status == courgette::C_OK)
return 0;
- VLOG(1) << "Failed to apply patch " << patch.value()
- << " using courgette. err=" << patch_status;
+ LOG(ERROR)
+ << "Failed to apply patch " << patch.value()
+ << " to file " << src.value() << " and generating file " << dest.value()
+ << " using courgette. err=" << patch_status;
// If we ran out of memory or disk space, then these are likely the errors
// we will see. If we run into them, return an error and stay on the
@@ -119,8 +169,16 @@ int ApplyDiffPatch(const base::FilePath& src,
if (installer_state != NULL)
installer_state->UpdateStage(installer::BINARY_PATCHING);
- return ApplyBinaryPatch(src.value().c_str(), patch.value().c_str(),
- dest.value().c_str());
+ int binary_patch_status = ApplyBinaryPatch(src.value().c_str(),
+ patch.value().c_str(),
+ dest.value().c_str());
+
+ LOG_IF(ERROR, binary_patch_status != OK)
+ << "Failed to apply patch " << patch.value()
+ << " to file " << src.value() << " and generating file " << dest.value()
+ << " using bsdiff. err=" << binary_patch_status;
+
+ return binary_patch_status;
}
Version* GetMaxVersionFromArchiveDir(const base::FilePath& chrome_path) {
diff --git a/chrome/installer/setup/setup_util.h b/chrome/installer/setup/setup_util.h
index 2a7530a..97bf4d4 100644
--- a/chrome/installer/setup/setup_util.h
+++ b/chrome/installer/setup/setup_util.h
@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// This file declares util functions for setup project.
+// This file declares util functions for setup project. It also declares a
+// few functions that the Chrome component updater uses for patching binary
+// deltas.
#ifndef CHROME_INSTALLER_SETUP_SETUP_UTIL_H_
#define CHROME_INSTALLER_SETUP_SETUP_UTIL_H_
@@ -28,15 +30,32 @@ class InstallationState;
class InstallerState;
class ProductState;
-// Apply a diff patch to source file. First tries to apply it using courgette
-// since it checks for courgette header and fails quickly. If that fails
-// tries to apply the patch using regular bsdiff. Returns status code.
+// Apply a diff patch to source file. First tries to apply it using Courgette
+// since it checks for Courgette header and fails quickly. If that fails
+// tries to apply the patch using regular bsdiff. Returns status code as
+// defined by the bsdiff code (see third_party/bspatch/mbspatch.h for the
+// definitions of the codes).
// The installer stage is updated if |installer_state| is non-NULL.
int ApplyDiffPatch(const base::FilePath& src,
const base::FilePath& patch,
const base::FilePath& dest,
const InstallerState* installer_state);
+// Applies a patch file to source file using Courgette. Returns 0 in case of
+// success. In case of errors, it returns kCourgetteErrorOffset + a Courgette
+// status code, as defined in courgette/courgette.h
+int CourgettePatchFiles(const base::FilePath& src,
+ const base::FilePath& patch,
+ const base::FilePath& dest);
+
+// Applies a patch file to source file using bsdiff. This function uses
+// Courgette's flavor of bsdiff. Returns 0 in case of success, or
+// kBsdiffErrorOffset + a bsdiff status code in case of errors.
+// See courgette/third_party/bsdiff.h for details.
+int BsdiffPatchFiles(const base::FilePath& src,
+ const base::FilePath& patch,
+ const base::FilePath& dest);
+
// Find the version of Chrome from an install source directory.
// Chrome_path should contain at least one version folder.
// Returns the maximum version found or NULL if no version is found.
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc
index c380a5f..e293e76 100644
--- a/chrome/installer/util/util_constants.cc
+++ b/chrome/installer/util/util_constants.cc
@@ -196,6 +196,15 @@ const char kExperimentGroup[] = "experiment-group";
// to. See DuplicateGoogleUpdateSystemClientKey for details.
const char kToastResultsKey[] = "toast-results-key";
+// Applies a binary patch to a file. The input, patch, and the output file are
+// specified as command line arguments following the --patch switch.
+// Ex: --patch=courgette --input_file='input' --patch_file='patch'
+// --output_file='output'
+const char kPatch[] = "patch";
+const char kInputFile[] = "input-file";
+const char kPatchFile[] = "patch-file";
+const char kOutputFile[] = "output-file";
+
} // namespace switches
// The Active Setup executable will be an identical copy of setup.exe; this is
@@ -261,4 +270,7 @@ const wchar_t kChromeChannelStable[] = L"";
const size_t kMaxAppModelIdLength = 64U;
+const char kCourgette[] = "courgette";
+const char kBsdiff[] = "bsdiff";
+
} // namespace installer
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index bb7b693..3f9a496 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -80,12 +80,14 @@ enum InstallStatus {
INVALID_STATE_FOR_OPTION, // 47. A non-install option was called with an
// invalid installer state.
WAIT_FOR_EXISTING_FAILED, // 48. OS error waiting for existing setup.exe.
+ PATCH_INVALID_ARGUMENTS, // 49. The arguments of --patch were missing or
+ // they were invalid for any reason.
// Friendly reminder: note the COMPILE_ASSERT below.
};
// Existing InstallStatus values must not change. Always add to the end.
-COMPILE_ASSERT(installer::WAIT_FOR_EXISTING_FAILED == 48,
+COMPILE_ASSERT(installer::PATCH_INVALID_ARGUMENTS == 49,
dont_change_enum);
// The type of an update archive.
@@ -128,6 +130,7 @@ COMPILE_ASSERT(DEFERRING_TO_HIGHER_VERSION == 18,
never_ever_ever_change_InstallerStage_values_bang);
namespace switches {
+
extern const char kAutoLaunchChrome[];
extern const char kChrome[];
extern const char kChromeAppHostDeprecated[]; // TODO(huangs): Remove by M27.
@@ -177,6 +180,11 @@ extern const char kInactiveUserToast[];
extern const char kSystemLevelToast[];
extern const char kExperimentGroup[];
extern const char kToastResultsKey[];
+extern const char kPatch[];
+extern const char kInputFile[];
+extern const char kPatchFile[];
+extern const char kOutputFile[];
+
} // namespace switches
extern const wchar_t kActiveSetupExe[];
@@ -237,6 +245,16 @@ extern const wchar_t kChromeChannelStable[];
extern const size_t kMaxAppModelIdLength;
+// The range of error values for the installer, Courgette, and bsdiff is
+// overlapping. These offset values disambiguate between different sets
+// of errors by shifting the values up with the specified offset.
+const int kCourgetteErrorOffset = 300;
+const int kBsdiffErrorOffset = 600;
+
+// Arguments to --patch switch
+extern const char kCourgette[];
+extern const char kBsdiff[];
+
} // namespace installer
#endif // CHROME_INSTALLER_UTIL_UTIL_CONSTANTS_H_