diff options
Diffstat (limited to 'chrome/installer')
-rw-r--r-- | chrome/installer/setup/setup_main.cc | 24 | ||||
-rw-r--r-- | chrome/installer/setup/setup_util.cc | 70 | ||||
-rw-r--r-- | chrome/installer/setup/setup_util.h | 27 | ||||
-rw-r--r-- | chrome/installer/util/util_constants.cc | 12 | ||||
-rw-r--r-- | chrome/installer/util/util_constants.h | 20 |
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_ |