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..a24a3d78a96d14e0534ca7ed966ba9a6ea8ee8fa 100644 |
--- a/content/browser/download/base_file.cc |
+++ b/content/browser/download/base_file.cc |
@@ -42,9 +42,10 @@ DownloadInterruptReason BaseFile::Initialize( |
const base::FilePath& full_path, |
const base::FilePath& default_directory, |
base::File file, |
- int64_t bytes_so_far, |
+ int64_t offset, |
const std::string& hash_so_far, |
- std::unique_ptr<crypto::SecureHash> hash_state) { |
+ std::unique_ptr<crypto::SecureHash> hash_state, |
+ AccessMode access_mode) { |
DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
DCHECK(!detached_); |
@@ -68,15 +69,18 @@ DownloadInterruptReason BaseFile::Initialize( |
full_path_ = full_path; |
} |
- bytes_so_far_ = bytes_so_far; |
+ access_mode_ = access_mode; |
+ offset_ = offset; |
+ if (access_mode_ == EXCLUSIVE) |
+ bytes_so_far_ = offset; |
secure_hash_ = std::move(hash_state); |
file_ = std::move(file); |
return Open(hash_so_far); |
} |
-DownloadInterruptReason BaseFile::AppendDataToFile(const char* data, |
- size_t data_len) { |
+DownloadInterruptReason BaseFile::WriteDataToFile(const char* data, |
+ size_t data_len) { |
DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
DCHECK(!detached_); |
@@ -112,6 +116,7 @@ DownloadInterruptReason BaseFile::AppendDataToFile(const char* data, |
DCHECK_LE(write_size, len); |
len -= write_size; |
current_data += write_size; |
+ offset_ += write_size; |
bytes_so_far_ += write_size; |
} |
net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN, |
@@ -195,17 +200,18 @@ std::string BaseFile::DebugString() const { |
"{ " |
" full_path_ = \"%" PRFilePath |
"\"" |
- " bytes_so_far_ = %" PRId64 " detached_ = %c }", |
- full_path_.value().c_str(), |
- bytes_so_far_, |
- detached_ ? 'T' : 'F'); |
+ " offset_ = %" PRId64 " detached_ = %c }", |
+ full_path_.value().c_str(), offset_, detached_ ? 'T' : 'F'); |
} |
DownloadInterruptReason BaseFile::CalculatePartialHash( |
const std::string& hash_to_expect) { |
secure_hash_ = crypto::SecureHash::Create(crypto::SecureHash::SHA256); |
- if (bytes_so_far_ == 0) |
+ if (access_mode_ == SHARED) |
+ return DOWNLOAD_INTERRUPT_REASON_NONE; |
+ |
+ if (offset_ == 0) |
return DOWNLOAD_INTERRUPT_REASON_NONE; |
if (file_.Seek(base::File::FROM_BEGIN, 0) != 0) |
@@ -220,17 +226,16 @@ DownloadInterruptReason BaseFile::CalculatePartialHash( |
// The size of the buffer is: |
// - at least kMinBufferSize so that we can use it to hold the hash as well. |
// - at most kMaxBufferSize so that there's a reasonable bound. |
- // - not larger than |bytes_so_far_| unless bytes_so_far_ is less than the |
- // hash size. |
+ // - not larger than |offset_| unless |offset_| is less than the hash size. |
std::vector<char> buffer(std::max<int64_t>( |
- kMinBufferSize, std::min<int64_t>(kMaxBufferSize, bytes_so_far_))); |
+ kMinBufferSize, std::min<int64_t>(kMaxBufferSize, offset_))); |
int64_t current_position = 0; |
- while (current_position < bytes_so_far_) { |
+ while (current_position < offset_) { |
// While std::min needs to work with int64_t, the result is always at most |
// kMaxBufferSize, which fits on an int. |
int bytes_to_read = |
- std::min<int64_t>(buffer.size(), bytes_so_far_ - current_position); |
+ std::min<int64_t>(buffer.size(), offset_ - current_position); |
int length = file_.ReadAtCurrentPos(&buffer.front(), bytes_to_read); |
if (length == -1) { |
return LogInterruptReason("Reading partial file", |
@@ -245,7 +250,7 @@ DownloadInterruptReason BaseFile::CalculatePartialHash( |
current_position += length; |
} |
- if (current_position != bytes_so_far_) { |
+ if (current_position != offset_) { |
return LogInterruptReason( |
"Verifying prefix hash", 0, DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT); |
} |
@@ -286,7 +291,16 @@ DownloadInterruptReason BaseFile::Open(const std::string& hash_so_far) { |
net_log_.BeginEvent( |
net::NetLogEventType::DOWNLOAD_FILE_OPENED, |
- base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_)); |
+ base::Bind(&FileOpenedNetLogCallback, &full_path_, offset_)); |
+ |
+ if (access_mode_ == SHARED) { |
+ if (file_.Seek(base::File::FROM_BEGIN, offset_) < 0) { |
+ logging::SystemErrorCode error = logging::GetLastSystemErrorCode(); |
+ ClearFile(); |
+ return LogSystemError("Seeking to end", error); |
+ } |
+ return DOWNLOAD_INTERRUPT_REASON_NONE; |
+ } |
if (!secure_hash_) { |
DownloadInterruptReason reason = CalculatePartialHash(hash_so_far); |
@@ -301,17 +315,17 @@ DownloadInterruptReason BaseFile::Open(const std::string& hash_so_far) { |
logging::SystemErrorCode error = logging::GetLastSystemErrorCode(); |
ClearFile(); |
return LogSystemError("Seeking to end", error); |
- } else if (file_size > bytes_so_far_) { |
+ } else if (file_size > offset_) { |
// The file is larger than we expected. |
// This is OK, as long as we don't use the extra. |
// Truncate the file. |
- if (!file_.SetLength(bytes_so_far_) || |
- file_.Seek(base::File::FROM_BEGIN, bytes_so_far_) != bytes_so_far_) { |
+ if (!file_.SetLength(offset_) || |
+ file_.Seek(base::File::FROM_BEGIN, offset_) != offset_) { |
logging::SystemErrorCode error = logging::GetLastSystemErrorCode(); |
ClearFile(); |
return LogSystemError("Truncating to last known offset", error); |
} |
- } else if (file_size < bytes_so_far_) { |
+ } else if (file_size < offset_) { |
// The file is shorter than we expected. Our hashes won't be valid. |
ClearFile(); |
return LogInterruptReason("Unable to seek to last written point", 0, |