Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1949)

Unified Diff: chrome/browser/component_updater/component_unpacker.cc

Issue 15908002: Differential updates for components. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Sync to LKGR revision 207804. Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/component_updater/component_unpacker.cc
diff --git a/chrome/browser/component_updater/component_unpacker.cc b/chrome/browser/component_updater/component_unpacker.cc
index 94546373f39b4cbac174bf84841c6bcc5f099b6c..341df220ffe8d5122920cca5bf4db483b2b8eb49 100644
--- a/chrome/browser/component_updater/component_unpacker.cc
+++ b/chrome/browser/component_updater/component_unpacker.cc
@@ -12,6 +12,7 @@
#include "base/memory/scoped_handle.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "chrome/browser/component_updater/component_patcher.h"
#include "chrome/browser/component_updater/component_updater_service.h"
#include "chrome/common/extensions/extension_constants.h"
#include "crypto/secure_hash.h"
@@ -22,11 +23,12 @@
using crypto::SecureHash;
namespace {
+
// This class makes sure that the CRX digital signature is valid
// and well formed.
class CRXValidator {
public:
- explicit CRXValidator(FILE* crx_file) : valid_(false) {
+ explicit CRXValidator(FILE* crx_file) : valid_(false), delta_(false) {
extensions::CrxFile::Header header;
size_t len = fread(&header, 1, sizeof(header), crx_file);
if (len < sizeof(header))
@@ -37,6 +39,7 @@ class CRXValidator {
extensions::CrxFile::Parse(header, &error));
if (!crx.get())
return;
+ delta_ = extensions::CrxFile::HeaderIsDelta(header);
std::vector<uint8> key(header.key_size);
len = fread(&key[0], sizeof(uint8), header.key_size, crx_file);
@@ -72,10 +75,13 @@ class CRXValidator {
bool valid() const { return valid_; }
+ bool delta() const { return delta_; }
+
const std::vector<uint8>& public_key() const { return public_key_; }
private:
bool valid_;
+ bool delta_;
std::vector<uint8> public_key_;
};
@@ -98,12 +104,29 @@ base::DictionaryValue* ReadManifest(const base::FilePath& unpack_path) {
return static_cast<base::DictionaryValue*>(root.release());
}
+// Deletes a path if it exists, and then creates a directory there.
+// Returns true if and only if these operations were successful.
+// This method doesn't take any special steps to prevent files from
+// being inserted into the target directory by another process or thread.
+bool MakeEmptyDirectory(const base::FilePath& path) {
+ if (file_util::PathExists(path)) {
+ if (!file_util::Delete(path, true))
+ return false;
+ }
+ if (!file_util::CreateDirectory(path))
+ return false;
+ return true;
+}
+
} // namespace.
ComponentUnpacker::ComponentUnpacker(const std::vector<uint8>& pk_hash,
const base::FilePath& path,
+ const std::string& fingerprint,
+ ComponentPatcher* patcher,
ComponentInstaller* installer)
- : error_(kNone) {
+ : error_(kNone),
+ extended_error_(0) {
if (pk_hash.empty() || path.empty()) {
error_ = kInvalidParams;
return;
@@ -135,31 +158,61 @@ ComponentUnpacker::ComponentUnpacker(const std::vector<uint8>& pk_hash,
return;
}
// We want the temporary directory to be unique and yet predictable, so
- // we can easily find the package in a end user machine.
- std::string dir(
+ // we can easily find the package in an end user machine.
+ const std::string dir(
base::StringPrintf("CRX_%s", base::HexEncode(hash, 6).c_str()));
unpack_path_ = path.DirName().AppendASCII(dir.c_str());
- if (file_util::DirectoryExists(unpack_path_)) {
- if (!file_util::Delete(unpack_path_, true)) {
- unpack_path_.clear();
- error_ = kUzipPathError;
- return;
- }
- }
- if (!file_util::CreateDirectory(unpack_path_)) {
+ if (!MakeEmptyDirectory(unpack_path_)) {
unpack_path_.clear();
- error_ = kUzipPathError;
+ error_ = kUnzipPathError;
return;
}
- if (!zip::Unzip(path, unpack_path_)) {
- error_ = kUnzipFailed;
- return;
+ if (validator.delta()) { // Package is a diff package.
+ // We want a different temp directory for the delta files; we'll put the
+ // patch output into unpack_path_.
+ std::string dir(
+ base::StringPrintf("CRX_%s_diff", base::HexEncode(hash, 6).c_str()));
+ base::FilePath unpack_diff_path = path.DirName().AppendASCII(dir.c_str());
+ if (!MakeEmptyDirectory(unpack_diff_path)) {
+ error_ = kUnzipPathError;
+ return;
+ }
+ if (!zip::Unzip(path, unpack_diff_path)) {
+ error_ = kUnzipFailed;
+ return;
+ }
+ ComponentUnpacker::Error result = DifferentialUpdatePatch(unpack_diff_path,
+ unpack_path_,
+ patcher,
+ installer,
+ &extended_error_);
+ file_util::Delete(unpack_diff_path, true);
+ unpack_diff_path.clear();
+ error_ = result;
+ if (error_ != kNone) {
+ return;
+ }
+ } else {
+ // Package is a normal update/install; unzip it into unpack_path_ directly.
+ if (!zip::Unzip(path, unpack_path_)) {
+ error_ = kUnzipFailed;
+ return;
+ }
}
scoped_ptr<base::DictionaryValue> manifest(ReadManifest(unpack_path_));
if (!manifest.get()) {
error_ = kBadManifest;
return;
}
+ // Write the fingerprint to disk.
+ if (static_cast<int>(fingerprint.size()) !=
+ file_util::WriteFile(
+ unpack_path_.Append(FILE_PATH_LITERAL("manifest.fingerprint")),
+ fingerprint.c_str(),
+ fingerprint.size())) {
+ error_ = kFingerprintWriteFailed;
+ return;
+ }
if (!installer->Install(*manifest, unpack_path_)) {
error_ = kInstallerError;
return;
@@ -169,7 +222,6 @@ ComponentUnpacker::ComponentUnpacker(const std::vector<uint8>& pk_hash,
}
ComponentUnpacker::~ComponentUnpacker() {
- if (!unpack_path_.empty()) {
+ if (!unpack_path_.empty())
file_util::Delete(unpack_path_, true);
- }
}

Powered by Google App Engine
This is Rietveld 408576698