Almost there...



git-svn-id: svn://chrome-svn/chromeos/trunk@24 06c00378-0e64-4dae-be16-12b19f9950a1
diff --git a/download_action.cc b/download_action.cc
new file mode 100644
index 0000000..3a039d1
--- /dev/null
+++ b/download_action.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2009 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 <glib.h>
+
+#include "update_engine/action_pipe.h"
+#include "update_engine/download_action.h"
+
+namespace chromeos_update_engine {
+
+DownloadAction::DownloadAction(const std::string& url,
+                               const std::string& output_path,
+                               off_t size, const std::string& hash,
+                               const bool should_decompress,
+                               HttpFetcher* http_fetcher)
+    : size_(size),
+      url_(url),
+      output_path_(output_path),
+      hash_(hash),
+      should_decompress_(should_decompress),
+      writer_(NULL),
+      http_fetcher_(http_fetcher) {}
+
+DownloadAction::~DownloadAction() {}
+
+void DownloadAction::PerformAction() {
+  http_fetcher_->set_delegate(this);
+  CHECK(!writer_);
+  direct_file_writer_.reset(new DirectFileWriter);
+
+  if (should_decompress_) {
+    decompressing_file_writer_.reset(
+        new GzipDecompressingFileWriter(direct_file_writer_.get()));
+    writer_ = decompressing_file_writer_.get();
+  } else {
+    writer_ = direct_file_writer_.get();
+  }
+
+  int rc = writer_->Open(output_path_.c_str(),
+                         O_TRUNC | O_WRONLY | O_CREAT | O_LARGEFILE, 0644);
+  if (rc < 0) {
+    LOG(ERROR) << "Unable to open output file " << output_path_;
+    // report error to processor
+    processor_->ActionComplete(this, false);
+    return;
+  }
+  http_fetcher_->BeginTransfer(url_);
+}
+
+void DownloadAction::TerminateProcessing() {
+  CHECK(writer_);
+  CHECK_EQ(writer_->Close(), 0);
+  writer_ = NULL;
+  http_fetcher_->TerminateTransfer();
+}
+
+void DownloadAction::ReceivedBytes(HttpFetcher *fetcher,
+                                   const char* bytes,
+                                   int length) {
+  int bytes_written = 0;
+  do {
+    CHECK_GT(length, bytes_written);
+    int rc = writer_->Write(bytes + bytes_written, length - bytes_written);
+    // TODO(adlr): handle write error
+    CHECK_GE(rc, 0);
+    bytes_written += rc;
+  } while (length != bytes_written);
+  omaha_hash_calculator_.Update(bytes, length);
+}
+
+void DownloadAction::TransferComplete(HttpFetcher *fetcher, bool successful) {
+  if (writer_) {
+    CHECK_EQ(0, writer_->Close()) << errno;
+    writer_ = NULL;
+  }
+  if (successful) {
+    // Make sure hash is correct
+    omaha_hash_calculator_.Finalize();
+    if (omaha_hash_calculator_.hash() != hash_) {
+      LOG(INFO) << "Download of " << url_ << " failed. Expect hash "
+                << hash_ << " but got hash " << omaha_hash_calculator_.hash();
+      successful = false;
+    }
+  }
+
+  // Write the path to the output pipe if we're successful
+  if (successful && HasOutputPipe())
+    SetOutputObject(output_path_);
+  processor_->ActionComplete(this, successful);
+}
+
+};  // namespace {}