| Index: content/browser/download/base_file.cc
|
| diff --git a/content/browser/download/base_file.cc b/content/browser/download/base_file.cc
|
| index 59dfa839cd51dca2373f2b6204d5a64c418fb41c..b95ef97ed98c372ddddcb82f12144b11418735ee 100644
|
| --- a/content/browser/download/base_file.cc
|
| +++ b/content/browser/download/base_file.cc
|
| @@ -44,7 +44,8 @@ DownloadInterruptReason BaseFile::Initialize(
|
| base::File file,
|
| int64_t bytes_so_far,
|
| const std::string& hash_so_far,
|
| - std::unique_ptr<crypto::SecureHash> hash_state) {
|
| + std::unique_ptr<crypto::SecureHash> hash_state,
|
| + bool is_sparse_file) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::FILE);
|
| DCHECK(!detached_);
|
|
|
| @@ -70,6 +71,8 @@ DownloadInterruptReason BaseFile::Initialize(
|
|
|
| bytes_so_far_ = bytes_so_far;
|
| secure_hash_ = std::move(hash_state);
|
| + is_sparse_file_ = is_sparse_file;
|
| + DCHECK(!is_sparse_file_ || !secure_hash_);
|
| file_ = std::move(file);
|
|
|
| return Open(hash_so_far);
|
| @@ -77,9 +80,13 @@ DownloadInterruptReason BaseFile::Initialize(
|
|
|
| DownloadInterruptReason BaseFile::AppendDataToFile(const char* data,
|
| size_t data_len) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::FILE);
|
| - DCHECK(!detached_);
|
| + DCHECK(!is_sparse_file_);
|
| + return WriteDataToFile(bytes_so_far_, data, data_len);
|
| +}
|
|
|
| +DownloadInterruptReason BaseFile::WriteDataToFile(int64_t offset,
|
| + const char* data,
|
| + size_t data_len) {
|
| // NOTE(benwells): The above DCHECK won't be present in release builds,
|
| // so we log any occurences to see how common this error is in the wild.
|
| if (detached_)
|
| @@ -93,27 +100,16 @@ DownloadInterruptReason BaseFile::AppendDataToFile(const char* data,
|
| if (data_len == 0)
|
| return DOWNLOAD_INTERRUPT_REASON_NONE;
|
|
|
| - // The Write call below is not guaranteed to write all the data.
|
| - size_t write_count = 0;
|
| - size_t len = data_len;
|
| - const char* current_data = data;
|
| net_log_.BeginEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN);
|
| - while (len > 0) {
|
| - write_count++;
|
| - int write_result = file_.WriteAtCurrentPos(current_data, len);
|
| - DCHECK_NE(0, write_result);
|
| -
|
| - // Report errors on file writes.
|
| - if (write_result < 0)
|
| - return LogSystemError("Write", logging::GetLastSystemErrorCode());
|
| -
|
| - // Update status.
|
| - size_t write_size = static_cast<size_t>(write_result);
|
| - DCHECK_LE(write_size, len);
|
| - len -= write_size;
|
| - current_data += write_size;
|
| - bytes_so_far_ += write_size;
|
| - }
|
| + int write_result = file_.Write(offset, data, data_len);
|
| + DCHECK_NE(0, write_result);
|
| +
|
| + // Report errors on file writes.
|
| + if (write_result < 0)
|
| + return LogSystemError("Write", logging::GetLastSystemErrorCode());
|
| +
|
| + DCHECK_EQ(static_cast<size_t>(write_result), data_len);
|
| + bytes_so_far_ += data_len;
|
| net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN,
|
| net::NetLog::Int64Callback("bytes", data_len));
|
|
|
| @@ -186,6 +182,10 @@ void BaseFile::Cancel() {
|
|
|
| std::unique_ptr<crypto::SecureHash> BaseFile::Finish() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::FILE);
|
| +
|
| + // TODO(qinmin): verify that all the holes have been filled.
|
| + if (is_sparse_file_)
|
| + CalculatePartialHash(std::string());
|
| Close();
|
| return std::move(secure_hash_);
|
| }
|
| @@ -288,6 +288,16 @@ DownloadInterruptReason BaseFile::Open(const std::string& hash_so_far) {
|
| net::NetLogEventType::DOWNLOAD_FILE_OPENED,
|
| base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_));
|
|
|
| + // For sparse file, skip hash validation.
|
| + if (is_sparse_file_) {
|
| + if (file_.GetLength() < bytes_so_far_) {
|
| + ClearFile();
|
| + return LogInterruptReason("File has fewer written bytes than expected", 0,
|
| + DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT);
|
| + }
|
| + return DOWNLOAD_INTERRUPT_REASON_NONE;
|
| + }
|
| +
|
| if (!secure_hash_) {
|
| DownloadInterruptReason reason = CalculatePartialHash(hash_so_far);
|
| if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
|
|
|