diff options
author | sorin@chromium.org <sorin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-21 20:41:36 +0000 |
---|---|---|
committer | sorin@chromium.org <sorin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-21 20:41:36 +0000 |
commit | e3e696d3e883f38577252e1a1a6a98ae89dea079 (patch) | |
tree | b5adbe01ec71c10c5f2d37bff9161acc40da2455 /chrome/installer | |
parent | 0ad74fd43800b179bc3d50847f695d4a902c79ca (diff) | |
download | chromium_src-e3e696d3e883f38577252e1a1a6a98ae89dea079.zip chromium_src-e3e696d3e883f38577252e1a1a6a98ae89dea079.tar.gz chromium_src-e3e696d3e883f38577252e1a1a6a98ae89dea079.tar.bz2 |
Differential updates for components. We are adding support for delivering delta updates for Chrome components. Initial platform support for the patcher is Windows only. The update response includes both the full update and, if available, the differential update. The differential update is tried first, then the full update, if needed.
BUG=245318
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=207805
Review URL: https://chromiumcodereview.appspot.com/15908002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207917 0039d316-1c4b-4281-b951-d872f2087c98
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_ |