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

Unified Diff: chrome/utility/image_writer/image_writer.cc

Issue 61643015: Adds imageWriterPrivate support for Windows (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixes test cleanup ordering for Chrome OS. Created 6 years, 10 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
« no previous file with comments | « chrome/utility/image_writer/image_writer.h ('k') | chrome/utility/image_writer/image_writer_handler.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/utility/image_writer/image_writer.cc
diff --git a/chrome/utility/image_writer/image_writer.cc b/chrome/utility/image_writer/image_writer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..710e1836a3d297abf8ea86fa2a9c53cfceaec263
--- /dev/null
+++ b/chrome/utility/image_writer/image_writer.cc
@@ -0,0 +1,244 @@
+// Copyright 2014 The Chromium 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 "base/platform_file.h"
+#include "chrome/utility/image_writer/error_messages.h"
+#include "chrome/utility/image_writer/image_writer.h"
+#include "chrome/utility/image_writer/image_writer_handler.h"
+#include "content/public/utility/utility_thread.h"
+
+namespace image_writer {
+
+// Since block devices like large sequential access and IPC is expensive we're
+// doing work in 1MB chunks.
+const int kBurningBlockSize = 1 << 20;
+
+ImageWriter::ImageWriter(ImageWriterHandler* handler)
+ : image_file_(base::kInvalidPlatformFileValue),
+ device_file_(base::kInvalidPlatformFileValue),
+ bytes_processed_(0),
+ handler_(handler) {}
+
+ImageWriter::~ImageWriter() { CleanUp(); }
+
+void ImageWriter::Write(const base::FilePath& image_path,
+ const base::FilePath& device_path) {
+ if (IsRunning()) {
+ handler_->SendFailed(error::kOperationAlreadyInProgress);
+ return;
+ }
+
+ image_path_ = image_path;
+ device_path_ = device_path;
+ bytes_processed_ = 0;
+
+ base::PlatformFileError error;
+
+ image_file_ = base::CreatePlatformFile(
+ image_path_,
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
+ NULL,
+ &error);
+
+ if (error != base::PLATFORM_FILE_OK) {
+ DLOG(ERROR) << "Unable to open file for read: " << image_path_.value();
+ Error(error::kOpenImage);
+ return;
+ }
+
+#if defined(OS_WIN)
+ // Windows requires that device files be opened with FILE_FLAG_NO_BUFFERING
+ // and FILE_FLAG_WRITE_THROUGH. These two flags are not part of
+ // PlatformFile::CreatePlatformFile.
+ device_file_ = CreateFile(device_path.value().c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
+ INVALID_HANDLE_VALUE);
+
+ if (device_file_ == base::kInvalidPlatformFileValue) {
+ Error(error::kOpenDevice);
+ return;
+ }
+#else
+ device_file_ = base::CreatePlatformFile(
+ device_path_,
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
+ NULL,
+ &error);
+
+ if (error != base::PLATFORM_FILE_OK) {
+ DLOG(ERROR) << "Unable to open file for write(" << error
+ << "): " << device_path_.value();
+ Error(error::kOpenDevice);
+ return;
+ }
+#endif
+
+ PostProgress(0);
+
+ PostTask(base::Bind(&ImageWriter::WriteChunk, AsWeakPtr()));
+}
+
+void ImageWriter::Verify(const base::FilePath& image_path,
+ const base::FilePath& device_path) {
+ if (IsRunning()) {
+ handler_->SendFailed(error::kOperationAlreadyInProgress);
+ return;
+ }
+
+ image_path_ = image_path;
+ device_path_ = device_path;
+ bytes_processed_ = 0;
+
+ base::PlatformFileError error;
+
+ image_file_ = base::CreatePlatformFile(
+ image_path_,
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
+ NULL,
+ &error);
+
+ if (error != base::PLATFORM_FILE_OK) {
+ DLOG(ERROR) << "Unable to open file for read: " << image_path_.value();
+ Error(error::kOpenImage);
+ return;
+ }
+
+ device_file_ = base::CreatePlatformFile(
+ device_path_,
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
+ NULL,
+ &error);
+
+ if (error != base::PLATFORM_FILE_OK) {
+ DLOG(ERROR) << "Unable to open file for read: " << device_path_.value();
+ Error(error::kOpenDevice);
+ return;
+ }
+
+ PostProgress(0);
+
+ PostTask(base::Bind(&ImageWriter::VerifyChunk, AsWeakPtr()));
+}
+
+void ImageWriter::Cancel() {
+ CleanUp();
+ handler_->SendCancelled();
+}
+
+bool ImageWriter::IsRunning() const {
+ return image_file_ != base::kInvalidPlatformFileValue ||
+ device_file_ != base::kInvalidPlatformFileValue;
+}
+
+void ImageWriter::PostTask(const base::Closure& task) {
+ base::MessageLoop::current()->PostTask(FROM_HERE, task);
+}
+
+void ImageWriter::PostProgress(int64 progress) {
+ handler_->SendProgress(progress);
+}
+
+void ImageWriter::Error(const std::string& message) {
+ CleanUp();
+ handler_->SendFailed(message);
+}
+
+void ImageWriter::WriteChunk() {
+ if (!IsRunning()) {
+ return;
+ }
+
+ scoped_ptr<char[]> buffer(new char[kBurningBlockSize]);
+ base::PlatformFileInfo info;
+
+ int bytes_read = base::ReadPlatformFile(
+ image_file_, bytes_processed_, buffer.get(), kBurningBlockSize);
+
+ if (bytes_read > 0) {
+ // Always attempt to write a whole block, as Windows requires 512-byte
+ // aligned writes to devices.
+ int bytes_written = base::WritePlatformFile(
+ device_file_, bytes_processed_, buffer.get(), kBurningBlockSize);
+
+ if (bytes_written < bytes_read) {
+ Error(error::kWriteImage);
+ return;
+ }
+
+ bytes_processed_ += bytes_read;
+ PostProgress(bytes_processed_);
+
+ PostTask(base::Bind(&ImageWriter::WriteChunk, AsWeakPtr()));
+ } else if (bytes_read == 0) {
+ // End of file.
+ base::FlushPlatformFile(device_file_);
+ CleanUp();
+ handler_->SendSucceeded();
+ } else {
+ // Unable to read entire file.
+ Error(error::kReadImage);
+ }
+}
+
+void ImageWriter::VerifyChunk() {
+ if (!IsRunning()) {
+ return;
+ }
+
+ scoped_ptr<char[]> image_buffer(new char[kBurningBlockSize]);
+ scoped_ptr<char[]> device_buffer(new char[kBurningBlockSize]);
+
+ int bytes_read = base::ReadPlatformFile(
+ image_file_, bytes_processed_, image_buffer.get(), kBurningBlockSize);
+
+ if (bytes_read > 0) {
+ if (base::ReadPlatformFile(device_file_,
+ bytes_processed_,
+ device_buffer.get(),
+ kBurningBlockSize) < 0) {
+ LOG(ERROR) << "Failed to read " << kBurningBlockSize << " bytes of "
+ << "device at offset " << bytes_processed_;
+ Error(error::kReadDevice);
+ return;
+ }
+
+ if (memcmp(image_buffer.get(), device_buffer.get(), bytes_read) != 0) {
+ LOG(ERROR) << "Write verification failed when comparing " << bytes_read
+ << " bytes at " << bytes_processed_;
+ Error(error::kVerificationFailed);
+ return;
+ }
+
+ bytes_processed_ += bytes_read;
+ PostProgress(bytes_processed_);
+
+ PostTask(base::Bind(&ImageWriter::VerifyChunk, AsWeakPtr()));
+ } else if (bytes_read == 0) {
+ // End of file.
+ CleanUp();
+ handler_->SendSucceeded();
+ } else {
+ // Unable to read entire file.
+ LOG(ERROR) << "Failed to read " << kBurningBlockSize << " bytes of image "
+ << "at offset " << bytes_processed_;
+ Error(error::kReadImage);
+ }
+}
+
+void ImageWriter::CleanUp() {
+ if (image_file_ != base::kInvalidPlatformFileValue) {
+ base::ClosePlatformFile(image_file_);
+ image_file_ = base::kInvalidPlatformFileValue;
+ }
+ if (device_file_ != base::kInvalidPlatformFileValue) {
+ base::ClosePlatformFile(device_file_);
+ device_file_ = base::kInvalidPlatformFileValue;
+ }
+}
+
+} // namespace image_writer
« no previous file with comments | « chrome/utility/image_writer/image_writer.h ('k') | chrome/utility/image_writer/image_writer_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698