AU: Start checkpointing update progress.
Checkpoint the manifest metadata size and the update
check response hash in the preference store. Also checkpoint
the next operation and data offset.
Add methods for getting/setting hash context.
BUG=7390,7394
TEST=unit tests
Change-Id: I25291bf598ac9b0f1033e11cfe59df45b1f6eeab
Review URL: http://codereview.chromium.org/3521016
diff --git a/delta_performer.cc b/delta_performer.cc
index 2436797..6143ec5 100644
--- a/delta_performer.cc
+++ b/delta_performer.cc
@@ -21,6 +21,7 @@
#include "update_engine/extent_writer.h"
#include "update_engine/graph_types.h"
#include "update_engine/payload_signer.h"
+#include "update_engine/prefs_interface.h"
#include "update_engine/subprocess.h"
using std::min;
@@ -36,6 +37,18 @@
const int kDeltaProtobufLengthLength = 8;
const char kUpdatePayloadPublicKeyPath[] =
"/usr/share/update_engine/update-payload-key.pub.pem";
+const int kUpdateStateOperationInvalid = -1;
+
+// Returns true if |op| is idempotent -- i.e., if we can interrupt it and repeat
+// it safely. Returns false otherwise.
+bool IsIdempotentOperation(const DeltaArchiveManifest_InstallOperation& op) {
+ if (op.src_extents_size() == 0) {
+ return true;
+ }
+ // TODO(petkov): Cover the case where the source and target extents don't
+ // intersect.
+ return false;
+}
// Converts extents to a human-readable string, for use by DumpUpdateProto().
string ExtentsToString(const RepeatedPtrField<Extent>& extents) {
@@ -177,10 +190,13 @@
}
// Remove protobuf and header info from buffer_, so buffer_ contains
// just data blobs
- DiscardBufferHeadBytes(strlen(kDeltaMagic) +
- kDeltaVersionLength +
- kDeltaProtobufLengthLength + protobuf_length,
+ size_t metadata_size = strlen(kDeltaMagic) + kDeltaVersionLength +
+ kDeltaProtobufLengthLength + protobuf_length;
+ DiscardBufferHeadBytes(metadata_size,
true); // do_hash
+ LOG_IF(WARNING, !prefs_->SetInt64(kPrefsManifestMetadataSize,
+ metadata_size))
+ << "Unable to save the manifest metadata size.";
manifest_valid_ = true;
block_size_ = manifest_.block_size();
}
@@ -202,6 +218,12 @@
}
bool is_kernel_partition =
(next_operation_num_ >= manifest_.install_operations_size());
+ // If about to start a non-idempotent operation, clear the update state so
+ // that if the operation gets interrupted, we don't try to resume the
+ // update.
+ if (!IsIdempotentOperation(op)) {
+ ResetUpdateProgress();
+ }
if (op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE ||
op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ) {
if (!PerformReplaceOperation(op, is_kernel_partition)) {
@@ -223,6 +245,7 @@
}
}
next_operation_num_++;
+ CheckpointUpdateProgress();
}
return count;
}
@@ -489,4 +512,22 @@
buffer_.erase(buffer_.begin(), buffer_.begin() + count);
}
+bool DeltaPerformer::ResetUpdateProgress() {
+ TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextOperation,
+ kUpdateStateOperationInvalid));
+ return true;
+}
+
+bool DeltaPerformer::CheckpointUpdateProgress() {
+ // First reset the progress in case we die in the middle of the state update.
+ ResetUpdateProgress();
+ TEST_AND_RETURN_FALSE(prefs_->SetString(kPrefsUpdateStateSignedSHA256Context,
+ hash_calculator_.GetContext()));
+ TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextDataOffset,
+ buffer_offset_));
+ TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextOperation,
+ next_operation_num_));
+ return true;
+}
+
} // namespace chromeos_update_engine
diff --git a/delta_performer.h b/delta_performer.h
index 82f4d90..2f9fd8a 100644
--- a/delta_performer.h
+++ b/delta_performer.h
@@ -17,13 +17,16 @@
namespace chromeos_update_engine {
+class PrefsInterface;
+
// This class performs the actions in a delta update synchronously. The delta
// update itself should be passed in in chunks as it is received.
class DeltaPerformer : public FileWriter {
public:
- DeltaPerformer()
- : fd_(-1),
+ DeltaPerformer(PrefsInterface* prefs)
+ : prefs_(prefs),
+ fd_(-1),
kernel_fd_(-1),
manifest_valid_(false),
next_operation_num_(0),
@@ -99,6 +102,12 @@
// updates the hash calculator with these bytes before discarding them.
void DiscardBufferHeadBytes(size_t count, bool do_hash);
+ bool ResetUpdateProgress();
+ bool CheckpointUpdateProgress();
+
+ // Update Engine preference store.
+ PrefsInterface* prefs_;
+
// File descriptor of open device.
int fd_;
diff --git a/delta_performer_unittest.cc b/delta_performer_unittest.cc
index 8c7d2cd..12de8a9 100755
--- a/delta_performer_unittest.cc
+++ b/delta_performer_unittest.cc
@@ -9,15 +9,16 @@
#include <string>
#include <vector>
+#include <base/scoped_ptr.h>
+#include <base/string_util.h>
#include <google/protobuf/repeated_field.h>
#include <gtest/gtest.h>
-#include "base/scoped_ptr.h"
-#include "base/string_util.h"
#include "update_engine/delta_diff_generator.h"
#include "update_engine/delta_performer.h"
#include "update_engine/graph_types.h"
#include "update_engine/payload_signer.h"
+#include "update_engine/prefs_mock.h"
#include "update_engine/test_utils.h"
#include "update_engine/update_metadata.pb.h"
#include "update_engine/utils.h"
@@ -27,6 +28,8 @@
using std::min;
using std::string;
using std::vector;
+using testing::_;
+using testing::Return;
extern const char* kUnittestPrivateKeyPath;
extern const char* kUnittestPublicKeyPath;
@@ -205,6 +208,8 @@
vector<char> delta;
EXPECT_TRUE(utils::ReadFile(delta_path, &delta));
+ uint64_t manifest_metadata_size;
+
// Check that the null signature blob exists
{
LOG(INFO) << "delta size: " << delta.size();
@@ -218,10 +223,11 @@
EXPECT_TRUE(manifest.ParseFromArray(&delta[kManifestOffset],
manifest_size));
EXPECT_TRUE(manifest.has_signatures_offset());
+ manifest_metadata_size = kManifestOffset + manifest_size;
Signatures sigs_message;
EXPECT_TRUE(sigs_message.ParseFromArray(
- &delta[kManifestOffset + manifest_size + manifest.signatures_offset()],
+ &delta[manifest_metadata_size + manifest.signatures_offset()],
manifest.signatures_size()));
EXPECT_EQ(1, sigs_message.signatures_size());
const Signatures_Signature& signature = sigs_message.signatures(0);
@@ -234,8 +240,18 @@
EXPECT_FALSE(signature.data().empty());
}
+ PrefsMock prefs;
+ EXPECT_CALL(prefs, SetInt64(kPrefsManifestMetadataSize,
+ manifest_metadata_size)).WillOnce(Return(true));
+ EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextOperation, _))
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(prefs, SetInt64(kPrefsUpdateStateNextDataOffset, _))
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
+ .WillRepeatedly(Return(true));
+
// Update the A image in place.
- DeltaPerformer performer;
+ DeltaPerformer performer(&prefs);
EXPECT_EQ(0, performer.Open(a_img.c_str(), 0, 0));
EXPECT_TRUE(performer.OpenKernel(old_kernel.c_str()));
diff --git a/download_action.cc b/download_action.cc
index 608eeb9..4462ab8 100644
--- a/download_action.cc
+++ b/download_action.cc
@@ -20,8 +20,10 @@
// Use a buffer to reduce the number of IOPS on SSD devices.
const size_t kFileWriterBufferSize = 128 * 1024; // 128 KiB
-DownloadAction::DownloadAction(HttpFetcher* http_fetcher)
- : writer_(NULL),
+DownloadAction::DownloadAction(PrefsInterface* prefs,
+ HttpFetcher* http_fetcher)
+ : prefs_(prefs),
+ writer_(NULL),
http_fetcher_(http_fetcher),
delegate_(NULL),
bytes_received_(0) {}
@@ -61,7 +63,7 @@
new GzipDecompressingFileWriter(split_file_writer_.get()));
writer_ = decompressing_file_writer_.get();
} else {
- delta_performer_.reset(new DeltaPerformer);
+ delta_performer_.reset(new DeltaPerformer(prefs_));
writer_ = delta_performer_.get();
}
}
diff --git a/download_action.h b/download_action.h
index f6d5a11..62dd29a 100644
--- a/download_action.h
+++ b/download_action.h
@@ -49,6 +49,7 @@
class DownloadAction;
class NoneType;
+class PrefsInterface;
template<>
class ActionTraits<DownloadAction> {
@@ -64,7 +65,7 @@
// Takes ownership of the passed in HttpFetcher. Useful for testing.
// A good calling pattern is:
// DownloadAction(new WhateverHttpFetcher);
- DownloadAction(HttpFetcher* http_fetcher);
+ DownloadAction(PrefsInterface* prefs, HttpFetcher* http_fetcher);
virtual ~DownloadAction();
typedef ActionTraits<DownloadAction>::InputObjectType InputObjectType;
typedef ActionTraits<DownloadAction>::OutputObjectType OutputObjectType;
@@ -96,6 +97,9 @@
// The InstallPlan passed in
InstallPlan install_plan_;
+ // Update Engine preference store.
+ PrefsInterface* prefs_;
+
// The FileWriter that downloaded data should be written to. It will
// either point to *decompressing_file_writer_ or *delta_performer_.
FileWriter* writer_;
diff --git a/download_action_unittest.cc b/download_action_unittest.cc
index 9ae9522..3e8aabd 100644
--- a/download_action_unittest.cc
+++ b/download_action_unittest.cc
@@ -4,13 +4,16 @@
#include <string>
#include <vector>
+
#include <glib.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+
#include "update_engine/action_pipe.h"
#include "update_engine/download_action.h"
#include "update_engine/mock_http_fetcher.h"
#include "update_engine/omaha_hash_calculator.h"
+#include "update_engine/prefs_mock.h"
#include "update_engine/test_utils.h"
#include "update_engine/utils.h"
@@ -106,8 +109,9 @@
"");
ObjectFeederAction<InstallPlan> feeder_action;
feeder_action.set_obj(install_plan);
- DownloadAction download_action(new MockHttpFetcher(&data[0],
- data.size()));
+ PrefsMock prefs;
+ DownloadAction download_action(&prefs, new MockHttpFetcher(&data[0],
+ data.size()));
download_action.SetTestFileWriter(&writer);
BondActions(&feeder_action, &download_action);
DownloadActionDelegateMock download_delegate;
@@ -225,7 +229,9 @@
ObjectFeederAction<InstallPlan> feeder_action;
InstallPlan install_plan(true, "", 0, "", temp_file.GetPath(), "");
feeder_action.set_obj(install_plan);
- DownloadAction download_action(new MockHttpFetcher(&data[0], data.size()));
+ PrefsMock prefs;
+ DownloadAction download_action(&prefs,
+ new MockHttpFetcher(&data[0], data.size()));
download_action.SetTestFileWriter(&writer);
DownloadActionDelegateMock download_delegate;
if (use_download_delegate) {
@@ -327,7 +333,8 @@
"/dev/null");
ObjectFeederAction<InstallPlan> feeder_action;
feeder_action.set_obj(install_plan);
- DownloadAction download_action(new MockHttpFetcher("x", 1));
+ PrefsMock prefs;
+ DownloadAction download_action(&prefs, new MockHttpFetcher("x", 1));
download_action.SetTestFileWriter(&writer);
DownloadActionTestAction test_action;
@@ -360,7 +367,8 @@
InstallPlan install_plan(true, "", 0, "", path, "");
ObjectFeederAction<InstallPlan> feeder_action;
feeder_action.set_obj(install_plan);
- DownloadAction download_action(new MockHttpFetcher("x", 1));
+ PrefsMock prefs;
+ DownloadAction download_action(&prefs, new MockHttpFetcher("x", 1));
download_action.SetTestFileWriter(&writer);
BondActions(&feeder_action, &download_action);
diff --git a/generate_delta_main.cc b/generate_delta_main.cc
index 81227e4..ab05c77 100644
--- a/generate_delta_main.cc
+++ b/generate_delta_main.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -7,15 +7,19 @@
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
+
#include <set>
#include <string>
#include <vector>
+
+#include <base/command_line.h>
+#include <base/logging.h>
#include <gflags/gflags.h>
#include <glib.h>
-#include "base/command_line.h"
-#include "base/logging.h"
+
#include "update_engine/delta_diff_generator.h"
#include "update_engine/delta_performer.h"
+#include "update_engine/prefs.h"
#include "update_engine/subprocess.h"
#include "update_engine/update_metadata.pb.h"
#include "update_engine/utils.h"
@@ -32,6 +36,8 @@
DEFINE_string(private_key, "", "Path to private key in .pem format");
DEFINE_string(apply_delta, "",
"If set, apply delta over old_image. (For debugging.)");
+DEFINE_string(prefs_dir, "/tmp/update_engine_prefs",
+ "Preferences directory, used with apply_delta.");
// This file contains a simple program that takes an old path, a new path,
// and an output file as arguments and the path to an output file and
@@ -64,7 +70,11 @@
if (FLAGS_old_image.empty()) {
LOG(FATAL) << "Must pass --old_image with --apply_delta.";
}
- DeltaPerformer performer;
+ Prefs prefs;
+ LOG(INFO) << "Setting up preferences under: " << FLAGS_prefs_dir;
+ LOG_IF(ERROR, !prefs.Init(FilePath(FLAGS_prefs_dir)))
+ << "Failed to initialize preferences.";
+ DeltaPerformer performer(&prefs);
CHECK_EQ(performer.Open(FLAGS_old_image.c_str(), 0, 0), 0);
CHECK(performer.OpenKernel(FLAGS_old_kernel.c_str()));
vector<char> buf(1024 * 1024);
@@ -92,7 +102,7 @@
if ((!IsDir(FLAGS_old_dir.c_str())) || (!IsDir(FLAGS_new_dir.c_str()))) {
LOG(FATAL) << "old_dir or new_dir not directory";
}
-
+
DeltaDiffGenerator::GenerateDeltaUpdateFile(FLAGS_old_dir,
FLAGS_old_image,
FLAGS_new_dir,
diff --git a/omaha_hash_calculator.cc b/omaha_hash_calculator.cc
index 0df83bc..bc71476 100644
--- a/omaha_hash_calculator.cc
+++ b/omaha_hash_calculator.cc
@@ -97,4 +97,14 @@
return OmahaHashOfBytes(&data[0], data.size());
}
+string OmahaHashCalculator::GetContext() const {
+ return string(reinterpret_cast<const char*>(&ctx_), sizeof(ctx_));
+}
+
+bool OmahaHashCalculator::SetContext(const std::string& context) {
+ TEST_AND_RETURN_FALSE(context.size() == sizeof(ctx_));
+ memcpy(&ctx_, context.data(), sizeof(ctx_));
+ return true;
+}
+
} // namespace chromeos_update_engine
diff --git a/omaha_hash_calculator.h b/omaha_hash_calculator.h
index 52ac1b7..7aa37e4 100644
--- a/omaha_hash_calculator.h
+++ b/omaha_hash_calculator.h
@@ -11,11 +11,11 @@
#include "base/basictypes.h"
#include "base/logging.h"
-// Omaha uses base64 encoded SHA-1 as the hash. This class provides a simple
+// Omaha uses base64 encoded SHA-256 as the hash. This class provides a simple
// wrapper around OpenSSL providing such a formatted hash of data passed in.
-// The methods of this class must be called in a very specific order:
-// First the ctor (of course), then 0 or more calls to Update(), then
-// Finalize(), then 0 or more calls to hash().
+// The methods of this class must be called in a very specific order: First the
+// ctor (of course), then 0 or more calls to Update(), then Finalize(), then 0
+// or more calls to hash().
namespace chromeos_update_engine {
@@ -45,6 +45,15 @@
return raw_hash_;
}
+ // Gets the current hash context. Note that the string will contain binary
+ // data (including \0 characters).
+ std::string GetContext() const;
+
+ // Sets the current hash context. |context| must the string returned by a
+ // previous OmahaHashCalculator::GetContext method call. Returns true on
+ // success, and false otherwise.
+ bool SetContext(const std::string& context);
+
static bool RawHashOfData(const std::vector<char>& data,
std::vector<char>* out_hash);
diff --git a/omaha_hash_calculator_unittest.cc b/omaha_hash_calculator_unittest.cc
index 449cb90..597b21f 100644
--- a/omaha_hash_calculator_unittest.cc
+++ b/omaha_hash_calculator_unittest.cc
@@ -51,6 +51,18 @@
EXPECT_TRUE(raw_hash == calc.raw_hash());
}
+TEST(OmahaHashCalculatorTest, ContextTest) {
+ OmahaHashCalculator calc;
+ calc.Update("h", 1);
+ OmahaHashCalculator calc_next;
+ calc_next.SetContext(calc.GetContext());
+ calc_next.Update("i", 1);
+ calc_next.Finalize();
+ // Generated by running this on a linux shell:
+ // $ echo -n hi | openssl dgst -sha256 -binary | openssl base64
+ EXPECT_EQ("j0NDRmSPa5bfid2pAcUXaxCm2Dlh3TwayItZstwyeqQ=", calc_next.hash());
+}
+
TEST(OmahaHashCalculatorTest, BigTest) {
OmahaHashCalculator calc;
diff --git a/omaha_response_handler_action.cc b/omaha_response_handler_action.cc
index 75776ab..cdcf735 100644
--- a/omaha_response_handler_action.cc
+++ b/omaha_response_handler_action.cc
@@ -1,22 +1,20 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium OS 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 "update_engine/omaha_response_handler_action.h"
+
#include <string>
+
+#include <base/logging.h>
+
+#include "update_engine/prefs_interface.h"
#include "update_engine/utils.h"
using std::string;
namespace chromeos_update_engine {
-namespace {
-// If the file part of the download URL contains kFullUpdateTag, then and
-// only then do we assume it's a full update. Otherwise, we assume it's a
-// delta update.
-const string kFullUpdateTag = "_FULL_";
-} // namespace
-
void OmahaResponseHandlerAction::PerformAction() {
CHECK(HasInputObject());
ScopedActionCompleter completer(processor_, this);
@@ -29,6 +27,12 @@
install_plan_.download_url = response.codebase;
install_plan_.size = response.size;
install_plan_.download_hash = response.hash;
+ // TODO(petkov): Decide here if this is going to be a regular update or
+ // resume-after-boot. This should also set the number of ops performed so far
+ // to invalid if no need to resume.
+ LOG_IF(WARNING, !prefs_->SetString(kPrefsUpdateCheckResponseHash,
+ response.hash))
+ << "Unable to save the update check response hash.";
TEST_AND_RETURN(GetInstallDev(
(!boot_device_.empty() ? boot_device_ : utils::BootDevice()),
&install_plan_.install_path));
diff --git a/omaha_response_handler_action.h b/omaha_response_handler_action.h
index b5feabd..2845df5 100644
--- a/omaha_response_handler_action.h
+++ b/omaha_response_handler_action.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -16,6 +16,7 @@
namespace chromeos_update_engine {
class OmahaResponseHandlerAction;
+class PrefsInterface;
template<>
class ActionTraits<OmahaResponseHandlerAction> {
@@ -26,7 +27,9 @@
class OmahaResponseHandlerAction : public Action<OmahaResponseHandlerAction> {
public:
- OmahaResponseHandlerAction() : got_no_update_response_(false) {}
+ OmahaResponseHandlerAction(PrefsInterface* prefs)
+ : prefs_(prefs),
+ got_no_update_response_(false) {}
typedef ActionTraits<OmahaResponseHandlerAction>::InputObjectType
InputObjectType;
typedef ActionTraits<OmahaResponseHandlerAction>::OutputObjectType
@@ -57,6 +60,9 @@
static bool GetInstallDev(const std::string& boot_dev,
std::string* install_dev);
+ // Update Engine preference store.
+ PrefsInterface* prefs_;
+
// set to non-empty in unit tests
std::string boot_device_;
diff --git a/omaha_response_handler_action_unittest.cc b/omaha_response_handler_action_unittest.cc
index 90cbed9..10be7d6 100644
--- a/omaha_response_handler_action_unittest.cc
+++ b/omaha_response_handler_action_unittest.cc
@@ -1,14 +1,18 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium OS 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 <string>
+
#include <gtest/gtest.h>
+
#include "update_engine/omaha_response_handler_action.h"
+#include "update_engine/prefs_mock.h"
#include "update_engine/test_utils.h"
#include "update_engine/utils.h"
using std::string;
+using testing::Return;
namespace chromeos_update_engine {
@@ -60,7 +64,12 @@
ObjectFeederAction<OmahaResponse> feeder_action;
feeder_action.set_obj(in);
- OmahaResponseHandlerAction response_handler_action;
+ PrefsMock prefs;
+ if (in.update_exists) {
+ EXPECT_CALL(prefs, SetString(kPrefsUpdateCheckResponseHash, in.hash))
+ .WillOnce(Return(true));
+ }
+ OmahaResponseHandlerAction response_handler_action(&prefs);
response_handler_action.set_boot_device(boot_dev);
BondActions(&feeder_action, &response_handler_action);
ObjectCollectorAction<InstallPlan> collector_action;
diff --git a/prefs.cc b/prefs.cc
index 585408c..2de7eea 100644
--- a/prefs.cc
+++ b/prefs.cc
@@ -18,6 +18,12 @@
const char kPrefsDeltaUpdateFailures[] = "delta-update-failures";
const char kPrefsLastActivePingDay[] = "last-active-ping-day";
const char kPrefsLastRollCallPingDay[] = "last-roll-call-ping-day";
+const char kPrefsManifestMetadataSize[] = "manifest-metadata-size";
+const char kPrefsUpdateCheckResponseHash[] = "update-check-response-hash";
+const char kPrefsUpdateStateNextDataOffset[] = "update-state-next-data-offset";
+const char kPrefsUpdateStateNextOperation[] = "update-state-next-operation";
+const char kPrefsUpdateStateSignedSHA256Context[] =
+ "update-state-signed-sha-256-context";
bool Prefs::Init(const FilePath& prefs_dir) {
prefs_dir_ = prefs_dir;
@@ -25,16 +31,13 @@
}
bool Prefs::GetString(const string& key, string* value) {
- LOG(INFO) << "Getting key \"" << key << "\"";
FilePath filename;
TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
TEST_AND_RETURN_FALSE(file_util::ReadFileToString(filename, value));
- LOG(INFO) << "Key \"" << key << "\" value \"" << *value << "\"";
return true;
}
bool Prefs::SetString(const std::string& key, const std::string& value) {
- LOG(INFO) << "Setting key \"" << key << "\" value \"" << value << "\"";
FilePath filename;
TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
TEST_AND_RETURN_FALSE(file_util::CreateDirectory(filename.DirName()));
diff --git a/prefs_interface.h b/prefs_interface.h
index 724651e..a9b20a5 100644
--- a/prefs_interface.h
+++ b/prefs_interface.h
@@ -12,6 +12,11 @@
extern const char kPrefsDeltaUpdateFailures[];
extern const char kPrefsLastActivePingDay[];
extern const char kPrefsLastRollCallPingDay[];
+extern const char kPrefsManifestMetadataSize[];
+extern const char kPrefsUpdateCheckResponseHash[];
+extern const char kPrefsUpdateStateNextDataOffset[];
+extern const char kPrefsUpdateStateNextOperation[];
+extern const char kPrefsUpdateStateSignedSHA256Context[];
// The prefs interface allows access to a persistent preferences
// store. The two reasons for providing this as an interface are
diff --git a/update_attempter.cc b/update_attempter.cc
index a9c9261..2db91a6 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -141,7 +141,7 @@
NULL,
new LibcurlHttpFetcher));
shared_ptr<OmahaResponseHandlerAction> response_handler_action(
- new OmahaResponseHandlerAction);
+ new OmahaResponseHandlerAction(prefs_));
shared_ptr<FilesystemCopierAction> filesystem_copier_action(
new FilesystemCopierAction(false));
shared_ptr<FilesystemCopierAction> kernel_filesystem_copier_action(
@@ -153,7 +153,7 @@
OmahaEvent::kTypeUpdateDownloadStarted),
new LibcurlHttpFetcher));
shared_ptr<DownloadAction> download_action(
- new DownloadAction(new LibcurlHttpFetcher));
+ new DownloadAction(prefs_, new LibcurlHttpFetcher));
shared_ptr<OmahaRequestAction> download_finished_action(
new OmahaRequestAction(prefs_,
omaha_request_params_,
diff --git a/update_attempter_unittest.cc b/update_attempter_unittest.cc
index 3c802b7..b8d85a1 100644
--- a/update_attempter_unittest.cc
+++ b/update_attempter_unittest.cc
@@ -78,7 +78,7 @@
OmahaRequestAction omaha_request_action(NULL, params, NULL, NULL);
EXPECT_EQ(kActionCodeOmahaRequestError,
GetErrorCodeForAction(&omaha_request_action, kActionCodeError));
- OmahaResponseHandlerAction omaha_response_handler_action;
+ OmahaResponseHandlerAction omaha_response_handler_action(&prefs_);
EXPECT_EQ(kActionCodeOmahaResponseHandlerError,
GetErrorCodeForAction(&omaha_response_handler_action,
kActionCodeError));